如何在 OpenMP 中使用缩减向量变量?

How to use reduction vector variable in OpenMP?

我想在 openmp 中使用 reduction 指令,但它不起作用。编译器错误说:

"reduction: OpenMP 'parallel for' empty factor in directive" (Visual studio 2015 community)

"reduction:^ needed scalar variable"

这是我的代码(字节是unsigned char

void RotXOR (const Byte *s, int n, Byte *t)
{
    int i = 0, q;
    q = n / 8; n %= 8;

    #pragma omp parallel for private(i) reduction()
    for (i = 0; i < 16; i++) {
        t[(q + i) % 16] ^= (s[i] >> n);

        if (n != 0) {
            t[(q + i + 1) % 16] ^= (s[i] << (8 - n));
        }
    }
}

来自 C/C++ 的 OpenMP 4.0 标准 p171:

Arrays may not appear in a reduction clause.

所以这样做的唯一方法是创建一个初始化为 0 的本地每线程 "tt" 数组,在其上计算并用 [=13= 更新 t ] 在并行部分退出时自动执行。

但无论如何,由于您的循环次数仅为 16,并行化开销将远远大于任何潜在收益,因此从我的角度来看,这只是一个死胡同。


编辑:这就是我的想法:

void RotXOR( const Byte *s, int n, Byte *t ) {
    int q = n / 8;
    n %= 8;

    #pragma omp parallel
    {
        int tt[] = { 0, 0, 0, 0,
                     0, 0, 0, 0,
                     0, 0, 0, 0,
                     0, 0, 0, 0 };
        #pragma omp for
        for ( int i = 0; i < 16; i++ ) {
            tt[( q + i ) % 16] ^= ( s[i] >> n );
            if ( n != 0 ) {
                tt[( q + i + 1 ) % 16] ^= ( s[i] << ( 8 - n ) );
            }
        }
        #pragma omp critical
        for ( int i = 0; i < 16; i++ ) {
            t[i] ^= tt[i];
        }
    }
}

而且我说我不期望性能有太大提升(如果有的话),因为行程计数非常小,不能在线程之间分配太多工作来隐藏线程管理的开销,以及顺序最终减少.

在写这个解决方案的时候,我想到了另一个,但我不知道这两个中哪个表现最好...我怀疑由于大量同步,第二个版本会比第一个版本更差t 的开销和虚假共享,但我不确定...

void RotXOR( const Byte *s, int n, Byte *t ) {
    int q = n / 8;
    n %= 8;

    #pragma omp parallel for
    {
        for ( int i = 0; i < 16; i++ ) {
            int idx = ( q + i ) % 16;
            int val = s[i] >> n;
            #pragma omp atomic
            t[idx] ^= val;
            if ( n != 0 ) {
                idx = ( q + i + 1 ) % 16;
                val = s[i] << ( 8 - n );
                #pragma omp atomic
                t[idx] ^= val;
            }
        }
    }
}

最后,由于 n 的值在输入时已知,我想从循环中删除 if 语句是个好主意,即使这意味着要多写一点代码。