[英]Curious result from the gcc linker behaviour around -ffast-math
我注意到在編譯器鏈接器的標志周圍有一種有趣的現象,它以我無法理解的方式影響正在運行的代碼。
我有一個庫,提供了相同算法的不同實現,以便測試這些不同實現的運行速度。
最初,我使用一對相同的實現對情況進行了測試,以檢查是否發生了正確的事情(兩者都以大致相同的速度運行)。 我首先使用以下編譯器標志編譯對象(每個實現一個):
-g -funroll-loops -flto -Ofast -Werror
然后在鏈接中通過gcc傳遞以下標志:
-Ofast -flto=4 -fuse-linker-plugin
這提供了一個運行得非常快的庫,但是奇怪的是,對於鏈接期間包含在參數中的第一個對象,可靠且可重復地快了7%左右(因此,如果先鏈接,則實現都更快)。
因此:
gcc -o libfoo.so -O3 -ffast-math -flto=4 -fuse-linker-plugin -shared support_obj.os obj1.os obj2.os -lm
VS
gcc -o libfoo.so -O3 -ffast-math -flto=4 -fuse-linker-plugin -shared support_obj.os obj2.os obj1.os -lm
第一種情況是obj1中的實現比obj2中的實現運行得更快。 在第二種情況下,情況相反。 為了清楚起見,除了函數條目名稱之外,兩種情況下的代碼都是相同的。
現在,我通過在鏈接期間刪除-Ofast
標志來消除了這種奇怪的鏈接參數順序差異(並實際上加快了一點)。
通過將-Ofast
更改為-O3 -ffast-math
,我可以復制幾乎相同的情況,但是在那種情況下,我需要在鏈接期間提供-ffast-math
,這又導致了奇怪的訂購速度差異。 我不確定為什么在鏈接過程中未通過-ffast-math
時為什么保持-Ofast
而不是-ffast-math
-ffast-math
,但是我可以接受,這可能-ffast-math
傳遞相關信息的鏈接時間優化在一種情況下,但在另一種情況下,則不是。 但這並不能解釋速度差異。
刪除-ffast-math
意味着它的運行速度慢了約8倍。
是否有人能夠闡明可能引起這種影響的原因? 我真的很想知道會導致這種有趣行為的原因,所以我不會偶然觸發它。
運行速度測試是使用庫和timeit周圍的包裝在python中執行的,我相當確定這是做對的事情(我可以旋轉命令,並且可以看出python的副作用可以忽略不計)。
我還測試了庫的輸出正確性,因此我也可以對此充滿信心。
發表評論的時間過長,因此被發布為答案:
由於存在在數學運算中獲得錯誤結果的風險,因此建議不要使用它。
使用-ffast_math
和/或-Ofast
可能導致錯誤的結果,如gcc手冊中的以下摘錄所示:
選項: -ffast-math
設置選項:
此選項將導致定義預處理程序宏__FAST_MATH__
。
除-Ofast
外,此選項未由任何-O選項-Ofast
因為它可能導致依賴於數學函數的IEEE或ISO規則/規范的確切實現的程序輸出不正確。 但是,對於不需要這些規范保證的程序,它可能會產生更快的代碼。 “
選項: -Ofast
忽略嚴格的標准合規性。 -Ofast
啟用所有-O3
優化。 它還啟用了並非對所有符合標准的程序都有效的優化。 它打開-ffast-math
和Fortran特定的-fno-protect-parens
和-fstack-arrays
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.