我想在reduction
中使用openmp
指令,但它不起作用。编译错误说:
"还原:OpenMP'并行用于'指令中的空因子" (Visual Studio 2015社区)
或
"减少:^需要标量变量"
这是我的代码(字节为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));
}
}
}
答案 0 :(得分:1)
从OpenMP 4.0标准p171 for C / C ++:
数组可能不会出现在减少条款中。
所以这样做的唯一方法就是创建一个本地的每线程&#34; tt&#34;数组初始化为0,在其上计算并在退出并行部分时以t
原子方式更新tt
。
但无论如何,由于你的环路跳数仅为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
语句是个好主意,即使它意味着要编写更多的代码。