C/C++:-msse 和 -msse2 标志对二进制文件没有任何影响?
C/C++: -msse and -msse2 Flags do not have any effect on the binaries?
我只是在玩弄 gcc (g++) 和编译器标志 -msse 和 -msse2。我有一个看起来像这样的小测试程序:
#include <iostream>
int main(int argc, char **argv) {
float a = 12558.5688;
float b = 6.5585;
float result = 0.0;
result = a * b;
std::cout << "Result: " << result << std::endl;
return 0;
}
当我用下面的语句编译它时:
/usr/local/bin/g++-4.9 -W -msse main.cpp -o testsse
和
/usr/local/bin/g++-4.9 -W -msse2 main.cpp -o testsse2
输出文件是二进制的。但由于 SMID 标志,我预计它们不相同。
所以我的问题是,那些编译器标志对二进制文件没有任何影响吗?我已经在 OS X 10.10.3 和 Fedora 21 上测试过它。
感谢您的帮助。
亲切的问候
法比安
在您的代码中涉及非常基本的浮点数学运算。我敢打赌,如果你打开优化(甚至 -O1
),它就会被优化掉,因为这些值是常量表达式,因此可以在编译时计算。
使用 SSE (movss
, mulss
) 因为它是浮点微积分的阈值,如果我们愿意的话。 SSE2 在这里没有作用域。
为了为 SSE2 找到空间,您需要包含更复杂的微积分,这些微积分可能会或可能不会利用 SSE2 中可用的某些指令;你可以看看有些人做了什么,做他们的等价物,看看编译器是否可以利用它们。
您需要知道的第一件事是 SSE2 和 SSE 默认情况下已启用并用于 64 位代码。对于 32 位代码,默认为 x87 指令。
您需要知道的第二件事是双精度浮动需要 SSE2,因此如果您想在示例中看到 SSE 和 SSE2 之间的区别,您应该将双精度浮点数与浮点数进行比较。
您需要知道的第三件事是如何说服您的编译器不要优化您的计算。一种方法是将您的代码包装在这样的函数中:
//foo.cpp
float foof(float x, float y) {
return x*y;
}
double food(double x, double y) {
return x*y;
}
然后 g++ -O3 -S foo.cpp
显示 foof
使用 mulss
而 food
使用 mulsd
。如果您想确保它获得正确的结果,您可以 link 像这样
//main.cpp
#include <iostream>
extern float foof(float, float);
extern double food(double, double);
int main(void) {
float af = 12558.5688;
float bf = 6.5585;
float resultf = 0.0;
double ad = af;
double bd = bf;
double resultd = 0.0;
resultf = foof(af, bf);
resultd = food(ad, bd);
std::cout << "Resultf: " << resultf << " Resultd: " << resultd << std::endl;
}
然后g++ -O3 -c foo.cpp
然后g++ -O3 main.cpp foo.o
。
如果要禁用 SSE 指令,请使用 -mfpmath=387
或使用 -m32
在 32 位模式下编译。
我只是在玩弄 gcc (g++) 和编译器标志 -msse 和 -msse2。我有一个看起来像这样的小测试程序:
#include <iostream>
int main(int argc, char **argv) {
float a = 12558.5688;
float b = 6.5585;
float result = 0.0;
result = a * b;
std::cout << "Result: " << result << std::endl;
return 0;
}
当我用下面的语句编译它时:
/usr/local/bin/g++-4.9 -W -msse main.cpp -o testsse
和
/usr/local/bin/g++-4.9 -W -msse2 main.cpp -o testsse2
输出文件是二进制的。但由于 SMID 标志,我预计它们不相同。
所以我的问题是,那些编译器标志对二进制文件没有任何影响吗?我已经在 OS X 10.10.3 和 Fedora 21 上测试过它。
感谢您的帮助。
亲切的问候
法比安
在您的代码中涉及非常基本的浮点数学运算。我敢打赌,如果你打开优化(甚至 -O1
),它就会被优化掉,因为这些值是常量表达式,因此可以在编译时计算。
SSE (movss
, mulss
) 因为它是浮点微积分的阈值,如果我们愿意的话。 SSE2 在这里没有作用域。
为了为 SSE2 找到空间,您需要包含更复杂的微积分,这些微积分可能会或可能不会利用 SSE2 中可用的某些指令;你可以看看有些人做了什么,做他们的等价物,看看编译器是否可以利用它们。
您需要知道的第一件事是 SSE2 和 SSE 默认情况下已启用并用于 64 位代码。对于 32 位代码,默认为 x87 指令。
您需要知道的第二件事是双精度浮动需要 SSE2,因此如果您想在示例中看到 SSE 和 SSE2 之间的区别,您应该将双精度浮点数与浮点数进行比较。
您需要知道的第三件事是如何说服您的编译器不要优化您的计算。一种方法是将您的代码包装在这样的函数中:
//foo.cpp
float foof(float x, float y) {
return x*y;
}
double food(double x, double y) {
return x*y;
}
然后 g++ -O3 -S foo.cpp
显示 foof
使用 mulss
而 food
使用 mulsd
。如果您想确保它获得正确的结果,您可以 link 像这样
//main.cpp
#include <iostream>
extern float foof(float, float);
extern double food(double, double);
int main(void) {
float af = 12558.5688;
float bf = 6.5585;
float resultf = 0.0;
double ad = af;
double bd = bf;
double resultd = 0.0;
resultf = foof(af, bf);
resultd = food(ad, bd);
std::cout << "Resultf: " << resultf << " Resultd: " << resultd << std::endl;
}
然后g++ -O3 -c foo.cpp
然后g++ -O3 main.cpp foo.o
。
如果要禁用 SSE 指令,请使用 -mfpmath=387
或使用 -m32
在 32 位模式下编译。