我有一个for循环,可以使用schedule(static)
或schedule(dynamic, 10)
执行,具体取决于条件。目前,我的代码不是DRY(不要重复自己),为了适应以前的功能,它有以下重复:
boolean isDynamic; //can be true or false
if(isDynamic){
#pragma omp parallel for num_threads(thread_count) default(shared) private(...) schedule(dynamic, 10)
for(...){
//for code inside
}
}else{
#pragma omp parallel for num_threads(thread_count) default(shared) private(...) schedule(static)
for(...){
//SAME for code inside, in fact, this is the EXACT same for as before
}
}
阅读完这些主题之后,我注意到openMP有一个#if(expression)
编译指示:
但是虽然我看到很多人遇到了我的问题,但似乎缺乏一般的解决方案。最好的解决方案是将for循环的主体转换为函数,然后调用函数,但这个解决方案对我来说还不够好。
所以我想知道,OpenMP是否有一个#if(expression) else
类型的pragma?就像是:
#if(isDynamic )pragma omp parallel for num_threads(thread_count) default(shared)
private(...) schedule(dynamic, 10)
else
pragma omp parallel for num_threads(thread_count) default(shared)
private(...) schedule(static)
或者我被迫将我的for循环体放入一个单独的函数并以这种方式调用它?
这是个有趣的问题。基本上,您希望在运行时更改schedule
策略。据我所知,目前的OpenMP没有这样的指令。
我遇到了完全相同的问题。正如你所提到的,我的解决方案最终使循环体成为一个函数。否则,您需要使用丑陋的宏。
但是,我也尝试使用schedule(runtime)
,它读取环境变量OMP_SCHEDULE
。所以,我在运行时更改了这个环境变量,但是没有用。这是因为OpenMP运行时只在开始时读取此环境一次。它可能是特定于实现的问题。因此,其他实现可以即时读取此环境变量。你可以尝试这种方法。
这已经晚了几年,但对于这种特殊情况,您可以使用运行时库在运行时设置计划。它在OpenMP 4.5中的§3.2.12中定义:
void omp_set_schedule(omp_sched_t kind, int chunk_size);
typedef enum omp_sched_t {
omp_sched_static = 1,
omp_sched_dynamic = 2,
omp_sched_guided = 3,
omp_sched_auto = 4
} omp_sched_t;
对于您的情况,您所做的是:
/* wherever currently isDynamic is set */
if (isDynamic) {
omp_set_schedule(omp_sched_dynamic, 10);
} else {
/* chunk_size < 1 uses default */
omp_set_schedule(static, 0);
}
/* later */
#pragma omp parallel for num_threads(thread_count) default(shared) private(...) schedule(runtime)
for (...) {
/* do a thing */
}