diff options
Diffstat (limited to 'final/runtime/test/tasking/kmp_taskloop.c')
-rw-r--r-- | final/runtime/test/tasking/kmp_taskloop.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/final/runtime/test/tasking/kmp_taskloop.c b/final/runtime/test/tasking/kmp_taskloop.c new file mode 100644 index 0000000..359f7a4 --- /dev/null +++ b/final/runtime/test/tasking/kmp_taskloop.c @@ -0,0 +1,160 @@ +// RUN: %libomp-compile-and-run +// RUN: %libomp-compile && env KMP_TASKLOOP_MIN_TASKS=1 %libomp-run +// REQUIRES: openmp-4.5 +#include <stdio.h> +#include <omp.h> +#include "omp_my_sleep.h" + +#define N 4 +#define GRAIN 10 +#define STRIDE 3 + +// globals +int th_counter[N]; +int counter; + + +// Compiler-generated code (emulation) +typedef struct ident { + void* dummy; +} ident_t; + +typedef struct shar { + int(*pth_counter)[N]; + int *pcounter; + int *pj; +} *pshareds; + +typedef struct task { + pshareds shareds; + int(* routine)(int,struct task*); + int part_id; +// privates: + 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(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, 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; + 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); + __kmpc_atomic_fixed4_add(NULL,gtid,&((*pshar->pth_counter)[task->th]),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; +} + +int main() +{ + int i, j, gtid = __kmpc_global_thread_num(NULL); + ptask task; + pshareds psh; + omp_set_dynamic(0); + counter = 0; + for( i=0; i<N; ++i ) + th_counter[i] = 0; + #pragma omp parallel num_threads(N) + { + #pragma omp master + { + int gtid = __kmpc_global_thread_num(NULL); +/* + * This is what the OpenMP runtime calls correspond to: + #pragma omp taskloop num_tasks(N) lastprivate(j) + for( i=0; i<N*GRAIN*STRIDE-1; i+=STRIDE ) + { + int th = omp_get_thread_num(); + #pragma omp atomic + counter++; + #pragma omp atomic + th_counter[th]++; + j = i; + } +*/ + task = __kmpc_omp_task_alloc(NULL,gtid,1,sizeof(struct task),sizeof(struct shar),&task_entry); + psh = task->shareds; + psh->pth_counter = &th_counter; + psh->pcounter = &counter; + psh->pj = &j; + task->lb = 0; + task->ub = N*GRAIN*STRIDE-2; + task->st = STRIDE; + + __kmpc_taskloop( + NULL, // location + gtid, // gtid + task, // task structure + 1, // if clause value + &task->lb, // lower bound + &task->ub, // upper bound + STRIDE, // loop increment + 0, // 1 if nogroup specified + 2, // schedule type: 0-none, 1-grainsize, 2-num_tasks + N, // schedule value (ignored for type 0) + (void*)&__task_dup_entry // tasks duplication routine + ); + } // end master + } // end parallel +// check results + if( j != N*GRAIN*STRIDE-STRIDE ) { + printf("Error in lastprivate, %d != %d\n",j,N*GRAIN*STRIDE-STRIDE); + return 1; + } + if( counter != N*GRAIN ) { + printf("Error, counter %d != %d\n",counter,N*GRAIN); + return 1; + } + for( i=0; i<N; ++i ) { + if( th_counter[i] % GRAIN ) { + printf("Error, th_counter[%d] = %d\n",i,th_counter[i]); + return 1; + } + } + printf("passed\n"); + return 0; +} |