[英]Can I create a union with formal parameter passed to a function in C++?
下面的函數計算32位浮點值的絕對值:
__forceinline static float Abs(float x)
{
union {
float x;
int a;
} u;
//u.x = x;
u.a &= 0x7FFFFFFF;
return u.x;
}
在函數中聲明的並集u包含變量x,該變量與在函數中作為參數傳遞的x不同。 有什么方法可以創建帶有函數參數-x的聯合嗎?
有什么原因使上面帶有注釋行的函數的執行時間比這個更長?
__forceinline float fastAbs(float a)
{
int b= *((int *)&a) & 0x7FFFFFFF;
return *((float *)(&b));
}
我正在嘗試找出盡可能少地對內存進行讀/寫操作以獲取浮點值Abs的最佳方法。
對於第一個問題,我不確定為什么您不能隨心所欲地完成任務。 編譯器將盡一切可能的優化。
在第二個示例代碼中。 您違反了嚴格的別名。 所以不一樣。
至於為什么它慢一些:
這是因為當今的CPU傾向於具有獨立的整數和浮點單元。 通過像這樣的類型調整,您可以將值從一個單位移動到另一個單位。 這有開銷。 (這通常是通過內存完成的,因此您需要額外的負載和存儲。)
在第二個片段中: a
最初位於浮點單元(x87 FPU或SSE寄存器)中,需要移入通用寄存器以應用掩碼0x7FFFFFFF
。 然后需要將其移回。
在第一個代碼段中:編譯器可能足夠聰明,可以將a
直接加載到整數單元中。 因此,您可以在第一階段繞過FPU。
(在向您展示程序集之前,我不確定100%。這在很大程度上還取決於參數是在寄存器中啟動還是在堆棧中啟動。輸出是否立即由其他浮點運算使用。)
看看在發布模式下編譯的代碼的反匯編,差異很明顯! 我刪除了內聯並使用了兩個虛擬函數,以使編譯器不會進行過多優化,並讓我們展示它們之間的差異。
這是第一個功能。
013D1002 in al,dx
union {
float x;
int a;
} u;
u.x = x;
013D1003 fld dword ptr [x] // Loads a float on top of the FPU STACK.
013D1006 fstp dword ptr [x] // Pops a Float Number from the top of the FPU Stack into the destination address.
u.a &= 0x7FFFFFFF;
013D1009 and dword ptr [x],7FFFFFFFh // Execute a 32 bit binary and operation with the specified address.
return u.x;
013D1010 fld dword ptr [x] // Loads the result on top of the FPU stack.
}
這是第二個功能。
013D1020 push ebp // Standard function entry... i'm using a virtual function here to show the difference.
013D1021 mov ebp,esp
int b= *((int *)&a) & 0x7FFFFFFF;
013D1023 mov eax,dword ptr [a] // Load into eax our parameter.
013D1026 and eax,7FFFFFFFh // Execute 32 bit binary and between our register and our constant.
013D102B mov dword ptr [a],eax // Move the register value into our destination variable
return *((float *)(&b));
013D102E fld dword ptr [a] // Loads the result on top of the FPU stack.
在第一種情況下,浮點操作的數量和FPU堆棧的使用量更大。 這些功能完全按照您的要求執行,因此毫不奇怪。 所以我希望第二個功能更快。
現在...刪除虛擬和內聯的東西有些不同,在這里很難寫反匯編代碼,因為編譯器當然做得很好,但是我重復一遍,如果值不是常量,則編譯器將使用更多的浮點數在第一個功能中進行操作。 當然,整數運算比浮點運算要快。
您確定直接使用math.h abs函數比您的方法慢嗎? 如果正確內聯,abs函數將執行此操作!
00D71016 fabs
這樣的微優化很難在長代碼中看到,但是如果在長串浮點運算中調用您的函數,則Fab將更好地工作,因為值已經存在於FPU堆棧或SSE寄存器中! 編譯器將更快,更好地優化abs。
您無法衡量在一段代碼中運行循環的優化性能,您必須查看編譯器如何在實際代碼中將所有這些混合在一起。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.