2016-06-29 106 views
2

我想優化一些C代碼,這是我第一次。 作爲第一步我傾銷我的可執行文件,以便看到彙編代碼。 例如,對於這樣的功能:C代碼優化

void init_twiddle(int N) 
{ 
    int i=0; 
    for(i=0; i<ELEMENTS_HALF; i++) 
    {  
    twiddle_table[i].re = (float) cos((float)i * 2.0 * PI/(float)N); 
    twiddle_table[i].im = (float) - sin((float)i * 2.0 * PI/(float)N); 
    } 
} 

不會更好,如果我這樣做,而不是:

void init_twiddle(int N) 
{ 
    int i=0; 
    float puls = 2.0 * PI/(float)N; 
    for(i=0; i<ELEMENTS_HALF; i++) 
    {  
    twiddle_table[i].re = (float) cos((float)i * puls); 
    twiddle_table[i].im = (float) - sin((float)i * puls); 
    } 

,以避免重複被數千次MULT和DIV操作? }

+1

機會是,它會。你不會指望編譯器自己弄清楚,是嗎? – dasblinkenlight

+2

這是一個簡單的基準應用程序標記。我最初的想法是,除非N很大,否則它可以忽略不計。或者正如Amin Negm-Awad在答案中指出的那樣,只要您啓用了優化標誌,編譯器可能已經爲您完成了這一切,這是無關緊要的。 – CHess

+0

彙編代碼與此有什麼關係? –

回答

5

不幸的是,您的第一步已經有點錯了。

不要盲目地遍歷代碼,優化可能或(更可能)不會影響性能的任意循環(可能是因爲代碼很少被調用以至於它沒有真正使用任何運行時)。

優化手段:您需要先找出我的程序花費的時間在哪裏?使用計時測量來縮小程序大部分時間花費的時間(您可以使用本地計時器使用我們的計時器或分析應用程序)。如果沒有至少一些數字,你甚至不會看到編譯器已經幫助你的位置,也許已經超出了所有的可能性,即使你的代碼看起來有一些潛在的更快的速度(現代編譯器真的非常擅長)。

只有當您知道應用程序中的熱點時,才應該開始優化這些熱點。

+0

@ tofro你的答案看起來更符合我的邏輯 這就是我要做的 –

0

一切罪惡的根源是過早的優化 - 高德納

你應該優化,如果你有時間的執行問題。有些工具可以記錄每一條語句或者至少是函數調用的持續時間。

我認爲大多數編譯器在一個循環中檢測到這樣的常量表達式,並且沒有什麼可以優化的,因爲它已經被優化了。

+0

上面的示例*不是一種過時的優化。 –

+0

你不能這麼說,因爲你不知道,是否有必要。 –

+0

你不能說它不是,@ AminNegm-Awad,因爲你不知道OP的測量結果。 – AShelly

-1

這可能不會改變你的代碼的性能,因爲這是由任何標準編譯器(假設優化不會關閉)執行標準循環不變優化..

3

的問題是,它是一個浮點表達式和浮點運算不可交換。因此,對於遵循IEEE 754的任何編譯器來說,優化通常是無效的。因此,無論您需要手動執行此優化,還是必須告訴編譯器將浮點視爲交換以實現優化目的(在gcc和clang中,您使用-ffast-math做這個)。這會在結果值中引入輕微的變化。

對於組件的比較:

所有的
+0

好點!+1! –

0

首先,使用double,不float。在C中,庫例程全部在double中,所以你只是做了很多轉換。

其次,計算一次角度並將其放入一個變量中,而不是兩次。 也許編譯器認識到它可以爲你做到這一點,但我不想誘使編譯器不要。

三,有沒有sincos函數?正弦函數和餘弦函數是緊密相關的,所以可以與其他函數同時進行計算。第四,當考慮績效時,請將您的大腦思考成的百分比,而不是做「數千次」的事情。這樣,你就會專注於最大的整體收益,而不是那些可能無關緊要的事情。

+0

如果使用正確的標誌,編譯器可以優化這一點,包括使用sincos和矢量化 – user1937198

+0

@ user1937198:也許這樣,也許不是,爲什麼會試試命運? –

+1

@ user1937198讓編譯器做非顯而易見的事情,自己做一個明顯的例子 –

2

你可以更快地做到這一點,事實上,你只需要1個正弦和1個餘弦(這是非常緩慢的)。你實際上在做的是計算你在原點周圍旋轉的一個小矢量的座標,另一種方法是通過在原點周圍旋轉該矢量,當時是一步。單步的旋轉矩陣是單個正弦和餘弦的花費。

當然,這可能不太準確,但如果您進行合理的步驟數量,則不會出現嚴重問題。

+0

你的回答比我的好因爲你可以看到用戶想要做什麼,不需要調用內置函數不止一次。 –

+1

那麼,如果問題是關於它的話,有很多方法可以優化它。就像只使​​用像'sin(pi/2 + x)= cos(x)'等身份一樣計算一個象限。 –

+0

夠公平,適用一些更多的技巧 – harold