跳转到内容

X86 汇编/AVX、AVX2、FMA3、FMA4

来自维基教科书,开放的书籍,开放的世界

先决条件:X86 汇编/SSE.

FMA4 程序示例

[编辑 | 编辑源代码]

以下程序展示了 FMA4 指令的使用vfmaddps它可以用于在一行指令中执行 8 个单精度浮点乘加运算。

.data
        #          2^-1  2^-2  2^-3   2^-4    2^-5     2^-6      2^-7       2^-8
        v1: .float 0.50, 0.25, 0.125, 0.0625, 0.03125, 0.015625, 0.0078125, 0.00390625
        v2: .float 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0
        v3: .float 512.0, 1024.0, 2048.0, 8192.0, 16384.0, 32768.0, 65536.0, 131072.0
        v4: .float 0,0,0,0,0,0,0,0
.text
.globl _start
        _start:
        vmovups v1,%ymm0
        vmovups v2,%ymm1
        vmovups v3,%ymm2
        #        addend + multiplicant1   * multiplicant2   = destination
        vfmaddps %ymm0,   %ymm1,            %ymm2,            %ymm3
        vmovups %ymm3, v4

如果在最后一行代码后设置断点,可以使用 GDB 分析结果。查看程序并尝试找出任何问题。

剧透警告。以二进制形式转储结果“向量”,我们可以看到精度已经丢失。

(gdb) x/8t &v4
0x80490fc <v4>:    01000100100000000001000000000000	01000101100000000000001000000000	01000110100000000000000001000000	01001000000000000000000000000100
0x804910c <v4+16>: 01001001000000000000000000000000	01001010000000000000000000000000	01001011000000000000000000000000	01001100000000000000000000000000
(gdb)

比较v4+12v4+16,可以看出加数变得太小,丢失了。我们只是将其从 +12 减半到 +16,为什么现在没有了?原因是指数也发生了改变,因此加数将放置在比前一个尾数的最后一个设置位少一位的位数上。因此,它变得非常小,以至于 32 位单精度浮点数无法表示它。当以其基数 10 表示形式转储浮点数时,数据丢失也可见,但需要注意,因为基数 10 表示形式并不总是忠实的。

(gdb) x/8f &v4
0x80490fc <v4>:    1024.5	4096.25	16384.125	131072.062
0x804910c <v4+16>: 524288	2097152	8388608		33554432
(gdb)
华夏公益教科书