OpenMP 4.0中“simd”构造和“for simd”构造的区别

6
OpenMP 4.0引入了SIMD结构,以利用CPU的SIMD指令。根据规范http://www.openmp.org/mp-documents/OpenMP4.0.0.pdf,有两个结构可用于使用simd来向量化循环。一个是"#pragma omp simd",另一个是"#pragma omp for simd"。根据规范,两者都用于向量化for循环。我也进行了测试,没有发现它们之间的区别。是否有人知道这两个结构之间有什么区别?

你尝试过使用pragma omp parallel for simd吗? - Z boson
1个回答

11

#pragma omp simd(SIMD结构)指示OpenMP编译器对接下来的循环进行向量化,而不进行工作共享,也就是说不将循环迭代在多个线程之间分配(如果有的话)。

#pragma omp for(循环结构)指示编译器在当前团队的线程之间分配工作时执行以下循环。因此,循环结构只有在并行区域的词法或动态作用域内使用时才有用,例如:

#pragma omp parallel
{
   ...
   #pragma omp for
   for (i = 0; i < 100; i++) { ... }
   ...
}

#pragma omp for simd(也称为循环SIMD结构)将上述两种结构相结合,即将迭代空间分配给团队中的线程,并进一步矢量化每个线程执行的部分循环。如果未在并行区域范围内使用,则for simd结构等效于simd结构。

可以将循环SIMD结构与parallel结构相结合:

#pragma omp parallel for simd
for (i = 0; i < 100; i++) { ... }

这个结构将创建一个并行区域,在线程之间分配循环的迭代,并对部分循环进行矢量化。

请注意,有时候矢量化和多线程在性能上不是正交的。例如,如果循环受到内存限制,则单独使用矢量化和多线程都可能导致可用内存带宽的耗尽,同时将它们组合起来也不会带来进一步的加速。

此外,在比较速度提升方面,使用#pragma omp simd#pragma omp [parallel] for simd时,请记住,仅使用多线程通常比相同数量的"重复计算"的矢量化提供更好的速度提升,即具有四路SIMD的循环(最有可能)比使用标量指令但分裂成四个线程的相同循环执行得更慢。


2
我不理解omp simd的意义。我的意思是,许多编译器已经通过自动向量化做得很好了。omp simd有什么优势呢? - Z boson
@Zboson,我猜想,这个想法是用一个标准化的向量化编译指示符来替换许多特定于供应商的向量化编译指示符。这也是OpenMP最初所做的。 - Hristo Iliev
1
对于一些编译器,如gcc,omp simd唯一的正常作用是忽略可能防止向量化的依赖关系。在许多情况下,它具有类似于restrict限定符的效果,但超出了这个范围。对于其他编译器,如icc,omp simd还有一个额外的效果,即设置更激进的编译选项,以便在循环中本地使用。例如,假设fp-model source已经设置,在omp simd循环内部将好像设置了-fp-model fast。这影响simd向量归约和隐式向量数学库调用,例如。 - tim18
需要注意的一点是,除了 simdlen 子句之外,编译器可以自由选择用于循环的SIMD长度。这意味着编译器也可能使用SIMD长度1,即标量代码用于 simd 结构。 - Michael Klemm

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