是否存在ICV(内部控制变量)或类似的东西来查询OpenMP中循环的上限和下限?
在某些情况下,以下计算会给出上限和下限:
#pragma omp parallel for
for ( i = 0 ; i < n ; i++ ){
int this_thread = omp_get_thread_num(),
num_threads = omp_get_num_threads();
int lower_bound = (this_thread * n / num_threads);
int upper_bound = ((this_thread+1) * n / num_threads) - 1;
...
}
对于n=100
,我会为线程0, 25, 50 and 75
获取24, 49, 74 and 99
的正确下限和0, 1, 2, 3
的上限。
如果我将n
更改为99
,则会给我不正确的界限。
GCC和Intel或C / C ++编译器的上限和下限计算是否不同?
答案 0 :(得分:1)
OpenMP运行时库中没有任何函数可以为您提供此信息。此外,它将高度依赖于在循环上应用的调度。
默认情况下,如果没有明确的schedule
指令,那么将应用的指令将依赖于编译器,并且不受OpenMP标准的指定。许多编译器将使用static
调度,但情况并非如此,并且绝对无法保证。
现在,引用OpenMP标准来引用静态调度:
指定
schedule(static, chunk_size)
时,会划分迭代次数 分成大小为chunk_size
的块,并将块分配给。{ 团队中的线程以循环方式按顺序排列 线号。如果未指定
chunk_size
,则迭代空间为 分成几乎大小相等的块,最多 每个线程分配一个块。块的大小是 在这种情况下没有说明。
正如您所看到的,即使在这种简单的情况下,如果没有给出块大小并且线程数没有均匀地划分迭代次数,则无法可靠地确定每个线程的下限和上限# 39;迭代。
如果你正确定义了块的大小,你应该能够可靠地计算每个线程的迭代范围。
现在,如果您的日程安排不是静态的,那么绝对无法推断哪个线程会获得什么样的迭代,因为这只会在运行时定义。
答案 1 :(得分:-1)
每个线程没有上限/下限。每个线程将在序列中选择下一个可用元素或下一个可用元素块。块大小是可配置的。
通常,内部使用原子增量,即InterlockedIncrement()。
顺便说一下,每个线程的下限/上限都是一个非常糟糕的主意。假设与其余元素相比,元素27的执行时间要长10倍。然后,必须处理此元素的不幸线程将比其他线程更晚完成。特定线程也可能被其他CPU活动停滞,每个线程拥有固定数量的元素将是非常低效的。