我正在尝试并行化代码。我的代码看起来像这样 -
#pragma omp parallel private(i,j,k)
#pragma omp parallel for shared(A)
for(k=0;k<100;<k++)
for(i=1;i<1024;<i++)
for(j=0;j<1024;<j++)
A[i][j+1]=<< some expression involving elements of A[i-1][j-1] >>
在执行此代码时,我得到了与循环的串行执行不同的结果。 我无法理解我做错了什么。
我也试过了崩溃()
#pragma omp parallel private(i,j,k)
#pragma omp parallel for collapse(3) shared(A)
for(k=0;k<100;<k++)
for(i=1;i<1024;<i++)
for(j=0;j<1024;<j++)
A[i][j+1]=<< some expression involving elements of A[][] >>
我尝试的另一件事是在每个循环之前使用#pragma omp并行而不是collapse()。
我认为这个问题是数据依赖性。知道如何在数据依赖的情况下并行化吗?
答案 0 :(得分:0)
如果这确实是你的用例,只需并行化外部循环k
,这应该足以满足你在常见架构上的适度并行性。
如果你想要更多,你必须重新编写你的循环,以便你有一个没有依赖的内部部分。在你的示例中,这是相对容易的,你必须通过“diagonals”(外循环,顺序)进行处理,然后在对角线内部进行独立处理。
for (size_t d=0; d<nDiag(100); ++d) {
size_t nPoints = somefunction(d);
#pragma omp parallel
for (size_t p=0; p<nPoints; ++p) {
size_t x = coX(p, d);
size_t y = coY(p, d);
... your real code ...
}
}
部分内容可以自动完成,但我不认为这些工具已经很容易在日常OMP中实现。这是一项积极的研究。
另请注意以下内容
int
对于索引来说很少是一个好主意,特别是如果你访问矩阵。如果你必须自己计算一个条目的绝对位置(你可能在这里看到),这很容易溢出。 int
通常是32位宽,其中32个你甚至浪费一个标志。在C中,对象大小使用size_t
计算,大多数时间为64位宽,无论如何都是平台设计者选择的正确类型。答案 1 :(得分:0)
你只是将外部&#k;&#39; for循环。每个并行线程都在执行&#39; i&#39;和&#39; j&#39;循环,他们都写入相同的&#39; A&#39;结果。由于他们在A中读取和写入相同的插槽,因此最终结果将是不确定的。
您的问题并不清楚任何并行性是可能的,因为每个步骤似乎都取决于之前的每一步。