返回介绍

24 章 使用 x64 下的 SIMD 来处理浮点数

发布于 2025-02-22 14:00:48 字数 1616 浏览 0 评论 0 收藏 0

当然,在增加了 x64 扩展这个特性之后,FPU 在 x86 兼容处理器中还是存在的。但是同事,SIMD 扩展(SSE, SSE2 等)已经有了,他们也可以处理浮点数。数字格式依然相同(使用 IEEE754 标准)。

所以,x86-64 编译器通常都使用 SIMD 指令。可以说这是一个好消息,因为这让我们可以更容易的使用他们。 24.1 简单的例子

#!cpp
double f (double a, double b)
{
    return a/3.14 + b*4.1;
};

清单 24.1: MSFC 2012 x64 /Ox

#!bash
__real@4010666666666666 DQ 04010666666666666r ; 4.1
__real@40091eb851eb851f DQ 040091eb851eb851fr ; 3.14
a$ = 8
b$ = 16
f PROC
    divsd xmm0, QWORD PTR __real@40091eb851eb851f
    mulsd xmm1, QWORD PTR __real@4010666666666666
    addsd xmm0, xmm1
    ret 0
f ENDP

输入的浮点数被传入了 XMM0-XMM3 寄存器,其他的通过栈来传递。 a 被传入了 XMM0,b 则是通过 XMM1。 XMM 寄存器是 128 位的(可以参考 SIMD22 一节),但是我们的类型是 double 型的,也就意味着只有一半的寄存器会被使用。

DIVSD 是一个 SSE 指令,意思是“Divide Scalar Double-Precision Floating-Point Values”(除以标量双精度浮点数值),它只是把一个 double 除以另一个 double,然后把结果存在操作符的低一半位中。 常量会被编译器以 IEEE754 格式提前编码。 MULSD 和 ADDSD 也是类似的,只不过一个是乘法,一个是加法。 函数处理 double 的结果将保存在 XMM0 寄存器中。

这是无优化的 MSVC 编译器的结果:

清单 24.2: MSVC 2012 x64

#!bash
__real@4010666666666666 DQ 04010666666666666r ; 4.1
__real@40091eb851eb851f DQ 040091eb851eb851fr ; 3.14
a$ = 8
b$ = 16
f PROC
    movsdx QWORD PTR [rsp+16], xmm1
    movsdx QWORD PTR [rsp+8], xmm0
    movsdx xmm0, QWORD PTR a$[rsp]
    divsd xmm0, QWORD PTR __real@40091eb851eb851f
    movsdx xmm1, QWORD PTR b$[rsp]
    mulsd xmm1, QWORD PTR __real@4010666666666666
    addsd xmm0, xmm1
    ret 0
f ENDP

有一些繁杂,输入参数保存在“shadow space”(影子空间,7.2.1 节),但是只有低一半的寄存器,也即只有 64 位存了这个 double 的值。

GCC 编译器生成了几乎一样的代码。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文