【问题标题】:Vectorization & #pragma omp simd矢量化和#pragma omp simd
【发布时间】:2016-10-04 11:33:35
【问题描述】:

由于我在阅读 SIMD 和 OpenMP 依赖于矢量化的过程中迷失了方向,所以我想问你是否有人可以澄清我上面的问题。 具体来说,我有一部分要并行化的 C++ 代码,但我现在很忙,无法自己想办法。 任何帮助我弄清楚矢量化到底是什么以及如何在以下代码部分中使用它将不胜感激!

for(unsigned short i=1; i<=N_a; i++) {
        for(unsigned short j=1; j<=N_b; j++) {
            temp[0] = H[i-1][j-1]+similarity_score(seq_a[i-1],seq_b[j-1]);
            temp[1] = H[i-1][j]-delta;
            temp[2] = H[i][j-1]-delta;
            temp[3] = 0.;
            H[i][j] = find_array_max(temp, 4);
            switch(ind) {
            case 0:                                  // score in (i,j) stems from a match/mismatch
                I_i[i][j] = i-1;
                I_j[i][j] = j-1;
                break;
            case 1:                                  // score in (i,j) stems from a deletion in sequence A
                I_i[i][j] = i-1;
                I_j[i][j] = j;
                break;
            case 2:                                  // score in (i,j) stems from a deletion in sequence B
                I_i[i][j] = i;
                I_j[i][j] = j-1;
                break;
            case 3:                                  // (i,j) is the beginning of a subsequence
                I_i[i][j] = i;
                I_j[i][j] = j;
                break;
            }
        }
    }

问候!

【问题讨论】:

  • x86 上的 SIMD 都是关于加载 16B(或 32B)的连续数据,并执行例如四个floatadds并行,或者两个double,或者不同宽度的整数。或改组/混合/打包比较以获得混合掩码/ ...
  • H[i][j] 取决于H[i-1][j-1]、H[i-i][j] 和H[i][j-1],没有直接的方法来矢量化或并行化i 或j 中的循环。好吧,您可能可以使用#pragma omp simd 和#pragma omp parallel for 使编译器矢量化和/或并行化它们,但计算结果将是错误的。

标签: c++ openmp vectorization simd pragma


【解决方案1】:

所以ind 对于两个嵌套循环都是常量?

您可能会得到一个编译器来使用 OpenMP 为您自动矢量化它。 (将#pragma omp simd 行放在您的任一for 循环之前,看看当您使用-O3 编译时这是否会影响asm。我不太了解OpenMP,所以如果您需要其他选项,请IDK。)

将它包装在一个实际编译的函数中,这样我就可以看到会发生什么。 (例如,通过将代码放在 http://gcc.godbolt.org/ 上以获得格式良好的 asm 输出)。

如果它不自动矢量化,那么使用 x86 的英特尔内在函数手动矢量化可能并不难,因为您只是使用数组索引初始化一些数组。保持循环计数器的向量以__m128i jvec = _mm_set_epi32(3, 2, 1, 0); 开头,并以_mm_add_ps() 递增,向量[ 4 4 4 4 ] (_mm_set1_epi32(4)) 将每个元素递增4。

保留一个单独的 i 值向量,您只能在外循环中修改它,但仍存储在内循环中。


有关指令集的内容,请参阅 标签 wiki。

查看 标签wiki 了解一些SIMD 指南,包括这个不错的intro to SIMD and what it's all about.

【讨论】:

  • 但是我怎么知道输出被正确矢量化并且没有任何依赖关系?
  • @MrDiaman:通过查看 asm 输出。或者根据编译器,有一些选项可以报告自动矢量化的成功/失败。您担心什么样的依赖关系?
  • 我需要数据的准确性。所以我们在谈论数据依赖。我不知道这有多大帮助,在这里github.com/MrDiaman/Proj/pull/1/files
  • @MrDiaman:只有当编译器可以生成始终给出与 C 源代码应该给出的相同结果的代码时,编译器才会自动向量化。 (除非您使用-ffast-math,在这种情况下允许假设 FP 数学是关联的,即使这会影响舍入。)任何其他行为都是编译器错误。
  • 您的代码在简单的初始化循环中使用#pragma omp parallel。如果您的数组很大,那么如果您始终如一地使用它可能会有意义,因此同一个线程每次都会触及数组的同一部分(因此它可能在缓存中很热)。我认为您可以在 OpenMP 中同时使用 simd 和 parallel,但 this question 并没有说明这一点:/
猜你喜欢
  • 2016-05-03
  • 1970-01-01
  • 2021-04-09
  • 2021-03-22
  • 2020-07-24
  • 2014-05-12
  • 2018-07-20
  • 2013-09-20
  • 1970-01-01
相关资源
最近更新 更多