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 将两个 &lt;4 x i32&gt; 向量相加)。您仍然需要执行与上述类似的操作,只能替换 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:有效地对向量求和的主要内容,如果未能解决你的问题,请参考以下文章

在 LLVM IR 中,将整数存储到向量的第二个元素中

递归地对列表的元素求和

递归地对数组中的整数求和

拆分为逗号,而不是一个一个地对数值求和 c#

累计动态地对每个月的字段求和

使用相同的 ID 列递增地对列值求和