C++ 内联汇编优化
c++ inline assembly optimizations
为什么 Visual Studio C++ 编译器默认不优化以下代码?
#include "ctime"
#include "iostream"
#define BIG_NUM 10000000000
int main() {
std::clock_t begin = clock();
for (unsigned long long i = 0; i < BIG_NUM; ++i) {
__asm
{
nop
}
}
std::clock_t end = clock();
std::cout << "time: " << double(end - begin) / CLOCKS_PER_SEC;
std::cin.get();
}
没有 _asm
块,操作时间始终为 0,因为循环 "skipped" 完全是由于编译器优化。使用 _asm
块需要几秒钟。
是否有任何编译器标志可以优化内联汇编或由于某些不明原因不可能?
编译器并不真正理解内联汇编,因此假定它可以做任何事情。
当您特别想在低级别优化某些代码时,通常使用内联汇编。如果你这样做了,为什么你期望编译器进一步优化它?
为已接受的答案添加更多信息
1) 一些 编译器可以跨内联 asm 进行优化 - Xbox 360 编译器可以,但这些可能是例外而不是规则。
2) 有一些工具可以 运行 优化已编译的二进制文件 e.g. here - 这些很可能能够优化内联 asm。
3) 最后,也许最恰当的是,添加内联 asm 的最常见原因之一是手动执行数学繁重的矢量化 SIMD 例程,这些例程对于编译器来说太复杂了,无法自行完成。如果你想要这个,那么更好的方法是使用 intrinsics。内在函数让您两全其美 - 您可以手动滚动棘手的例程,然后让编译器为您处理寄存器分配、展开、交错、死代码 p运行ing 等。
有关内在函数的一个很好的例子,请参见下面的示例 - 如果定义了 'INLINE_ASM',它需要大约 300 毫秒,否则它被优化为空,即使它们做类似的事情也需要 0 毫秒。
#include <windows.h>
#include <iostream>
int main()
{
auto tc = ::GetTickCount();
for(int i=0; i<1024 * 1024 * 1024; ++i)
{
#if INLINE_ASM
_asm
{
paddw xmm0, xmm0;
}
#else
_mm_add_epi16(__m128i(), __m128i());
#endif
}
std::cout << "Took " << ::GetTickCount()-tc << " milli-seconds!" << std::endl;
}
为什么 Visual Studio C++ 编译器默认不优化以下代码?
#include "ctime"
#include "iostream"
#define BIG_NUM 10000000000
int main() {
std::clock_t begin = clock();
for (unsigned long long i = 0; i < BIG_NUM; ++i) {
__asm
{
nop
}
}
std::clock_t end = clock();
std::cout << "time: " << double(end - begin) / CLOCKS_PER_SEC;
std::cin.get();
}
没有 _asm
块,操作时间始终为 0,因为循环 "skipped" 完全是由于编译器优化。使用 _asm
块需要几秒钟。
是否有任何编译器标志可以优化内联汇编或由于某些不明原因不可能?
编译器并不真正理解内联汇编,因此假定它可以做任何事情。
当您特别想在低级别优化某些代码时,通常使用内联汇编。如果你这样做了,为什么你期望编译器进一步优化它?
为已接受的答案添加更多信息
1) 一些 编译器可以跨内联 asm 进行优化 - Xbox 360 编译器可以,但这些可能是例外而不是规则。
2) 有一些工具可以 运行 优化已编译的二进制文件 e.g. here - 这些很可能能够优化内联 asm。
3) 最后,也许最恰当的是,添加内联 asm 的最常见原因之一是手动执行数学繁重的矢量化 SIMD 例程,这些例程对于编译器来说太复杂了,无法自行完成。如果你想要这个,那么更好的方法是使用 intrinsics。内在函数让您两全其美 - 您可以手动滚动棘手的例程,然后让编译器为您处理寄存器分配、展开、交错、死代码 p运行ing 等。
有关内在函数的一个很好的例子,请参见下面的示例 - 如果定义了 'INLINE_ASM',它需要大约 300 毫秒,否则它被优化为空,即使它们做类似的事情也需要 0 毫秒。
#include <windows.h>
#include <iostream>
int main()
{
auto tc = ::GetTickCount();
for(int i=0; i<1024 * 1024 * 1024; ++i)
{
#if INLINE_ASM
_asm
{
paddw xmm0, xmm0;
}
#else
_mm_add_epi16(__m128i(), __m128i());
#endif
}
std::cout << "Took " << ::GetTickCount()-tc << " milli-seconds!" << std::endl;
}