gpt4 book ai didi

c - 天真的梯形逻辑比因式逻辑更好吗?

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

这里是新手...

我正在测试具有嵌套逻辑的例程的两种实现:一种是朴素的实现,另一种是我巧妙地尝试删除一些分支的实现。我在 x86 Merom 上使用“gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3”,gcc 选项为“-ffast-math -fomit-frame-pointer -msseregparm -mfpmath=sse -msse2”。代码如下:

#define math_sign(a) ( (a) < .0f ? -1.f : +1.f )

inline float math_interp_clamp(float a, float slope, float target)
{
#if 0
// 5 instr, 1 branch
float b = a + slope;
return slope > 0.f ? (b > target ? target : b) : (b < target ? target : b);
#else
// 19 instr
float b = a + slope;
return ( b - target ) * math_sign( slope ) > 0.f ? target : b;
#endif
}

启用 ifdef 后,我得到:

math_interp_clamp:
.LFB505:
.cfi_startproc
comiss .LC7, %xmm1
addss %xmm1, %xmm0
jbe .L44
minss %xmm0, %xmm2
movaps %xmm2, %xmm0
ret
.L44:
maxss %xmm0, %xmm2
movaps %xmm2, %xmm0
ret
.cfi_endproc

在禁用 ifdef 的情况下,我得到:

math_interp_clamp:
.LFB505:
.cfi_startproc
xorps %xmm5, %xmm5
addss %xmm1, %xmm0
movss .LC3, %xmm4
cmpltss %xmm5, %xmm1
movss .LC2, %xmm6
movaps %xmm0, %xmm3
andps %xmm1, %xmm4
andnps %xmm6, %xmm1
subss %xmm2, %xmm3
orps %xmm4, %xmm1
mulss %xmm1, %xmm3
movaps %xmm5, %xmm1
cmpltss %xmm3, %xmm1
movaps %xmm2, %xmm3
movaps %xmm1, %xmm2
andps %xmm1, %xmm3
andnps %xmm0, %xmm2
orps %xmm3, %xmm2
movaps %xmm2, %xmm0
ret
.cfi_endproc

我实际上并没有为生成的代码计时,但基于循环计数,我无法想象这 19 条指令比单纯的分支更快......我应该多么无情地避免分支,或者我正在使用gcc 错了吗?

我们慷慨地接受了一个很好的计时方法或 sse 教程的链接。

最佳答案

gcc 4.9.2 将无分支版本编译为 16 条指令。或者像你一样的 19 个 -m32 -msse但不是 -m32 -msse2 .这些指令中有相当多的并行性,但不幸的是,FP 逻辑(如 orps )只能在当前英特尔设计中的单个端口上运行。 (与能够接受 por 微指令的所有 3 个 vector ALU 端口相比。)

gcc 使用 -O3 -ffast-math 无分支地编译您的“原始”版本. (没有 -ffast-math ,它仍然使用分支。我没有检查位操作以查看即使使用 NaN 结果是否相同。)可能有一种方法可以编写您的原始版本,以便它可以制作无分支版本即使没有-ffast-math .也许通过 !(b < target)而不是 b > target ,所以 NaN 处理是一样的? IDK.

math_interp_clamp:  # gcc 4.9.2 -O3 -ffast-math
.LFB0:
addss %xmm1, %xmm0
movaps %xmm0, %xmm3
maxss %xmm2, %xmm3
minss %xmm0, %xmm2
pxor %xmm0, %xmm0
cmpltss %xmm1, %xmm0
andps %xmm0, %xmm2
andnps %xmm3, %xmm0
orps %xmm2, %xmm0
ret

这很可能是一次胜利,除非分支是非常可预测的(即值几乎不需要限制)。你最好的是-fprofile-generate/-fprofile-use , 让编译器决定。

出于好奇,我查看了 x87 的无分支版本 ( -m32 -O3 )。即使 x87 有 fcmovbe ,它仍然编译为 19 个 insns,因为 x87 需要额外的指令来弹出堆栈(并且函数 args 不以 regs 开头)。

没有cmov基于 xmm 寄存器的标志。打包cmovandps / pand 完成或 blendv基于掩码寄存器。

关于c - 天真的梯形逻辑比因式逻辑更好吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23210858/

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