1// RUN: %libomp-compile
2// RUN: env OMP_NUM_THREADS=4 %libomp-run 5 5005 500 1000000000
3// It fails using gcc compilers because the gcc compiler does not use any
4// runtime interface to calculate the iterations for static loop schedule
5// Hence, the runtime is never involved.
6// XFAIL: gcc
7//
8// This test makes sure that large chunks sizes are handled correctly
9// including internal runtime calculations which incorporate the chunk size
10#include <stdio.h>
11#include <stdlib.h>
12#include "omp_testsuite.h"
13
14#ifndef DEBUG_OUTPUT
15#define DEBUG_OUTPUT 0
16#endif
17
18// Used in qsort() to compare integers
19int compare_ints(const void *v1, const void *v2) {
20 int i1 = *(const int *)v1;
21 int i2 = *(const int *)v2;
22 return i1 - i2;
23}
24
25int main(int argc, char **argv) {
26 int i, j, lb, ub, stride, nthreads, chunk;
27 int num_iters = 0;
28 int counted_iters = 0;
29 int errs = 0;
30 if (argc != 5) {
31 fprintf(stderr, format: "error: incorrect number of arguments\n");
32 fprintf(stderr, format: "usage: %s <lb> <ub> <stride> <chunk>\n", argv[0]);
33 exit(EXIT_FAILURE);
34 }
35 lb = atoi(nptr: argv[1]);
36 ub = atoi(nptr: argv[2]);
37 stride = atoi(nptr: argv[3]);
38 chunk = atoi(nptr: argv[4]);
39 nthreads = omp_get_max_threads();
40 if (lb >= ub) {
41 fprintf(stderr, format: "error: lb must be less than ub\n");
42 exit(EXIT_FAILURE);
43 }
44 if (stride <= 0) {
45 fprintf(stderr, format: "error: stride must be positive integer\n");
46 exit(EXIT_FAILURE);
47 }
48 if (chunk <= 0) {
49 fprintf(stderr, format: "error: chunk must be positive integer\n");
50 exit(EXIT_FAILURE);
51 }
52 for (i = lb; i < ub; i += stride)
53 num_iters++;
54 // Thread private record of iterations each thread performed
55 int *iters = (int *)malloc(size: sizeof(int) * nthreads * num_iters);
56 // This will be the list of all iteration performed by every thread
57 int *final_iters = (int *)malloc(size: sizeof(int) * nthreads * num_iters);
58 for (i = 0; i < nthreads * num_iters; ++i) {
59 iters[i] = -1;
60 final_iters[i] = -1;
61 }
62
63 #pragma omp parallel num_threads(nthreads)
64 {
65 int j = 0;
66 int *my_iters = iters + omp_get_thread_num() * num_iters;
67 #pragma omp for schedule(static, chunk)
68 for (i = lb; i < ub; i += stride) {
69 #pragma omp atomic
70 counted_iters++;
71 my_iters[j++] = i;
72 }
73 }
74
75 // Put all iterations into final_iters then sort it from lowest to highest
76 for (i = 0, j = 0; i < nthreads * num_iters; ++i) {
77 if (iters[i] != -1)
78 final_iters[j++] = iters[i];
79 }
80 if (j != counted_iters) {
81 fprintf(stderr, format: "error: wrong number of final iterations counted!\n");
82 exit(EXIT_FAILURE);
83 }
84 qsort(base: final_iters, nmemb: j, size: sizeof(int), compar: compare_ints);
85
86 // Check for the right number of iterations
87 if (counted_iters != num_iters) {
88 fprintf(stderr, format: "error: wrong number of iterations executed. Expected %d "
89 "but executed %d\n",
90 num_iters, counted_iters);
91 exit(EXIT_FAILURE);
92 }
93
94#if DEBUG_OUTPUT
95 for (i = 0; i < num_iters; ++i)
96 printf("final_iters[%d] = %d\n", i, final_iters[i]);
97#endif
98
99 // Check that the iterations performed were correct
100 for (i = lb, j = 0; i < ub; i += stride, ++j) {
101 if (final_iters[j] != i) {
102 fprintf(stderr,
103 format: "error: iteration j=%d i=%d is incorrect. Expect %d but see %d\n",
104 j, i, i, final_iters[j]);
105 exit(EXIT_FAILURE);
106 }
107 }
108
109 free(ptr: iters);
110 free(ptr: final_iters);
111 return EXIT_SUCCESS;
112}
113

source code of openmp/runtime/test/worksharing/for/omp_for_static_large_chunk.c