从SIMD指令捕获SIGFPE
问题描述:
我试图清除浮点除零标志忽略该异常。我期待与标志设置(没有改变我相信的默认行为,并在下面注释),我的错误处理程序将触发。然而,_mm_div_ss
似乎没有提高SIGFPE。有任何想法吗?从上面的代码从SIMD指令捕获SIGFPE
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <xmmintrin.h>
static void sigaction_sfpe(int signal, siginfo_t *si, void *arg)
{
printf("inside SIGFPE handler\nexit now.");
exit(1);
}
int main()
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = sigaction_sfpe;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGFPE, &sa, NULL);
//_mm_setcsr(0x00001D80); // catch all FPE except divide by zero
__m128 s1, s2;
s1 = _mm_set_ps(1.0, 1.0, 1.0, 1.0);
s2 = _mm_set_ps(0.0, 0.0, 0.0, 0.0);
_mm_div_ss(s1, s2);
printf("done (no error).\n");
return 0;
}
输出:
$ gcc a.c
$ ./a.out
done (no error).
正如你看到的,我的处理程序是从来没有达到过。附注:我已经尝试了几个不同的编译器标志(-msse3,-march = native),没有任何改变。
GCC(Debian的5.3.1-7)5.3.1 20160121
从/ proc一些信息内/ cpuinfo
model name : Intel(R) Core(TM) i3 CPU M 380 @ 2.53GHz
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 popcnt lahf_lm arat dtherm tpr_shadow vnmi flexpriority ept vpid
答
两件事情。
首先,我误解了文档。例外情况需要被捕获未被掩盖的。调用_mm_setcsr(0x00001D80);
将允许SIGFPE在被零除之前触发。
其次,即使使用-O0
,gcc也在优化我的除法指令。
鉴于源极线
_mm_div_ss(s1, s2);
与gcc -S -O0 -msse2 a.c
编译给出
76 movaps -24(%ebp), %xmm0
77 movaps %xmm0, -72(%ebp)
78 movaps -40(%ebp), %xmm0
79 movaps %xmm0, -88(%ebp)
a1 subl $12, %esp ; renumbered to show insertion below
a2 pushl $.LC2
a3 call puts
a4 addl $16, %esp
虽然源线
s2 = _mm_div_ss(s1, s2); // add "s2 = "
给出
76 movaps -24(%ebp), %xmm0
77 movaps %xmm0, -72(%ebp)
78 movaps -40(%ebp), %xmm0
79 movaps %xmm0, -88(%ebp)
movaps -72(%ebp), %xmm0
divss -88(%ebp), %xmm0
movaps %xmm0, -40(%ebp)
a1 subl $12, %esp
a2 pushl $.LC2
a3 call puts
a4 addl $16, %esp
通过这些更改,SIGFPE处理程序根据MXCSR中的除零标志被调用。
我认为你必须揭露MXCSR中的相关异常。所有FP异常在默认情况下都被屏蔽。我还没有试过编写一个从FP异常中产生信号的程序,但是如果这个常量是正确的,我会猜测你的'_mm_setcsr'会起作用。对于测试,您可以实际触发x86 Linux上的SIGFPE,除了POSIX所要求的整数除以零。 (http://*.com/questions/37262572/on-which-platforms-does-integer-divide-by-zero-trigger-a-floating-point-exceptio) –
即使有'_mm_setcsr(0x00001F80)'什么也没有发生。你是对的,我可以测试整数除零的SIGFPE,但我试图让MXCSR来控制是否发生这种情况。 – BurnsBA
无法编辑我的评论,但'_mm_setcsr(0x00000000)'具有相同的效果(未引发任何信号)。 – BurnsBA