关于未指定块大小的#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)
进行比较,我会发现给定线程的块大小不是t始终同意,因此OpenMP(在GCC中)实现的夹头尺寸与start
和finish
中定义的夹头尺寸不同。这是为什么?
我定义的start
和finish
值有几个方便的属性。
编辑: 原文我只说了一个块,但在考虑之后,如果线程数是,则块的大小可能为零比N
(ithread*N/nthreads = (ithread*1)*N/nthreads
)大得多。我真正想要的属性最多只有一个块。
使用#pragma omp for schedule(static)
根据OpenMP规范:
依赖于哪个线程在任何其他情况下执行特定迭代的程序是不符合的。
和
具有相同调度和迭代计数的不同循环区域,即使它们出现在相同的并行区域中,也可以不同地在线程之间分配迭代。唯一的例外是静态计划
对于schedule(static)
,规范说:
按照线程编号的顺序以循环方式将块分配给团队中的线程。
另外,规范说“schedule(static):
”当没有指定chunk_size时,迭代空间被划分为大小大致相等的块,并且最多只有一个块被分配给每个线程。
最后,规范针对schedule(static)
:
静态计划的合规实施必须确保 逻辑迭代次数与线程的相同分配将在两个中使用 如果满足以下条件,则循环区域:1)两个循环区域具有相同数量的循环迭代,2)两个循环区域具有相同的chunk_size值,或者两个循环区域都没有指定chunk_size,3)两个循环区域绑定到同一个平行区域。
因此,如果我正确读取此schedule(static)
将具有我列为start
和finish
的相同方便属性,即使我的代码依赖于线程执行特定迭代。 我是否正确解释了这一点?当未指定块大小时,这似乎是schedule(static)
的一种特殊情况。
像我一样定义start
和finish
更容易,然后尝试中断此案例的规范。
答案 0 :(得分:5)
有没有充分的理由不在OpenMP中手动并行化这样的循环?
我想到的第一件事:
schedule(static)
之间的所有日程安排机会。 使用#pragam omp进行计划(静态)时是否保证所有这些属性?
让我们一个接一个地看:
1。)每个线程只有一个块
当没有指定chunk_size时,迭代空间被分成 大小大致相等的块,最多一个块 分发给每个线程。请注意,块的大小是 在这种情况下没有说明。
最多一个块不是恰好一个块。因此,财产一不履行。此外,这就是为什么大块的大小没有说明。
2。)迭代值的范围直接随线程数增加(即,对于具有两个线程的100次迭代,第一个线程将 进程迭代1-50和第二个线程51-100而不是 其他方式)
静态的兼容实现 schedule必须确保逻辑迭代的分配相同 如果满足以下条件,则数字到线程将用于两个循环区域 条件得到满足:
- 两个循环区域具有相同数量的循环迭代
- 两个循环区域都指定了相同的chunk_size值,或者两个循环区域都没有指定chunk_size
- 两个循环区域都绑定到同一个并行区域。
醇>两个这样的相同逻辑迭代之间的数据依赖性 保证满足循环,允许安全使用nowait (例如,参见第182页的A.10节)。
尽管我从来没有看到过与你所说的不同的东西,但我敢说即使属性二也没有实现,至少不是schedule(static)
。在我看来,在某个基数的迭代空间中,唯一的保证是,如果遵守条件1,2和3,则相同的“逻辑迭代数”将被赋予相同的线程。
如果您指定块大小,则确实已授予:
当指定schedule(static,chunk_size)时,迭代被划分 进入大小为chunk_size的块,并将块分配给 团队中的线程以循环方式按顺序排列 线号。
3。)对于两个完全相同范围的for循环,每个线程将在完全相同的迭代上运行
这确实被授予,并且更加通用:对于具有相同基数的迭代空间的两个循环,将给予每个线程相同的“逻辑迭代数”。 OpenMP 3.1标准的Example A.10.2c
应澄清这一点。