如何同时使用omp parallel for和omp simd?

10
我想测试一个简单的矩阵加法程序,使用#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;
}

错误信息:

ICC:

IMP1.c(20): error: omp指令后面没有可并行化的for循环 #pragma omp parallel for ^

IMP1.c编译失败 (code 2)

GCC:

IMP1.c: 在函数‘main’中:

IMP1.c:21:10: error: 缺少for循环 #pragma omp simd

因为在我的其他测试中,对于外循环而言,pragma omp simd可以获得更好的性能,所以我需要将其放在那里(不是吗?)。

平台: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 吗? - Daniel Langr
#define M N 这段代码实际上是您的代码中的一部分,还是在这里提问时打错了? - Christian Gibbons
@ChristianGibbons,我在这里简化时打错了一个字。 - Amiri
3
虽然icc实现了并行for simd(gcc将忽略simd),但这不是适用于此情况的正确方法,因为内部循环(但不是外部循环)可以有效地使用simd。因此,您可以在内部放置omp simd,在外部放置omp parallel,但您可能会遇到内存带宽饱和,因此无法看到理想的加速。omp simd对内部循环的影响取决于编译器和选择的选项。 - tim18
@tim18,所以GCC(即使在2023年)说“GCC 11”忽略了“#pragma omp simd”指令?谢谢。 - velenos14
1个回答

10

来自OpenMP 4.5规范:

2.11.4 并行循环SIMD结构

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

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

#pragma omp parallel for simd ...

你也可以这样写:

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

我重新检查了一下,这种方法并不适合混合使用TLP和DLP。即使ICC也感到困惑!但是,非常感谢您!您为我节省了很多时间,我真的很感激。 - Amiri
@Martin 我猜你的算法受到内存带宽的限制,这通常会阻碍向量化和多线程的可扩展性。每个算术操作有2次加载和1次存储,即字节/操作比相当高。如果你想了解更多关于这个问题的信息,请搜索“内存墙”和“屋顶线模型”。 - Daniel Langr
谢谢,我记下了这些短语。你说得对,我测试了矩阵加法、矩阵转置、矩阵乘法、有限脉冲响应(FIR)滤波器、绝对差之和(SAD)、平方差之和(SSD)和矩阵卷积算法,它们都受到内存带宽的限制(我猜测)。 - Amiri
如何编写“parallel”参数(例如“private”,“first”等)和“simd”参数? - Royi
我认为这不是离题了。它只是让答案更完整而已。可能当它被分开时就没有问题了。问题是联合形式的正确语法是什么。 - Royi
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接