【问题标题】:OpenMP odd behaviour with SIMD linear and parallel for linear directives线性指令的 SIMD 线性和并行的 OpenMP 奇怪行为
【发布时间】:2016-09-13 16:52:02
【问题描述】:

我正在学习如何使用 GNU C 编译器 6.2.1 将 OpenMP 与 C++ 结合使用,并且我测试了以下代码:

#include <stdio.h>
#include <omp.h>
#include <iostream>

int b=10;

int main()
{
    int array[8];
    std::cout << "Test with #pragma omp simd linear:\n";
    #pragma omp simd linear(b)
    for (int n=0;n<8;++n) array[n]=b;

    for (int n=0;n<8;++n) printf("Iteration %d: %d\n", n, array[n]);

    std::cout << "Test with #pragma omp parallel for linear:\n";
    #pragma omp parallel for linear(b)
    for (int n=0;n<8;++n) array[n]=b;

    for (int n=0;n<8;++n) printf("Iteration %d: %d\n", n, array[n]);
}

在这两种情况下,我都希望得到一个从 10 到 17 的数字列表,但事实并非如此。 #pragma omp simd linear(b) 被完全忽略,array 中的每个值只打印 10 个。对于#pragma omp parallel for linear(b),程序输出10,10,12,12,14,14,16,16

我使用g++ -fopenmp -Wall main.cpp -o main.o 编译文件。我该如何解决这个问题?

编辑:更仔细地阅读规范,我发现linear 子句用获得的最后一个值覆盖了初始值(即,如果我们在第一个循环之后以b=10 开始,我们有b=17)。 但是,如果我将 schedule(dynamic) 添加到并行循环中,程序将正确运行。为什么我必须指定该参数才能正确执行?

【问题讨论】:

  • 这很有趣。这可以用 GCC5.4.0 重现,除了 GCC 的 openmp 不接受没有 simd 子句的 linear 子句(测试代码的后半部分不能用 GCC 编译)。为了让 b 在 GCC 上发生变化,我使用 #pragma omp parallel for simd linear(b) 但在每个线程中, b 仍然是一个固定值。您可以提交错误报告并向 GCC 团队或其他编译器开发组询问。

标签: c++ openmp simd


【解决方案1】:

OpenMP specification 说:

linear 子句声明一个或多个列表项是私有的,并且 与 a 的迭代空间呈线性关系 与出现子句的结构相关联的循环。

这是仅供编译器参考的信息,用于指示变量在循环中的线性行为,但在您的代码中b 根本没有增加。这就是你在第一个循环中总是得到10 的原因。所以,得到的奇怪结果不是编译器的错。要纠正它,你必须使用 array[n]=b++;

另一方面,对于#pragma omp parallel for linear(b) 循环,OpenMP 计算每个线程的起始b 值(基于线性关系),但该值在给定线程中仍然没有增加。因此,根据使用的线程数,您会看到不同数量的“步骤”。

schedule(dynamic) 子句的情况下,chunk_size1,因此每个循环循环在不同的线程中运行。在这种情况下,初始 b 值始终由 OpenMP 计算,因此您只能获得正确的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-21
    • 1970-01-01
    • 2018-03-06
    相关资源
    最近更新 更多