X86 汇编/AVX、AVX2、FMA3、FMA4
外观
< X86 汇编
先决条件:X86 汇编/SSE.
以下程序展示了 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+12与v4+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)
- 虚拟机(为 Ubuntu 预先构建)和 VM 快照,用于在旧版 CPU 上测试新指令
- IEEE 754 单精度交互式小程序
- Intel AVX 简介
- Binutils 测试套件(用于 AT&T 和 Intel 语法中的 AVX 和 FMA 示例)
- http://sourceware.org/git/?p=binutils.git;a=blob_plain;f=gas/testsuite/gas/i386/fma.s;hb=HEAD
- http://sourceware.org/git/?p=binutils.git;a=blob_plain;f=gas/testsuite/gas/i386/fma4.s;hb=HEAD
- http://sourceware.org/git/?p=binutils.git;a=blob_plain;f=gas/testsuite/gas/i386/avx.s;hb=HEAD
- http://sourceware.org/git/?p=binutils.git;a=blob_plain;f=gas/testsuite/gas/i386/avx-gather.s;hb=HEAD
- http://sourceware.org/git/?p=binutils.git;a=blob_plain;f=gas/testsuite/gas/i386/avx2.s;hb=HEAD
- http://sourceware.org/git/?p=binutils.git;a=blob_plain;f=gas/testsuite/gas/i386/avx256int.s;hb=HEAD