4

当我准备一些代码示例以向我的队友介绍 OpenMP 时,我发现了一个奇怪的案例。首先我写了一个经典的循环:

void sequential(int *a, int size, int *b)
{
    int i;
    for (i = 0; i < size; i++) {
        b[i] = a[i] * i;
    }
}

for 指令的正确 OpenMP 用法很简单。我们只需要将int i声明移入范围即可private

void parallel_for(int *a, int size, int *b)
{
#pragma omp parallel for
    for (int i = 0; i < size; i++) {
        b[i] = a[i] * i;
    }
}

但是当我编写以下函数时,我预计我会得到与其他 2 个不同的结果,因为int j我声明的共享超出了 for 循环范围。但是使用我的测试框架,我没有看到我预期的错误,该函数的输出值不正确。

void parallel_for_with_an_usage_error(int *a, int size, int *b)
{
    int j;
#pragma omp parallel for
    for (int i = 0; i < size; i++) {
        /*int*/ j = a[i]; //To be correct j should be declared here, in-loop to be private !
        j *= i;
        b[i] = j;
    }
}

我有一个完整的测试源代码,它使用 VS'12 和 gcc(启用 C++11)构建在这里http://pastebin.com/NJ4L0cbV

你知道编译器是做什么的吗?它是否检测到错误共享,是否int j由于优化启发式而在循环中移动?

谢谢

4

1 回答 1

0

在我看来,可能发生的是编译器正在做一些优化。由于在上面粘贴的代码中(没有 cout),变量 j 不在循环内以外的任何地方,编译器可以将 j 的声明放在生成的汇编代码中的循环内。

另一种可能性是编译器可能会将循环内的 3 个语句转换为一个语句,即从

/*int*/ j = a[i]; //To be correct j should be declared here, in-loop to be private !
j *= i;
b[i] = j;

到,

b[i] = a[i] * i;

无论是否为 OpenMP 代码,编译器都会执行此优化。

于 2013-08-21T02:51:11.037 回答