File: kmp_taskloop_5.c

package info (click to toggle)
llvm-toolchain-15 1%3A15.0.6-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,554,644 kB
  • sloc: cpp: 5,922,452; ansic: 1,012,136; asm: 674,362; python: 191,568; objc: 73,855; f90: 42,327; lisp: 31,913; pascal: 11,973; javascript: 10,144; sh: 9,421; perl: 7,447; ml: 5,527; awk: 3,523; makefile: 2,520; xml: 885; cs: 573; fortran: 567
file content (167 lines) | stat: -rw-r--r-- 4,351 bytes parent folder | download | duplicates (19)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// RUN: %libomp-compile-and-run
// RUN: %libomp-compile && env KMP_TASKLOOP_MIN_TASKS=1 %libomp-run

#include <stdio.h>
#include <omp.h>
#include "omp_my_sleep.h"

#define N 4
#define ST 3
#define UB 118
#define LB 0

// globals
int counter;
int task_count;

// Compiler-generated code (emulation)
typedef struct ident {
  void* dummy;
} ident_t;

typedef struct shar {
  int *pcounter;
  int *pj;
  int *ptask_count;
} *pshareds;

typedef struct task {
  pshareds shareds;
  int(* routine)(int,struct task*);
  int part_id;
  unsigned long long lb; // library always uses ULONG
  unsigned long long ub;
  int st;
  int last;
  int i;
  int j;
  int th;
} *ptask, kmp_task_t;

typedef int(* task_entry_t)( int, ptask );

void
__task_dup_entry(ptask task_dst, ptask task_src, int lastpriv)
{
// setup lastprivate flag
  task_dst->last = lastpriv;
// could be constructor calls here...
}

// OpenMP RTL interfaces
typedef unsigned long long kmp_uint64;
typedef long long kmp_int64;

#ifdef __cplusplus
extern "C" {
#endif
void
__kmpc_taskloop_5(ident_t *loc, int gtid, kmp_task_t *task, int if_val,
                  kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st,
                  int nogroup, int sched, kmp_int64 grainsize, int modifier,
                  void *task_dup);
ptask
__kmpc_omp_task_alloc(ident_t *loc, int gtid, int flags,
                      size_t sizeof_kmp_task_t, size_t sizeof_shareds,
                      task_entry_t task_entry);
void __kmpc_atomic_fixed4_add(void *id_ref, int gtid, int * lhs, int rhs);
int  __kmpc_global_thread_num(void *id_ref);
#ifdef __cplusplus
}
#endif

// User's code
int task_entry(int gtid, ptask task)
{
  pshareds pshar = task->shareds;
  __kmpc_atomic_fixed4_add(NULL, gtid, pshar->ptask_count, 1);

  for (task->i = task->lb; task->i <= (int)task->ub; task->i += task->st) {
    task->th = omp_get_thread_num();
    __kmpc_atomic_fixed4_add(NULL,gtid,pshar->pcounter,1);
    task->j = task->i;
  }
  my_sleep( 0.1 ); // sleep 100 ms in order to allow other threads to steal tasks
  if (task->last) {
    *(pshar->pj) = task->j; // lastprivate
  }
  return 0;
}

void task_loop(int sched_type, int sched_val, int modifier)
{
  int i, j, gtid = __kmpc_global_thread_num(NULL);
  ptask task;
  pshareds psh;
  omp_set_dynamic(0);
  counter = 0;
  task_count = 0;
  #pragma omp parallel num_threads(N)
  {
    #pragma omp master
    {
      int gtid = __kmpc_global_thread_num(NULL);
      task = __kmpc_omp_task_alloc(NULL, gtid, 1, sizeof(struct task),
                                   sizeof(struct shar), &task_entry);
      psh = task->shareds;
      psh->pcounter = &counter;
      psh->ptask_count = &task_count;
      psh->pj = &j;
      task->lb = LB;
      task->ub = UB;
      task->st = ST;

      __kmpc_taskloop_5(
        NULL,             // location
        gtid,             // gtid
        task,             // task structure
        1,                // if clause value
        &task->lb,        // lower bound
        &task->ub,        // upper bound
        ST,               // loop increment
        0,                // 1 if nogroup specified
        sched_type,       // schedule type: 0-none, 1-grainsize, 2-num_tasks
        sched_val,        // schedule value (ignored for type 0)
        modifier,         // strict modifier
        (void*)&__task_dup_entry // tasks duplication routine
      );
    } // end master
  } // end parallel
// check results
  int tc;
  if (ST == 1) { // most common case
    tc = UB - LB + 1;
  } else if (ST < 0) {
    tc = (LB - UB) / (-ST) + 1;
  } else { // ST > 0
    tc = (UB - LB) / ST + 1;
  }
  int count;
  if (sched_type == 1) {
    count = (sched_val > tc) ? 1 : (tc + sched_val - 1) / sched_val;
  } else {
    count = (sched_val > tc) ? tc : sched_val;
  }
  if (j != LB + (tc - 1) * ST) {
    printf("Error in lastprivate, %d != %d\n", j, LB + (tc - 1) * ST);
    exit(1);
  }
  if (counter != tc) {
    printf("Error, counter %d != %d\n", counter, tc);
    exit(1);
  }
  if (task_count != count) {
    printf("Error, task count %d != %d\n", task_count, count);
    exit(1);
  }
}

int main(int argc, char *argv[]) {
  task_loop(1, 6, 1); // create 7 tasks
  task_loop(2, 6, 1); // create 6 tasks
  task_loop(1, 50, 1); // create 1 task
  task_loop(2, 50, 1); // create 40 tasks

  printf("Test passed\n");
  return 0;
}