循环中标量积的自动矢量化
Auto-vectorization of scalar product in loop
我正在尝试自动矢量化以下循环。在下文中,我们使用 i-
和 j-
循环遍历矩阵的下三角。不幸的是,矢量化报告无法矢量化(=转换为 AVX SIMD 指令)j 循环和 k 循环。但我认为这很简单,因为没有指针别名(#pragma ivdep
和编译器选项 -D NOALIAS
)并且数据(x: 1D-array 和 p: 1D-array)对齐到 64 字节。
可能 if
语句是一个问题,但即使使用 if
自由解决方案(昂贵的移位操作和计算双精度符号)编译器也不是能够向量化这个循环。
__assume_aligned(x, 64);
__assume_aligned(p, 64);
#pragma omp parallel for simd reduction(+:accum)
for ( int i = 1 ; i < N ; i++ ){ // loop over lower triangle (i,j), OpenMP SIMD LOOP WAS VECTORIZED
for ( int j = 0 ; j < i ; j++ ){ // <-- remark #25460: No loop optimizations reported
double __attribute__((aligned(64))) scalarp = 0.0;
#pragma omp simd
for ( int k=0 ; k < D ; k++ ){ // <-- remark #25460: No loop optimizations reported
// scalar product of \sum_k x_{i,k} \cdot x_{j,k}
scalarp += x[i*D + k] * x[j*D + k];
}
// Alternative to following if:
// accum += - ( (long long) floor( - ( scalarp + p[i] + p[j] ) ) >> 63);
#pragma ivdep
if ( scalarp + p[i] + p[j] >= 0 ){ // check if condition is satisfied
accum += 1;
}
}
}
它是否指的是每个 OpenMP 线程的 OpenMP 起点直到 运行 时间才知道的问题?我认为这解决了 simd
子句并且英特尔的自动矢量化知道这一点。
英特尔编译器:18.0.2 20180210
编辑:我查看了程序集,现在很明显代码已经矢量化了,很抱歉打扰了大家。
查看程序集确实很有帮助。代码已经矢量化。 OpenMP SIMD LOOP WAS VECTORIZED
在这种特殊情况下也处理内部循环。
我正在尝试自动矢量化以下循环。在下文中,我们使用 i-
和 j-
循环遍历矩阵的下三角。不幸的是,矢量化报告无法矢量化(=转换为 AVX SIMD 指令)j 循环和 k 循环。但我认为这很简单,因为没有指针别名(#pragma ivdep
和编译器选项 -D NOALIAS
)并且数据(x: 1D-array 和 p: 1D-array)对齐到 64 字节。
可能 if
语句是一个问题,但即使使用 if
自由解决方案(昂贵的移位操作和计算双精度符号)编译器也不是能够向量化这个循环。
__assume_aligned(x, 64);
__assume_aligned(p, 64);
#pragma omp parallel for simd reduction(+:accum)
for ( int i = 1 ; i < N ; i++ ){ // loop over lower triangle (i,j), OpenMP SIMD LOOP WAS VECTORIZED
for ( int j = 0 ; j < i ; j++ ){ // <-- remark #25460: No loop optimizations reported
double __attribute__((aligned(64))) scalarp = 0.0;
#pragma omp simd
for ( int k=0 ; k < D ; k++ ){ // <-- remark #25460: No loop optimizations reported
// scalar product of \sum_k x_{i,k} \cdot x_{j,k}
scalarp += x[i*D + k] * x[j*D + k];
}
// Alternative to following if:
// accum += - ( (long long) floor( - ( scalarp + p[i] + p[j] ) ) >> 63);
#pragma ivdep
if ( scalarp + p[i] + p[j] >= 0 ){ // check if condition is satisfied
accum += 1;
}
}
}
它是否指的是每个 OpenMP 线程的 OpenMP 起点直到 运行 时间才知道的问题?我认为这解决了 simd
子句并且英特尔的自动矢量化知道这一点。
英特尔编译器:18.0.2 20180210
编辑:我查看了程序集,现在很明显代码已经矢量化了,很抱歉打扰了大家。
查看程序集确实很有帮助。代码已经矢量化。 OpenMP SIMD LOOP WAS VECTORIZED
在这种特殊情况下也处理内部循环。