为什么内联函数中的循环无法正确自动矢量化
Why loops in inline function cannot be properly auto-vectorized?
我正在尝试矢量化一些简单的计算,以便从 SIMD 架构加速。但是,我也想将它们作为内联函数,因为函数调用和非矢量化代码也需要计算时间。但是,我不能总是同时实现它们。事实上,我的大多数内联函数都无法自动矢量化。下面是一个简单的测试代码:
inline void add1(double *v, int Length) {
for(int i=0; i < Length; i++) v[i] += 1;
}
void call_add1(double v[], int L) {
add1(v, L);
}
int main(){return 0;}
在 Mac OS X 10.12.3 上,编译它:
clang++ -O3 -Rpass=loop-vectorize -Rpass-analysis=loop-vectorize -std=c++11 -ffast-math test.cpp
test.cpp:2:5: remark: vectorized loop (vectorization width: 2, interleaved count: 2) [-Rpass=loop-vectorize]
for(int i=0; i < Length; i++) v[i] += 1;
^
但是,非常相似的东西(仅在call_add1中移动参数(不起作用:
inline void add1(double *v, int Length) {
for(int i=0; i < Length; i++) v[i] += 1;
}
void call_add1() {
double v[20]={0,1,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9};
int L=20;
add1(v, L);
}
int main(){ return 0;}
使用相同的命令进行编译不会产生任何输出。为什么会这样?如何确保内联函数中的循环始终自动矢量化?我想矢量化许多函数循环,所以我希望修复不会很复杂。
使用 -fsave-optimization-record
编译代码会显示循环已展开,然后被消除。
--- !Passed
Pass: loop-unroll
Name: FullyUnrolled
DebugLoc: { File: main.cpp, Line: 2, Column: 5 }
Function: _Z9call_add1v
Args:
- String: 'completely unrolled loop with '
- UnrollCount: '20'
- String: ' iterations'
...
--- !Passed
Pass: gvn
Name: LoadElim
DebugLoc: { File: main.cpp, Line: 2, Column: 40 }
Function: _Z9call_add1v
Args:
- String: 'load of type '
- Type: double
- String: ' eliminated'
- String: ' in favor of '
- InfavorOfValue: '0.000000e+00'
如果将 4000 个元素放入数组,它将超过优化器阈值,并且 clang 将启用矢量化。
这是因为对于第二种情况,编译器知道没有副作用,并且仅使用-O3
叶子优化了 clang 4.0.0 https://godbolt.org/g/CnojEi 的所有内容:
call_add1():
rep ret
main:
xor eax, eax
ret
而且你没有得到关于循环魔术的营销。
在第一种情况下,编译器确实为函数生成了一些主体,因为函数确实修改了参数。如果将其编译为目标文件。您可以链接到此函数,它将起作用。我想如果参数是常量,那么也许函数也会留下空体。
当您打印出内容时,程序并不相同,但它们都使用矢量化指令:https://godbolt.org/g/KF1kNt
当显式指定v
时,编译器似乎只会展开并优化循环。这是一件好事:不必执行的代码是最快的。
为了验证它是优化,您可以尝试使某些变量不稳定(实时示例(。
相关文章:
- 为什么 openmp 的并行不适用于矢量化色彩空间转换?
- GCC 4.8.2 自动矢量化由于 cout 而失败
- 为什么浮点数的矢量化比双精度更有效?
- GCC、CLANG 和 MSVC 的可视化C++自动矢量化要求
- 如何使 msvc 矢量化浮点添加?
- 我可以期望某些 STL 函数实现是可自动矢量化的吗?
- 当在循环中使用时,std::shared_ptr 对该循环的矢量化有任何影响吗?
- 使用 size_t 初始化循环变量时的整数下溢
- 矢量化图像处理
- 用于自动矢量化的展开指针增量循环
- 对于使用 C 样式指针矢量化的循环,但不使用迭代器
- 为什么 GCC 不能矢量化这个函数和循环
- GCC自动矢量化在减少循环中失败
- OpenCL-循环的矢量化与线程内
- 如何自动矢量化基于范围的 for 循环
- AVX循环矢量化中的奇怪错误
- C++自动矢量化矩阵乘法循环
- 你能调试自动矢量化循环吗
- 矢量化/优化循环,用于宽寄存器(特别是Xeon Phi)的未对齐数据访问
- GCC 无法矢量化这个简单的循环("无法计算迭代次数"),但在同一代码中管理类似的循环?