【问题标题】:How to use omp parallel for and omp simd together?如何同时使用 omp parallel for 和 omp simd?
【发布时间】:2024-01-21 17:27:01
【问题描述】:

我想测试#pragma omp parallel for#pragma omp simd 的简单矩阵加法程序。当我分别使用它们时,我没有收到任何错误,而且看起来很好。但是,我想测试使用它们两者可以获得多少性能。如果我在外循环之前使用#pragma omp parallel for,在内循环之前使用#pragma omp simd,我也不会出错。当我在外循环之前同时使用它们时会发生错误。我在运行时而不是编译时收到错误。 ICCGCC 返回错误,但 Clang 没有。可能是因为Clang 接受了并行化。在我的实验中,Clang 不会并行化并仅使用一个线程运行程序。

程序在这里:

#include <stdio.h>
//#include <x86intrin.h>
#define N 512
#define M N

int __attribute__(( aligned(32))) a[N][M],
    __attribute__(( aligned(32))) b[N][M],
    __attribute__(( aligned(32))) c_result[N][M];

int main()
{
    int i, j;
    #pragma omp parallel for
    #pragma omp simd
    for( i=0;i<N;i++){
        for(j=0;j<M;j++){
            c_result[i][j]= a[i][j] + b[i][j];
        }
    }

    return 0;
}

错误: 国际商会:

IMP1.c(20):错误:omp 指令后面没有可并行化 for loop #pragma omp parallel for ^

IMP1.c 的编译中止(代码 2)

海合会:

IMP1.c:在函数“main”中:

IMP1.c:21:10:错误:for 语句 预计在“#pragma”之前#pragma omp simd

因为在我的其他睾丸 pragma omp simd for 外循环中获得了更好的性能,我需要把它放在那里(不是吗?)。

平台:Intel Core i7 6700 HQ、Fedora 27

经过测试的编译器:ICC 18、GCC 7.2、Clang 5

编译器命令行:

icc -O3 -qopenmp -xHOST -no-vec

gcc -O3 -fopenmp -march=native -fno-tree-vectorize -fno-tree-slp-vectorize

clang -O3 -fopenmp=libgomp -march=native -fno-vectorize -fno-slp-vectorize

【问题讨论】:

  • 你也试过#pragma omp parallel for simd吗?
  • #defien M N 这实际上是在您的代码中还是在此处提问时出现拼写错误?
  • @ChristianGibbons,我在这里简化时打错了。
  • 虽然 icc 为 simd 实现了并行(gcc 将忽略 simd),但这不是这种情况的正确方法,因为内部(但不是外部)循环可以有效地使用 simd。因此,您可以将 omp simd 放在内部,将 omp parallel 放在外部,但您可能会遇到内存带宽饱和,因此不会看到理想的加速。 omp simd 是否对内部循环有影响取决于编译器和选择的选项。

标签: c parallel-processing x86 openmp simd


【解决方案1】:

来自 OpenMP 4.5 规范:

2.11.4 并行循环 SIMD 构造

并行循环 SIMD 构造是指定并行循环的快捷方式 包含一个循环 SIMD 构造且没有其他语句的构造。

并行循环SIMD结构的语法如下:

#pragma omp parallel for simd ...

你也可以写:

#pragma omp parallel
{
   #pragma omp for simd
   for ...
}

【讨论】:

  • 这种方法有效,但我认为矢量化并不像它可能的那样好。 pragma omp simd 在 ICC 中工作得很好,但这种方法并不能向量化大多数实现。
  • 我重新检查过,是的,这种方法不适合混合 TLP 和 DLP。连ICC都糊涂了!但是,谢谢!你为我节省了很多时间。我真的很感激。
  • @Martin 我猜你的算法受到内存带宽的限制,这通常会阻碍矢量化和多线程的可扩展性。每个算术运算有 2 次加载和 1 次存储,即相当高的字节/操作比率。如果您想了解更多有关此问题的信息,请查找“记忆墙”和“屋顶模型”。
  • 谢谢,我注意到了这些短语。你是对的,我测试了矩阵-矩阵加法、矩阵转置、矩阵-矩阵乘法、有限脉冲响应 (FIR) 滤波器、绝对差和 (SAD)、平方差和 (SSD) 和矩阵卷积算法,它们都是受限于内存带宽(我猜)。
  • 如何写parallel参数(如privatefirst等)和simd参数?
最近更新 更多