C语言 如何使用减少向量变量在OpenMP



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

" reduce: OpenMP 'parallel for'指令中的空因子"(Visual studio 2015社区)

"reduction:^所需标量变量"

这是我的代码(字节是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));
        }
    }
}

来自openmp4.0标准p171 for C/c++:

数组不能出现在缩减子句中。

因此,这样做的唯一方法是创建一个初始化为0的本地每线程"tt"数组,在其上进行计算,并在退出并行部分时自动使用tt更新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语句将是一个好主意,即使这意味着要编写更多的代码。

最新更新