gpt4 book ai didi

c++ - 如何优化长系列的 If/then 条件表达式 - SIMD

转载 作者:太空宇宙 更新时间:2023-11-04 00:47:34 24 4
gpt4 key购买 nike

我正在使用 SIMD 来提高 C 代码的性能,但我遇到了一个具有许多 if/then 条件的函数,如下所示:

if (Di <= -T3) return  -4;
if (Di <= -T2) return -3;
if (Di <= -T1) return -2;
if (Di < -NEAR) return -1;
if (Di <= NEAR) return 0;
if (Di < T1) return 1;
if (Di < T2) return 2;
if (Di < T3) return 3;

return 4;

使用 VC++ 编译器支持的英特尔内部函数会导致处理时间变慢。

那么有没有更好的方法来优化这一长串条件表达式?

最佳答案

我假设几件事:

  1. 您处理 int32 数据(尽管它可以很容易地更改为 float32)。
  2. 您可以一次将 4 个值传递给您的函数(不只是一个)。这就是人们通常所说的矢量化
  3. 常量已排序,即 0 < NEAR < T1 < T2 < T3。

这是一个向量化函数:

__m128i func4(__m128i D) {
__m128i cmp_m3 = _mm_cmpgt_epi32(D, _mm_set1_epi32(-T3));
__m128i cmp_m2 = _mm_cmpgt_epi32(D, _mm_set1_epi32(-T2));
__m128i cmp_m1 = _mm_cmpgt_epi32(D, _mm_set1_epi32(-T1));
__m128i cmp_p0 = _mm_cmpgt_epi32(D, _mm_set1_epi32(NEAR));
__m128i reduce_true = _mm_add_epi32(_mm_add_epi32(cmp_m3, cmp_m2), _mm_add_epi32(cmp_m1, cmp_p0));
__m128i cmp_m0 = _mm_cmplt_epi32(D, _mm_set1_epi32(-NEAR));
__m128i cmp_p1 = _mm_cmplt_epi32(D, _mm_set1_epi32(T1));
__m128i cmp_p2 = _mm_cmplt_epi32(D, _mm_set1_epi32(T2));
__m128i cmp_p3 = _mm_cmplt_epi32(D, _mm_set1_epi32(T3));
__m128i reduce_false = _mm_add_epi32(_mm_add_epi32(cmp_p3, cmp_p2), _mm_add_epi32(cmp_p1, cmp_m0));
return _mm_sub_epi32(reduce_false, reduce_true);
}

如果输入数据是随机的,那么它在 Ivy Bridge 上使用 MSVC2013 x64 的速度比您的原始版本快 11 倍:

Time = 4.436   (-39910000)
Time = 0.409 (-39910000)

带有测试的完整代码可用here .

这个想法很简单。您可以在上面链接后的函数 funcX 中看到建议解决方案的非矢量化版本。它可能比语言更能解释一切。

我们将寄存器 D 作为输入,它包含 4 个打包值。然后我们将它与你拥有的所有 8 个常量与 _mm_cmp* 内在进行比较。此比较产生 8 个位掩码 cmp_pXcmp_mX。在位掩码中,与数字对应的所有位都为零或一。为每个比较设置 32 个零位,这是错误的。如果比较条件为真,则这 32 位设置为 1。

现在回想一下,全 1 位的 32 位整数在有符号表示中是 -1。当我们将四个比较结果加在一起时,我们得到一组否定的计数。最后,我们取两个计数的差值,就是我们想要的结果。

附言这是为内部循环生成的汇编代码:

movdqa  xmm3, XMMWORD PTR [rcx]
movdqa xmm4, xmm10
movdqa xmm0, xmm9
add rcx, 16
pcmpgtd xmm0, xmm3
pcmpgtd xmm4, xmm3
paddd xmm4, xmm0
movdqa xmm2, xmm3
movdqa xmm1, xmm8
pcmpgtd xmm1, xmm3
pcmpgtd xmm2, xmm14
movdqa xmm0, xmm7
pcmpgtd xmm0, xmm3
paddd xmm1, xmm0
paddd xmm4, xmm1
movdqa xmm0, xmm3
movdqa xmm1, xmm3
pcmpgtd xmm1, xmm12
pcmpgtd xmm0, xmm13
pcmpgtd xmm3, xmm11
paddd xmm1, xmm3
paddd xmm2, xmm0
paddd xmm2, xmm1
psubd xmm4, xmm2
paddd xmm4, xmm5
movdqa xmm5, xmm4
cmp rcx, r15
jl SHORT $LL3@main

关于c++ - 如何优化长系列的 If/then 条件表达式 - SIMD,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31743359/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com