对不起,如果标题很不清楚。我不太清楚怎么说这个。
我想知道我是否有办法做到以下几点:
#pragma omp parallel
{
for (int i = 0; i < iterations; i++) {
#pragma omp for
for (int j = 0; j < N; j++)
// Do something
}
}
忽略诸如在for循环中省略私有说明符之类的东西,有什么方法可以在我的外部循环之外分叉线程,这样我就可以并行化内部循环?从我的理解(如果我错了请纠正我),所有线程将执行外部循环。我不确定内循环的行为,但我认为for
会将块分发给遇到它的每个线程。
我想要做的是不必fork / join iterations
次,而只是在外循环中执行一次。这是正确的策略吗?
如果有另一个外环不应该并行化怎么办?那是......
#pragma omp parallel
{
for (int i = 0; i < iterations; i++) {
for(int k = 0; k < innerIterations; k++) {
#pragma omp for
for (int j = 0; j < N; j++)
// Do something
// Do something else
}
}
}
如果有人向我指出使用OpenMP并行化的大型应用程序的示例,那就太棒了,这样我就可以更好地理解使用OpenMP时要采用的策略。我似乎无法找到任何。
澄清:我正在寻找不改变循环排序或涉及阻塞,缓存和一般性能考虑因素的解决方案。我想了解如何在OpenMP上对指定的循环结构进行此操作。 // Do something
可能有也可能没有依赖关系,假设它们存在,并且您无法移动。
答案 0 :(得分:3)
你处理这两个for循环的方式对我来说是正确的,因为它实现了你想要的行为:外部循环不是并行化的,而内部循环是。
为了更好地说明会发生什么,我会尝试在您的代码中添加一些注释:
#pragma omp parallel
{
// Here you have a certain number of threads, let's say M
for (int i = 0; i < iterations; i++) {
// Each thread enters this region and executes all the iterations
// from i = 0 to i < iterations. Note that i is a private variable.
#pragma omp for
for (int j = 0; j < N; j++) {
// What happens here is shared among threads so,
// according to the scheduling you choose, each thread
// will execute a particular portion of your N iterations
} // IMPLICIT BARRIER
}
}
隐式屏障是线程彼此等待的同步点。作为拇指的一般规则,因此最好并行化外部循环而不是内部循环,因为这将为iterations*N
迭代创建单个同步点(而不是{{ 1}}你在上面创建的点数。)
答案 1 :(得分:1)
我不确定我能回答你的问题。我现在只使用OpenMP几个月,但是当我尝试回答这样的问题时,我会做一些你好的世界printf测试,如下所示。我认为这可能有助于回答您的问题。同时尝试#pragma omp for nowait
,看看会发生什么。
确保当你“//做某事并做其他事情”而你没有写入同一个内存地址并创建竞争条件时。此外,如果您正在进行大量的阅读和写作,则需要考虑如何有效地使用缓存。
#include "stdio.h"
#include <omp.h>
void loop(const int iterations, const int N) {
#pragma omp parallel
{
int start_thread = omp_get_thread_num();
printf("start thread %d\n", start_thread);
for (int i = 0; i < iterations; i++) {
printf("\titeration %d, thread num %d\n", i, omp_get_thread_num());
#pragma omp for
for (int j = 0; j < N; j++) {
printf("\t\t inner loop %d, thread num %d\n", j, omp_get_thread_num());
}
}
}
}
int main() {
loop(2,30);
}
就性能而言,您可能需要考虑融合您的循环。
#pragma omp for
for(int n=0; n<iterations*N; n++) {
int i = n/N;
int j = n%N;
//do something as function of index i and j
}
答案 2 :(得分:0)
很难回答,因为它实际上取决于代码中的依赖关系。但解决这个问题的一般方法是反转循环的嵌套,如下所示:
#pragma omp parallel
{
#pragma omp for
for (int j = 0; j < N; j++) {
for (int i = 0; i < iterations; i++) {
// Do something
}
}
}
当然,根据循环中的代码,这可能是也可能不可能。