// RUN: %libomp-compile // RUN: env OMP_NUM_THREADS=4 %libomp-run 5 5005 500 1000000000 // It fails using gcc compilers because the gcc compiler does not use any // runtime interface to calculate the iterations for static loop schedule // Hence, the runtime is never involved. // XFAIL: gcc // // This test makes sure that large chunks sizes are handled correctly // including internal runtime calculations which incorporate the chunk size #include #include #include "omp_testsuite.h" #ifndef DEBUG_OUTPUT #define DEBUG_OUTPUT 0 #endif // Used in qsort() to compare integers int compare_ints(const void *v1, const void *v2) { int i1 = *(const int *)v1; int i2 = *(const int *)v2; return i1 - i2; } int main(int argc, char **argv) { int i, j, lb, ub, stride, nthreads, chunk; int num_iters = 0; int counted_iters = 0; int errs = 0; if (argc != 5) { fprintf(stderr, "error: incorrect number of arguments\n"); fprintf(stderr, "usage: %s \n", argv[0]); exit(EXIT_FAILURE); } lb = atoi(argv[1]); ub = atoi(argv[2]); stride = atoi(argv[3]); chunk = atoi(argv[4]); nthreads = omp_get_max_threads(); if (lb >= ub) { fprintf(stderr, "error: lb must be less than ub\n"); exit(EXIT_FAILURE); } if (stride <= 0) { fprintf(stderr, "error: stride must be positive integer\n"); exit(EXIT_FAILURE); } if (chunk <= 0) { fprintf(stderr, "error: chunk must be positive integer\n"); exit(EXIT_FAILURE); } for (i = lb; i < ub; i += stride) num_iters++; // Thread private record of iterations each thread performed int *iters = (int *)malloc(sizeof(int) * nthreads * num_iters); // This will be the list of all iteration performed by every thread int *final_iters = (int *)malloc(sizeof(int) * nthreads * num_iters); for (i = 0; i < nthreads * num_iters; ++i) { iters[i] = -1; final_iters[i] = -1; } #pragma omp parallel num_threads(nthreads) { int j = 0; int *my_iters = iters + omp_get_thread_num() * num_iters; #pragma omp for schedule(static, chunk) for (i = lb; i < ub; i += stride) { #pragma omp atomic counted_iters++; my_iters[j++] = i; } } // Put all iterations into final_iters then sort it from lowest to highest for (i = 0, j = 0; i < nthreads * num_iters; ++i) { if (iters[i] != -1) final_iters[j++] = iters[i]; } if (j != counted_iters) { fprintf(stderr, "error: wrong number of final iterations counted!\n"); exit(EXIT_FAILURE); } qsort(final_iters, j, sizeof(int), compare_ints); // Check for the right number of iterations if (counted_iters != num_iters) { fprintf(stderr, "error: wrong number of iterations executed. Expected %d " "but executed %d\n", num_iters, counted_iters); exit(EXIT_FAILURE); } #if DEBUG_OUTPUT for (i = 0; i < num_iters; ++i) printf("final_iters[%d] = %d\n", i, final_iters[i]); #endif // Check that the iterations performed were correct for (i = lb, j = 0; i < ub; i += stride, ++j) { if (final_iters[j] != i) { fprintf(stderr, "error: iteration j=%d i=%d is incorrect. Expect %d but see %d\n", j, i, i, final_iters[j]); exit(EXIT_FAILURE); } } free(iters); free(final_iters); return EXIT_SUCCESS; }