是否启用了 SSE2 指令?
Posted
技术标签:
【中文标题】是否启用了 SSE2 指令?【英文标题】:Are SSE2 instructions enabled? 【发布时间】:2018-08-10 15:09:24 【问题描述】:我有一个使用 sse2 内在函数的非常简单的 c++ 代码(我实际在做的一个最小示例)。
#include <xmmintrin.h>
int main()
__m128d a = 0,0;
__m128d b = 1,1;
__m128d c = a + b;
int t = c[0] >= 1;
return t;
我想检查加法是否确实编译为矢量化指令。我用g++ -S test.cpp
编译文件
我对这件事的理解是,如果我不将msse2
标志放入g++,则不会启用sse2。好像被g++ -Q --help=target
的结果证实了
-msse [disabled]
-msse2 [disabled]
-msse2avx [disabled]
-msse3 [disabled]
-msse4 [disabled]
-msse4.1 [disabled]
-msse4.2 [disabled]
-msse4a [disabled]
但是,在查看汇编代码时,似乎使用了addpd
指令。
main:
.LFB499:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $80, %rsp
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
pxor %xmm0, %xmm0
movaps %xmm0, -48(%rbp)
movapd .LC0(%rip), %xmm0
movaps %xmm0, -32(%rbp)
movapd -48(%rbp), %xmm0
addpd -32(%rbp), %xmm0
movaps %xmm0, -64(%rbp)
movsd -64(%rbp), %xmm0
pxor %xmm1, %xmm1
ucomisd %xmm1, %xmm0
setnb %al
movzbl %al, %eax
movl %eax, -68(%rbp)
movl -68(%rbp), %eax
movq -8(%rbp), %rdx
xorq %fs:40, %rdx
je .L3
call __stack_chk_fail
.L3:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE499:
.size main, .-main
.section .rodata
.align 16
.LC0:
.long 0
.long 1072693248
.long 0
.long 1072693248
.ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609"
.section .note.GNU-stack,"",@progbits
我在这里看到了一个矛盾,这让我觉得有些东西我不明白。 sse2 是否启用?
【问题讨论】:
在 64 位模式下它始终处于启用状态。 那我猜问题是我不太明白g++ -Q --help=target
做了什么。
--help=target
选项仅指您传递给 gcc 的命令行选项。见gcc.gnu.org/onlinedocs/gcc/Option-Index.html
您也可以使用-m32
创建 32 位二进制文件。不确定-Q --help=target
是否认为不同。
sse2 不是 AMD64 的扩展,它是基本指令集的一部分,因此“-msse”和“-msse2”参数不做任何事情,默认情况下它们可能处于关闭状态,但不会停止 gcc 生成 SSE2 代码
【参考方案1】:
我无法重现您的结果。
x86-64 g++ 确实启用了-msse
和-msse2
。您可以在 64 位模式下使用-mno-sse
禁用 SSE 代码生成(即使 SSE2 是 x86-64 的基线),在这种情况下 gcc 使用 x87 fld
实现 +
运算符/faddp
.
__m128d
被定义为具有两个 double
元素的 GNU C 本机向量,并且您没有使用任何内在函数。如果您使用_mm_set_pd
或_mm_add_pd
而不是将它们用作带有 大括号初始化列表和
+
运算符的本机向量的GNU 扩展语法,您会得到:
<source>:5:13: error: SSE register return with SSE disabled
__m128d c = _mm_add_pd(a, b);
有趣的是,即使禁用了 SSE2,它仍然会解析 xmmintrin.h
而不会出错,但仅限于 -O0
。启用优化后,它会注意到所有这些(内联)函数会在 SSE 寄存器中返回且 SSE 已禁用,即使您不调用它们也是如此。
您可以通过自己定义一个矢量类型来解决这个问题,例如typedef double v2d __attribute__((vector_size(16)))
。
On the Godbolt compiler explorer、gcc8.2 -m32
配置为默认启用 SSE2(尽管 SSE2 通常不是 32 位的基线)。
但 gcc6.3 -m32 默认不启用 SSE2,正如您在 -Q --help=target
输出中看到的那样。
当 SSE2 被禁用(明确地或根本没有使用 -m32
启用)时,我尝试过的任何组合都没有让 gcc 发出 addpd
。 AFAIK,那将是一个错误。
【讨论】:
以上是关于是否启用了 SSE2 指令?的主要内容,如果未能解决你的问题,请参考以下文章
#error “SSE2 指令集未启用”通过 pip 安装 scikit-bio 时
在 Visual Studio 中检测 SSE/SSE2 指令集的可用性
如何在 Code::Blocks 上启用 SSE/SSE2?