我想在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
语句将是一个好主意,即使这意味着要编写更多的代码。