[英]What's causing this exception? Using VC++ 2010 with libcurl
[英]Are measurable performance gains possible from using VC++'s __assume?
使用VC ++的__assume
可以帶來可衡量的性能提升嗎? 如果是這樣,請在答案中張貼帶代碼和基准的證明。
關於__assume的稀疏MSDN文章: http : //msdn.microsoft.com/en-us/library/1b3fsfxw( v = vs.100) .aspx
本文中提到的是使用__assume(0)
通過__assume(0)
default
情況使switch
語句更快。 我測量了以這種方式使用__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;
}
圓形控制台輸出,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();
}
}
請注意,唯一的區別是__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
}
這里注意如何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:
請注意,在第二種情況下:
還要注意這是如此接近,以至於我不知道如何測量除噪音以外的任何東西......
另一方面,在語義上它確實表明了一個意圖,盡管可能一個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.在使用速度選項時必須說的內容一致。 在其他情況下調用了開關功能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.