2015-11-02 63 views
0

使用GOMP_loop_static_start当gcc编译器编译它永远不会调用ligbomp功能GOMP_loop_static_start#pragma omp for schedule(static),它使用一些汇编指令做#pragma omp for schedule(static)的功能。从libgomp

我实现我自己的libgomp库,我想的是,当OpenMP的应用程序调用#pragma omp for static gcc编译器调用我的实现GOMP_loop_static_start的。

+0

您可以查看英特尔贡献的Clang的OSS运行时。它应该实现GOMP接口,但不受GPL病毒的阻碍,所以你可以用衍生作品做你想做的事情。 – Jeff

回答

1

这实际上是不可能得到GCC产生的,因为在OpenMP的扩展程序的一段代码的for指令扩张的结果GOMP_loop_static_start通话快捷键schedule(static)情况:

3123 static void 
3124 expand_omp_for (struct omp_region *region) 
3125 { 
3126  struct omp_for_data fd; 
3127  
3128  push_gimplify_context(); 
3129  
3130  extract_omp_for_data (last_stmt (region->entry), &fd); 
3131  region->sched_kind = fd.sched_kind; 
3132  
3133  if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC 
3134   && !fd.have_ordered 
3135   && region->cont 
3136   && region->exit) 
3137  { 
3138   if (fd.chunk_size == NULL) 
3139   expand_omp_for_static_nochunk (region, &fd); 
3140   else 
3141   expand_omp_for_static_chunk (region, &fd); 
3142  } 
3143  else 
3144  { 
3145   int fn_index = fd.sched_kind + fd.have_ordered * 4; 
3146   int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index; 
3147   int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index; 
3148   expand_omp_for_generic (region, &fd, start_ix, next_ix); 
3149  } 
3150  
3151  pop_gimplify_context (NULL); 
3152 } 

上面的代码来自GCC 4.2.0,这是第一个正式引入OpenMP支持的版本。自那时以来,事情并没有多大变化(只有OpenMP标准的每个新版本都变得复杂得多)。 extract_omp_for_data()分析for指令和相关的for循环。它放置了在fd.sched_kind中找到的那种循环调度。如果没有提供schedule子句,则它使用GCC schedule(static)的默认值。 expand_omp_for_static_nochunk()expand_omp_for_static_chunk()都不会拨打电话GOMP_loop_static_start。相反,他们发出一个使用omp_get_num_threads()omp_get_thread_num()计算迭代空间为每个线程代码:

#pragma omp for 
for (int i = 0; i < steps; i++) 
    ... 

变为:

<bb 2>: 
i = 0; 
steps.0 = steps; 
D.1368 = __builtin_omp_get_num_threads(); 
D.1369 = __builtin_omp_get_thread_num(); 
q.1 = steps.0/D.1368; 
tt.2 = steps.0 % D.1368; 
if (D.1369 < tt.2) 
    goto <bb 3>; 
else 
    goto <bb 4>; 

<bb 3>: 
tt.2 = 0; 
q.1 = q.1 + 1; 

<bb 4>: 
D.1372 = q.1 * D.1369; 
D.1373 = D.1372 + tt.2; 
D.1374 = D.1373 + q.1; 
if (D.1373 >= D.1374) 
    goto <bb 7>; 
else 
    goto <bb 5>; 

<bb 5>: 
i = D.1373; 

<bb 6>: 
... 
i = i + 1; 
if (i < D.1374) 
    goto <bb 6>; 
else 
    goto <bb 7>; 

<bb 7>: 
__builtin_GOMP_barrier(); 

只有expand_omp_for_generic()可以发出调用GOMP_loop_static_start代码。为此,执行流程必须输入else区块,如果循环时间表不是静态的,或者应用了ordered子句。在前一种情况下,将会调用另一个GOMP_loop_xxx_start()。在后一种情况下,GOMP_loop_ordered_static_start()将被调用。

唯一的剩余选项是该区域没有延续(OMP_CONTINUE)或退出(OMP_RETURN)块。我认为没有办法实现这一点,因为两个块总是由降低OpenMP for指令的代码添加。后期版本的编译器删除了退出块的检查,但对我而言仍然不明显,继续块如何被删除。