使用 openMP simd 进行以下循环是否安全?
Is it safe to use openMP simd for following loops?
我只是更仔细地研究OpenMP simd结构,并且有三个循环似乎没有被gcc(简短的性能测试)矢量化,但我认为它们可以。所以我想知道,添加 simd 编译指示是否安全,以及为什么 gcc 不对它们进行矢量化。
第一个是矩阵乘法,其值存储为单个数组:
#pragma omp parallel for
for(size_t row = 0; row < 100; ++row){
{#pragma omp simd}
for(size_t col = 0; col < 100; ++col){
float sum = c[row * 100 + col];
for(size_t k = 0; k < 100; k++){
sum += a[rows * 100 + k] * b[k * 100 + col];
}
c[row * 100 + col] = sum;
}
我知道 b 没有转置,这阻碍了性能。通过添加 simd 编译指示,代码可以更快。由于内部循环,自动矢量化是不可能的吗?
对于第二个示例,我尝试了 OpenMP 的自定义减少声明功能,这实际上并不需要。
#pragma omp declare reduction(sum : double : omp_out += omp_in) initializer(omp_priv = omp_orig)
double red_result = 0;
#pragma omp parallel for {simd} reduction(sum:red_result)
for(size_t i = 0; i < 100; ++i){
red_result = red_result + a[i];
}
减少会阻止矢量化吗?因为我认为它应该可以正常工作吗?
最后一个示例是一个复杂的循环,具有另一个内部循环和函数调用。简化后,它看起来像这样:
#pragma omp parallel for {simd}
for(size_t i = 0; i < 100; ++i){
[..]
for(size_t j = 0; j < 100; j++){
if(j != i){
float k2 = a[i] - b[j];
k = std::sqrt(k2);
}
}
[do more with k]
}
所以这里的问题可能是 sqrt 调用,它无法矢量化?但是,使用simd编译指示的性能应该更好吗?一些简短的测试表明情况确实如此,但是如果由于 std::sqrt 而无法进行自动矢量化,为什么编译指示可以呢?
谢谢你的帮助! :)
对于math.h
中的数学函数,编译器需要实现数学函数的矢量化版本。 GCC 使用 libmvec 执行此操作,ICC 使用 SVML 执行此操作。据我所知,Clang没有对矢量化数学函数的原生支持。
让我们考虑以下代码:
void foo(float * __restrict a, float * __restrict b) {
a = (float*)__builtin_assume_aligned(a, 16);
b = (float*)__builtin_assume_aligned(b, 16);
for(int i = 0; i < 100; ++i) {
b[i] = sqrtf(a[i]);
}
}
void foo2(float * __restrict a, float * __restrict b) {
a = (float*)__builtin_assume_aligned(a, 16);
b = (float*)__builtin_assume_aligned(b, 16);
for(int i = 0; i < 100; ++i) {
b[i] = sinf(a[i]);
}
}
GCC、ICC 和 Clang 矢量化sqrtf
(使用牛顿方法的一次迭代)。GCC和ICC分别用libmvec(_ZGVbN4v_sinf
)和SVML(__svml_sinf4
)对sinf
进行矢量化。Clang不矢量化sinf
。见神霹雳。sqrt
是一种特殊情况(因为 x86 指令集具有矢量化sqrt
指令),可以在没有矢量化数学库的情况下内联。
相关文章:
- 使用 for 循环是否比在 C++ 中将内容保存在向量中更快?
- For 循环是否总是至少执行一次?
- 在不再满足条件后,while 循环是否停止验证?
- 使用 openMP simd 进行以下循环是否安全?
- while 循环是否在设置标志的情况下运行多次?
- 循环是否需要运行时间C++?
- 放置多个条件时,循环是否存在限制
- 在固定大小的数组上展开C++循环是否有益?
- 这个循环是否将int隐式转换为size_t
- r语言 - 在C++中使用 RCPP 的 NumericMatrix 循环是否是一个好的理想?
- 这无休止地循环是否有明显的原因
- 基于范围的 for 循环是否有利于性能
- 基于范围的 for 循环是否可以采用类型参数
- 在 C 和 C++ 中,for 循环是否可以将双精度值作为索引
- 基于范围的 for 循环是否缓存容器表达式,或每次迭代重新计算它
- 在Qt中,当事件循环线程拥有的QObject上的插槽正在执行时,QThread的事件循环是否会阻塞?
- 在vector上迭代时使用return语句退出循环是否安全?
- 在try-catch块中包装循环是否会导致性能问题?
- 分配器构造循环是否等于 std::uninitialized_copy
- 基于范围的'for'循环是否弃用了许多简单的算法?