GCC -msse2 不生成 SIMD 代码
GCC -msse2 does not generate SIMD code
我想弄清楚为什么 g++ 不生成 SIMD 代码。
信息 GCC / OS / CPU:
$ gcc -v
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
$ cat /proc/cpuinfo
...
model name : Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz
...
这是我的 C++ 代码:
#include <iostream>
#include <cstdlib>
//function that fills an array with random numbers
template<class T>
void fillArray(T *array, int n){
srand(1);
for (int i = 0; i < n; i++) {
array[i] = (float) (rand() % 10);
}
}
// function that computes the dotprod of two vectors (loop unrolled)
float dotCPP(float *src1, float *src2, int n){
float dest = 0;
for (int i = 0; i < n; i+=2) {
dest += (src1[i] * src2[i]) + (src1[i+1] * src2[i+1]);
}
return dest;
}
int main(int argc, char *argv[])
{
const int n = 1200000;
float *a = new float[n]; //allocate data on the heap
float something_else; //store result
fillArray<float>(a,n); //function that fills the array with random numbers
something_else = dotCPP(a, a, n); //call function and store return value
return 0;
}
我编译代码:
makefile:
CXX = g++
CXXFLGS = -g -Wall -std=c++11 -msse2 -O3
SRC = main.o dot.o
EXEC = dot
$(EXEC): $(SRC)
$(CXX) $(CXXFLGS) $(SRC) -o $(EXEC)
main.o: dot.cpp
$(CXX) $(CXXFLGS) -c dot.cpp -o main.o
并使用 gdb 检查生成的代码:
$gdb dot
...
(gdb) b dotCPP
(gdb) r
...
(gdb) disass
Dump of assembler code for function dotCPP(float*, float*, int):
=> 0x08048950 <+0>: push %ebx
0x08048951 <+1>: mov 0x10(%esp),%ebx
0x08048955 <+5>: mov 0x8(%esp),%edx
0x08048959 <+9>: mov 0xc(%esp),%ecx
0x0804895d <+13>: test %ebx,%ebx
0x0804895f <+15>: jle 0x8048983 <dotCPP(float*, float*, int)+51>
0x08048961 <+17>: xor %eax,%eax
0x08048963 <+19>: fldz
0x08048965 <+21>: lea 0x0(%esi),%esi
0x08048968 <+24>: flds (%edx,%eax,4)
0x0804896b <+27>: fmuls (%ecx,%eax,4)
0x0804896e <+30>: flds 0x4(%edx,%eax,4)
0x08048972 <+34>: fmuls 0x4(%ecx,%eax,4)
0x08048976 <+38>: add [=13=]x2,%eax
0x08048979 <+41>: cmp %eax,%ebx
0x0804897b <+43>: faddp %st,%st(1)
0x0804897d <+45>: faddp %st,%st(1)
0x0804897f <+47>: jg 0x8048968 <dotCPP(float*, float*, int)+24>
0x08048981 <+49>: pop %ebx
0x08048982 <+50>: ret
0x08048983 <+51>: fldz
0x08048985 <+53>: pop %ebx
0x08048986 <+54>: ret
End of assembler dump.
现在我是不是遗漏了什么或者 gcc 应该使用 xmm 寄存器?
如果有任何建议可以帮助我理解为什么 gcc 不生成使用 xmm 寄存器的代码,我将不胜感激。
如果您需要任何进一步的信息,请告诉我。
-march=core2
意味着 gcc 可以假定(连同 64 位 ISA)最多 SSSE3(例如,MMX、SSE、SSE2、SSE3)可用。
-mfpmath=sse
可以强制使用 SSE 进行浮点运算(64 位模式下的默认值),而不是 387(32 位 -m32
模式下的默认值)。
参见:手册页中的 "Intel 386 and AMD x86-64 Options" 部分。
不幸的是,您仍然有 32 位模式和 32 位 ABI 的限制。例如,只有寄存器 XMM0 .. XMM7
可用; XMM8 .. XMM15
仅适用于 64 位模式。
我想弄清楚为什么 g++ 不生成 SIMD 代码。
信息 GCC / OS / CPU:
$ gcc -v
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
$ cat /proc/cpuinfo
...
model name : Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz
...
这是我的 C++ 代码:
#include <iostream>
#include <cstdlib>
//function that fills an array with random numbers
template<class T>
void fillArray(T *array, int n){
srand(1);
for (int i = 0; i < n; i++) {
array[i] = (float) (rand() % 10);
}
}
// function that computes the dotprod of two vectors (loop unrolled)
float dotCPP(float *src1, float *src2, int n){
float dest = 0;
for (int i = 0; i < n; i+=2) {
dest += (src1[i] * src2[i]) + (src1[i+1] * src2[i+1]);
}
return dest;
}
int main(int argc, char *argv[])
{
const int n = 1200000;
float *a = new float[n]; //allocate data on the heap
float something_else; //store result
fillArray<float>(a,n); //function that fills the array with random numbers
something_else = dotCPP(a, a, n); //call function and store return value
return 0;
}
我编译代码:
makefile:
CXX = g++
CXXFLGS = -g -Wall -std=c++11 -msse2 -O3
SRC = main.o dot.o
EXEC = dot
$(EXEC): $(SRC)
$(CXX) $(CXXFLGS) $(SRC) -o $(EXEC)
main.o: dot.cpp
$(CXX) $(CXXFLGS) -c dot.cpp -o main.o
并使用 gdb 检查生成的代码:
$gdb dot
...
(gdb) b dotCPP
(gdb) r
...
(gdb) disass
Dump of assembler code for function dotCPP(float*, float*, int):
=> 0x08048950 <+0>: push %ebx
0x08048951 <+1>: mov 0x10(%esp),%ebx
0x08048955 <+5>: mov 0x8(%esp),%edx
0x08048959 <+9>: mov 0xc(%esp),%ecx
0x0804895d <+13>: test %ebx,%ebx
0x0804895f <+15>: jle 0x8048983 <dotCPP(float*, float*, int)+51>
0x08048961 <+17>: xor %eax,%eax
0x08048963 <+19>: fldz
0x08048965 <+21>: lea 0x0(%esi),%esi
0x08048968 <+24>: flds (%edx,%eax,4)
0x0804896b <+27>: fmuls (%ecx,%eax,4)
0x0804896e <+30>: flds 0x4(%edx,%eax,4)
0x08048972 <+34>: fmuls 0x4(%ecx,%eax,4)
0x08048976 <+38>: add [=13=]x2,%eax
0x08048979 <+41>: cmp %eax,%ebx
0x0804897b <+43>: faddp %st,%st(1)
0x0804897d <+45>: faddp %st,%st(1)
0x0804897f <+47>: jg 0x8048968 <dotCPP(float*, float*, int)+24>
0x08048981 <+49>: pop %ebx
0x08048982 <+50>: ret
0x08048983 <+51>: fldz
0x08048985 <+53>: pop %ebx
0x08048986 <+54>: ret
End of assembler dump.
现在我是不是遗漏了什么或者 gcc 应该使用 xmm 寄存器?
如果有任何建议可以帮助我理解为什么 gcc 不生成使用 xmm 寄存器的代码,我将不胜感激。
如果您需要任何进一步的信息,请告诉我。
-march=core2
意味着 gcc 可以假定(连同 64 位 ISA)最多 SSSE3(例如,MMX、SSE、SSE2、SSE3)可用。
-mfpmath=sse
可以强制使用 SSE 进行浮点运算(64 位模式下的默认值),而不是 387(32 位 -m32
模式下的默认值)。
参见:手册页中的 "Intel 386 and AMD x86-64 Options" 部分。
不幸的是,您仍然有 32 位模式和 32 位 ABI 的限制。例如,只有寄存器 XMM0 .. XMM7
可用; XMM8 .. XMM15
仅适用于 64 位模式。