#pragma omp for schedule(static)
关于未指定块大小的位置, 我有几个问题。
在 OpenMP 中并行化循环的一种方法是手动执行,如下所示:
#pragma omp parallel
{
const int nthreads = omp_get_num_threads();
const int ithread = omp_get_thread_num();
const int start = ithread*N/nthreads;
const int finish = (ithread+1)*N/nthreads;
for(int i = start; i<finish; i++) {
//
}
}
是否有充分的理由不在 OpenMP 中手动并行化这样的循环? 如果我将这些值与我进行比较,#pragma omp for schedule(static)
我发现给定线程的块大小并不总是一致,因此 OpenMP(在 GCC 中)实现的卡盘大小与 和 中定义的start
不同finish
。为什么是这样?
我定义的start
andfinish
值有几个方便的属性。
- 每个线程最多获得一个块。
- 迭代值的范围直接随线程数增加(即对于具有两个线程的 100 个线程,第一个线程将处理迭代 1-50 和第二个线程 51-100,而不是相反)。
- 对于完全相同范围内的两个 for 循环,每个线程将运行完全相同的迭代。
编辑:原来我说的是一个块,但经过考虑,如果线程数远大于N
(ithread*N/nthreads = (ithread*1)*N/nthreads
),则块的大小可能为零。我真正想要的财产最多是一大块。
使用时是否保证所有这些属性#pragma omp for schedule(static)
?
根据 OpenMP 规范:
依赖于哪个线程在任何其他情况下执行特定迭代的程序是不合格的。
和
具有相同调度和迭代计数的不同循环区域,即使它们发生在同一个并行区域中,也可以在线程之间以不同的方式分配迭代。唯一的例外是静态计划
对于schedule(static)
规范说:
块按照线程编号的顺序以循环方式分配给团队中的线程。
此外,该规范对`schedule(static) 进行了说明:
当没有指定chunk_size时,迭代空间被分成大小近似相等的chunk,每个线程最多分配一个chunk。
最后,规范说schedule(static)
:
如果满足以下条件,静态调度的兼容实现必须确保在两个循环区域中使用相同的逻辑迭代次数分配给线程:1)两个循环区域具有相同的循环迭代次数,2)两个循环区域具有相同的 chunk_size 值,或者两个循环区域都没有指定 chunk_size,3) 两个循环区域绑定到同一个并行区域。
因此,如果我正确阅读此内容,schedule(static)
将具有与我列出的相同的方便属性start
,finish
即使我的代码依赖于线程执行特定的迭代。 我是否正确解释了这一点? 这似乎schedule(static)
是未指定块大小时的特殊情况。
定义更容易start
,finish
就像我所做的那样,然后尝试中断这种情况的规范。