c - 如何让 clang 向量化一个简单的循环?
问题描述
我有以下循环:
float* s;
float* ap;
float* bp;
... // initialize s, ap, bp
for(size_t i=0;i<64;++i) {
s[i] = ap[i]+bp[i];
}
似乎是矢量化的一个很好的候选者。虽然我打开了优化,但当我查看程序集输出时,clang(我正在使用 Xcode)似乎没有对循环进行矢量化:
LBB33_1: ## =>This Inner Loop Header: Depth=1
movss (%rax,%rsi,4), %xmm0 ## xmm0 = mem[0],zero,zero,zero
addss (%rcx,%rsi,4), %xmm0
movss %xmm0, (%rdx,%rsi,4)
Ltmp353:
incq %rsi
Ltmp354:
cmpq $64, %rsi
Ltmp355:
jne LBB33_1
如何让 clang/Xcode 向量化这个简单的循环?
解决方案
使用 clang/LLVM 的非古代版本。Apple clang/LLVM 与主线 clang/LLVM 不同,但它们共享一个共同的代码库。
主线 clang3.3 和更新的自动矢量化你的循环在-O3
. Clang3.4 和更新的自动矢量化它甚至在-O2
.
如果没有restrict
,clang确实会发出检查目标和两个源之间重叠的 asm(回退到标量),因此您将从float *restrict s
.
#include <stdlib.h>
void add_float_good(float *restrict s, float *restrict ap, float *restrict bp)
{
for(size_t i=0;i<64;++i) {
s[i] = ap[i]+bp[i];
}
}
使用clang3.4 -O3 (在 Godbolt 编译器资源管理器上)编译为这个简单的 asm,具有最差的索引寻址模式和循环开销,但至少它是矢量化的。较新的 clang 喜欢展开,尤其是在为最近的 Intel 进行调整时(例如-march=skylake
)
# clang3.4 -O3
add_float_good:
xor eax, eax
.LBB0_1: # %vector.body
movups xmm0, xmmword ptr [rsi + 4*rax]
movups xmm1, xmmword ptr [rdx + 4*rax]
addps xmm1, xmm0
movups xmmword ptr [rdi + 4*rax], xmm1
add rax, 4
cmp rax, 64
jne .LBB0_1
ret
请注意,如果没有 AVX,它就不能使用内存源操作数,addps
因为没有编译时对齐保证。
clang8.0 -O3 -march=skylake 使用 YMM 向量完全展开,就像 gcc 具有相同的选项。
推荐阅读
- php - DateTimeZone 只处理一个方向的偏移量
- whatsapp - 如何使用 chat-api 向 whatsapp 组发送消息
- r - 什么是 RStudio 项目 (.Rproj)?
- javascript - 如何从多部分/表单数据中获取文本值
- java - Java编程用户定义类
- mysql - MySQL将一个子字符串与另一个字符串进行比较,如果匹配,我会得到匹配百分比
- python-3.7 - 如何使用 chromebook 空闲版本 python 3.7.3 shell 导入 CSV 文件
- c++ - 防止包含恶意 shell 脚本的代码条目
- python - Python包安装在哪个目录?[MAC]
- html - 如何在html中的表格中插入表格并合并几列