适用于在1D阵列上运行的嵌套for循环的openmp指令

时间:2018-05-09 16:50:34

标签: c++ for-loop openmp nested-loops

我需要迭代一个数组并根据需要一些迭代的计算来分配每个元素。删除所有不必要的细节,程序归结为类似的东西。

float output[n];
const float input[n] = ...;

for (int i = 0; i < n; ++i) {
    output[i] = 0.0f;
    for (int j = 0; j < n; ++j) {
        output[i] += some_calculation(i, input[j]);
    }
}

some_calculation不改变其参数,也没有内部状态,因此其线程安全。看一下循环,我理解外部循环是线程安全的,因为不同的迭代输出到不同的内存位置(不同的output[i]),而input的共享元素在循环运行时永远不会改变,但是内部循环不是线程安全的,因为它在output[i]上有一个竞争条件,因为它在所有迭代中都被改变了。

因此,我想生成线程并让它们为i的不同值工作,但是input上的整个迭代应该是每个线程的本地迭代,以便不引入竞争条件output[i]。我认为以下成就了这一点。

std::array<float, n> output;
const std::array<float, n> input[n];

#pragma omp parallel for
for (int i = 0; i < n; ++i) {
    output[i] = 0.0f;
    for (int j = 0; j < n; ++j) {
        output[i] += some_calculation(i, input[j]);
    }
}

我不确定这是如何处理内循环的。在不同的i上工作的线程应该能够并行运行循环但我不明白我是否允许它们没有另一个#pragma omp指令。另一方面,我不想在相同的j上意外地允许线程针对不同的i值运行,因为这会引入竞争条件。我还不确定是否需要一些关于如何处理这两个数组的额外规范。

最后,如果这个代码在一个将被重复调用的函数中,它是否需要parallel指令,或者可以在我的主循环开始之前调用一次。

void iterative_step(const std::array<float, n> &input, const std::array<float, n> &output) {
    // Threads have already been spawned
    #pragma omp for
    for (int i = 0; i < n; ++i) {
        output[i] = 0.0f;
        for (int j = 0; j < n; ++j) {
            output[i] += some_calculation(i, input[j]);
        }
    }

int main() {
    ...
    // spawn threads once, but not for this loop
    #pragma omp parallel
    while (...) {
        iterative_step(input, output);
    }
    ...
}

我查看了其他各种问题,但他们是关于不同种族条件的不同问题,我对如何概括答案感到困惑。

1 个答案:

答案 0 :(得分:0)

您不希望omp parallel中有main。您使用的omp for将仅为以下for (int i循环创建/重用线程。对于i的任何特定值,j循环将完全在一个线程上运行。

另一件有用的事情是将output[i]结果计算到局部变量中,然后在output[i]循环完成后将其存储到j