LLVM IR:有效地对向量求和
Posted
技术标签:
【中文标题】LLVM IR:有效地对向量求和【英文标题】:LLVM IR: efficiently summing a vector 【发布时间】:2013-02-07 00:15:45 【问题描述】:我正在编写一个生成 LLVM IR 指令的编译器。我正在广泛使用向量。
我希望能够对向量中的所有元素求和。现在我只是单独提取每个元素并手动添加它们,但令我震惊的是,这正是硬件应该能够提供帮助的那种事情(因为这听起来像是一个非常常见的操作)。但似乎没有内在的去做。
最好的方法是什么?我正在使用 LLVM 3.2。
【问题讨论】:
【参考方案1】:首先,即使不使用内在函数,您也可以生成log(n)
向量加法(n 为向量长度)而不是n
标量加法,这是一个向量大小为 8 的示例:
define i32 @sum(<8 x i32> %a)
%v1 = shufflevector <8 x i32> %a, <8 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
%v2 = shufflevector <8 x i32> %a, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
%sum1 = add <4 x i32> %v1, %v2
%v3 = shufflevector <4 x i32> %sum1, <4 x i32> undef, <2 x i32> <i32 0, i32 1>
%v4 = shufflevector <4 x i32> %sum1, <4 x i32> undef, <2 x i32> <i32 2, i32 3>
%sum2 = add <2 x i32> %v3, %v4
%v5 = extractelement <2 x i32> %sum2, i32 0
%v6 = extractelement <2 x i32> %sum2, i32 1
%sum3 = add i32 %v5, %v6
ret i32 %sum3
如果您的目标支持这些向量添加,那么似乎很可能会降低上述内容以使用这些指令,从而为您提供性能。
关于内在函数,没有独立于目标的内在函数来处理这个问题。但是,如果您要编译到 x86,则可以访问 hadd
instrinsics(例如 llvm.x86.int_x86_ssse3_phadd_sw_128
将两个 <4 x i32>
向量相加)。您仍然需要执行与上述类似的操作,只能替换 add
指令。
更多信息可以搜索“水平和”或“水平向量和”;例如,这里有一些关于 x86 水平求和的相关 *** 问题:
horizontal sum of 8 packed 32bit floats Fastest way to do horizontal vector sum with AVX instructions Fastest way to do horizontal float vector sum on x86【讨论】:
我完全没有想到这一点。它优雅且运行良好 --- 我正在使用浮点数和双精度数,上面的代码反复变成六和七指令。我不认为我会做得比这更好(特别是如果代码是优化友好的)。还要感谢让 Google 开心的神奇关键字;当你知道它叫什么时,找到东西就容易多了……以上是关于LLVM IR:有效地对向量求和的主要内容,如果未能解决你的问题,请参考以下文章