Nei*_*ice 10 c++ performance compiler-optimization visual-c++
使用VC++可以获得可衡量的性能提升__assume
吗?如果是这样,请在答案中张贴带代码和基准的证明.
关于__assume的稀疏MSDN文章:http://msdn.microsoft.com/en-us/library/1b3fsfxw( v = vs.100).aspx
文章提到在是利用__assume(0)
使switch
通过语句更快__assume(0)
荷兰国际集团的default
情况.我通过__assume(0)
这种方式测量的性能没有增加:
void NoAssumeSwitchStatement(int i)
{
switch (i)
{
case 0:
vector<int>();
break;
case 1:
vector<int>();
break;
default:
break;
}
}
void AssumeSwitchStatement(int i)
{
switch (i)
{
case 0:
vector<int>();
break;
case 1:
vector<int>();
break;
default:
__assume(0);
}
}
int main(int argc, char* argv[])
{
const int Iterations = 1000000;
LARGE_INTEGER start, middle, end;
QueryPerformanceCounter(&start);
for (int i = 0; i < Iterations; ++i)
{
NoAssumeSwitchStatement(i % 2);
}
QueryPerformanceCounter(&middle);
for (int i = 0; i < Iterations; ++i)
{
AssumeSwitchStatement(i % 2);
}
QueryPerformanceCounter(&end);
LARGE_INTEGER cpuFrequency;
QueryPerformanceFrequency(&cpuFrequency);
cout << "NoAssumeSwitchStatement: " << (((double)(middle.QuadPart - start.QuadPart)) * 1000) / (double)cpuFrequency.QuadPart << "ms" << endl;
cout << " AssumeSwitchStatement: " << (((double)(end.QuadPart - middle.QuadPart)) * 1000) / (double)cpuFrequency.QuadPart << "ms" << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
圆形控制台输出,1000000次迭代:
NoAssumeSwitchStatement:46ms
AssumeSwitchStatement:46ms
基准谎言.他们很少衡量你想要的东西.在这种特殊情况下,这些方法可能都是内联的,因此__assume
只是多余的.
至于实际问题,是的,它可能有所帮助.交换机通常由跳转表实现,通过减小该表的大小或删除一些条目,编译器可能能够选择更好的CPU指令来实现switch
.
在极端的情况下,它可以switch
变成一个if (i == 0) { } else { }
通常有效的结构.
此外,修剪死分支有助于保持代码整洁,较少的代码意味着更好地使用CPU指令缓存.
然而,这些是微观优化,它们很少得到回报:你需要一个分析器来指出它们,甚至它们可能很难理解要进行的特定转换(是__assume
最好的?).这是专家的工作.
编辑:与LLVM一起使用
void foo(void);
void bar(void);
void regular(int i) {
switch(i) {
case 0: foo(); break;
case 1: bar(); break;
}
}
void optimized(int i) {
switch(i) {
case 0: foo(); break;
case 1: bar(); break;
default: __builtin_unreachable();
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,唯一的区别是存在或不存在__builtin_unreachable()
与MSVC类似的情况__assume(0)
.
define void @regular(i32 %i) nounwind uwtable {
switch i32 %i, label %3 [
i32 0, label %1
i32 1, label %2
]
; <label>:1 ; preds = %0
tail call void @foo() nounwind
br label %3
; <label>:2 ; preds = %0
tail call void @bar() nounwind
br label %3
; <label>:3 ; preds = %2, %1, %0
ret void
}
define void @optimized(i32 %i) nounwind uwtable {
%cond = icmp eq i32 %i, 1
br i1 %cond, label %2, label %1
; <label>:1 ; preds = %0
tail call void @foo() nounwind
br label %3
; <label>:2 ; preds = %0
tail call void @bar() nounwind
br label %3
; <label>:3 ; preds = %2, %1
ret void
}
Run Code Online (Sandbox Code Playgroud)
并注意这里如何将switch
语句regular
优化为简单的比较optimized
.
这映射到以下x86程序集:
.globl regular | .globl optimized
.align 16, 0x90 | .align 16, 0x90
.type regular,@function | .type optimized,@function
regular: | optimized:
.Ltmp0: | .Ltmp3:
.cfi_startproc | .cfi_startproc
# BB#0: | # BB#0:
cmpl $1, %edi | cmpl $1, %edi
je .LBB0_3 | je .LBB1_2
# BB#1: |
testl %edi, %edi |
jne .LBB0_4 |
# BB#2: | # BB#1:
jmp foo | jmp foo
.LBB0_3: | .LBB1_2:
jmp bar | jmp bar
.LBB0_4: |
ret |
.Ltmp1: | .Ltmp4:
.size regular, .Ltmp1-regular | .size optimized, .Ltmp4-optimized
.Ltmp2: | .Ltmp5:
.cfi_endproc | .cfi_endproc
.Leh_func_end0: | .Leh_func_end1:
Run Code Online (Sandbox Code Playgroud)
请注意,在第二种情况下:
还要注意这是如此接近,以至于我不知道如何测量除噪音以外的任何东西......
另一方面,从语义上来说它确实表明了一个意图,尽管它assert
可能更适合语义.
如果设置正确的编译器开关似乎确实有所不同......
三次跟随.没有优化,选择速度和选择大小.
此运行没有优化
C:\temp\code>cl /EHsc /FAscu assume.cpp Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86 assume.cpp Microsoft (R) Incremental Linker Version 10.00.40219.01 /out:assume.exe assume.obj C:\temp\code>assume NoAssumeSwitchStatement: 29.5321ms AssumeSwitchStatement: 31.0288ms
这是最大优化(/ Ox)注意/ O2在速度上基本相同.
C:\temp\code>cl /Ox /EHsc /Fa assume.cpp Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86 assume.cpp Microsoft (R) Incremental Linker Version 10.00.40219.01 /out:assume.exe assume.obj C:\temp\code>assume NoAssumeSwitchStatement: 1.33492ms AssumeSwitchStatement: 0.666948ms
此次运行是为了最小化代码空间
C:\temp\code>cl -O1 /EHsc /FAscu assume.cpp Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86 assume.cpp Microsoft (R) Incremental Linker Version 10.00.40219.01 /out:assume.exe assume.obj C:\temp\code>assume NoAssumeSwitchStatement: 5.67691ms AssumeSwitchStatement: 5.36186ms
请注意,输出汇编代码与Matthiu M.在使用速度选项时必须说的内容一致.在其他情况下调用了开关功能.
归档时间: |
|
查看次数: |
2018 次 |
最近记录: |