c++ - _mm_fmadd_pd 程序收到信号 SIGILL,非法指令

标签 c++ x86 simd intrinsics fma

我收到以下代码的奇怪错误:

#include <assert.h>
#include <stdio.h>
#include <immintrin.h>

inline static double myfma(double x,double y, double z) {
    double r; // result                                                                                                                                                     
    __m128d xx, yy, zz,rr;

    xx = _mm_set_sd(x);// xx[0]=x, xx[1]=undefined                                                                                                                          
    yy = _mm_set_sd(y);// yy[0]=y, yy[1]=undefined                                                                                                                          
    zz = _mm_set_sd(z);// zz[0]=z, zz[1]=undefined                                                                                                                          
    r = _mm_cvtsd_f64(_mm_fmadd_pd(xx,yy,zz));

    return r;
}

void testfma() {
    double x, y, z, res;
    x = 1.0;
    y = 2.0;
    z = 3.0;

    res =  myfma(x,y,z);
    printf("test: res = x*y + z \n");
    printf("    x: %g\n", x);
    printf("    y: %g\n", y);
    printf("    z: %g\n", z);
    assert(res == 5.0);
}


int main() {
    testfma();
    return 0; 
}

将代码编译为:

g++ test.cpp -o a.out -std=c++11 -mavx2 -mfma  -march=native -g

当我运行可执行文件时,我收到消息:

Illegal instruction (core dumped)

使用 gdb 以获得更多详细信息:

gdb ./a.out
(gdb) r
(gdb) r
Starting program: ....

Program received signal SIGILL, Illegal instruction.
0x000000000040067d in _mm_fmadd_pd(double __vector(2), double __vector(2), double __vector(2)) (__C=..., __B=..., __A=...)
    at /usr/lib/gcc/x86_64-linux-gnu/5/include/fmaintrin.h:42
42                                                 (__v2df)__C);

但是当使用 valgrind 如下时:

valgrind ./a.out
==9825== Memcheck, a memory error detector
==9825== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==9825== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright 

info
==9825== Command: ./helios.x
==9825== 
test: res = x*y + z 
    x: 1
    y: 2
    z: 3
    res: 5
==9825== 
==9825== HEAP SUMMARY:
==9825==     in use at exit: 0 bytes in 0 blocks
==9825==   total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==9825== 
==9825== All heap blocks were freed -- no leaks are possible
==9825== 
==9825== For counts of detected and suppressed errors, rerun with: -v
==9825== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

该程序似乎正在运行。我在这里缺少什么?如何以可靠的方式使用 _mm_fmadd_pd?无论是在 Intel 还是 AMD 处理器上运行,都可以使示例正常工作吗?不管用g++还是icpc都能编译成功吗?

最佳答案

我猜你的 CPU 不支持 FMA 指令。它在 valgrind 下不会失败的原因是因为 valgrind 可以模拟某些指令。

您可能要考虑使用 std::fma如果你只想要 SISD。 With gcc it generates an inline FMA instruction , 但如果你为非 FMA 目标编译那么它会 fall back to a non-FMA implementation .

关于c++ - _mm_fmadd_pd 程序收到信号 SIGILL,非法指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42853867/

相关文章:

assembly - 为什么在使用DIV指令之前EDX必须为0?

linux - ebx 寄存器在 NASM 中不起作用,但 ecx 可以工作

c# - Visual Studio 的 'watch' 错误地将 Vector<float> 中的一半数字显示为零

c++ - 为什么模板类的静态成员不是唯一的

c++ - unsigned char 在函数调用中自动提升为int,为什么?

assembly - x86_32 虚拟 8086 和实模式是否支持扩展通用和专用寄存器?

c++ - 用 sse 累加整数 vector

c++ - C++ 中的继承成本

c# - Arduino 使用 USB 连接到 Mysql

c - 如何解决vfmadd213ps的 "illegal instruction"?