關於for迴圈的執行效率問題

2021-08-13 07:08:08 字數 1612 閱讀 7491

我以前遇到的問題大概都是這種型別的:

1for(

inti  = 

0;i<100;i++) 2

7} 8和 9

for(

inti  = 

0;i<10000;i++) 10

15}這兩個程式那個執行效率高,如果是以前我會毫不猶豫的說是第乙個效率高,這是由於cpu切換的次數比較多導致效能下降,知道這句話不理解什麼原理。我比較贊同下面的說法,

1. 最長迴圈放到內部可以提高i cache的效率,降低因為迴圈跳轉造成cache的miss以及流水線flush造成的延時

2. 多次相同迴圈後也能提高跳轉**的成功率,提高流水線效率

3. 編譯器會自動展開迴圈提高效率, 這個不一定是必然有效的

但不是絕對正確的,比如:

1 int

x[1000

][100];

2for(i=0;i<1000;i++) 3

for(j=0;j<100;j++) 4

78int

x[1000][100]; 9

for(j=0;j<100;j++)

10for(i=0;i=1000;i++)

1114

這時候第乙個的效率就比第二個的高,原因嘛和硬體也有一些關係,cpu對於記憶體的訪問都是通過資料快取(cache)來進行的。比如乙個通用cpu,一級快取(l1-cache)的大小為16k,而其組織結構為每32個位元組一組(cache line size=32byte),

也就是每次從二級快取或內訪問資料到一級快取,都是一次性取32個位元組。

對於上面的第一段**,每次取資料到一級快取,都有連續8次記憶體訪問可以共享一條快取。

而對於第二段**,每次取資料到一級快取後,訪問一次後,基本上就沒有機會被再次使用了;

上面這兩段**的區別在於第一段**,每次記憶體訪問後,位址值需要加常數4,而第二段**,每次訪問後,位址值加400。

如果沒有對於快取訪問的區別,那麼這時我們的確可以將長的迴圈放在裡層,短的放在外層。但是而其主要原因不是一般人所想象的指令數目的區別的問題,

而主要由於分支**錯誤會引起的流水線中斷從而導致效能的降低。

-------------

觀點2(重點在陣列)

在多重迴圈中,如果有可能,應當將最長的迴圈放在最內

層,最短的迴圈放在最外層,以減少cpu跨切 ...

這種說法是錯誤的。譬如,對陣列操作的兩層迴圈,如果陣列的物理儲存是行優先的(現在的陣列都是如此),則應該外層對行,內層對列,才有高效率。這樣才能 充分發揮cache的效果,即提高cache的命中率。如果反過來做,特別是當列數很多、元素很大時,cache的命中率會非常低。世界級的大牛,比如寫 《深入c++物件模型》,或者c++之父bs,遇到效率問題,一般都會說:理論上可能如何如何,但是真正的結果一定要在具體的環境中實際測試。優化除了有 良好的演算法結構以外,還涉及到很多的方面,硬體的處理方式必須有所了解

除了cache以外,現代cpu會對**進行分支**和預讀取等優化執行效率的處理

如果**編譯後生成的機器語言更適合cpu的優化執行,執行效率也會高出不少

不過了解太多的底層實現來優化程式,成本太高。

大部分情況下,一般的設計人員只要有良好的**結構就足夠了。我估計林博士應該和我的觀點是一樣的^_^

關於 迴圈 效率的問題

今天寫到迴圈邏輯,糾結於是用更少的迴圈呼叫函式還是用更少的函式,多迴圈兩次。於是做了個實驗,發現基於c的lua,函式呼叫的代價果然很高。local tb local max 10000000 for i 1,max do tb i i endfunction check i,max if tb i ...

for迴圈執行效率

include include include include define a 10000 define b 10 define num 100000 void main double a a b double b 0 int t1 clock for int n 0 n 第一種情況是內外層迴圈次...

關於for迴圈的累加效率問題(java)

累加的效率問題 目前有下面兩種方法 方法一 long sum 0 for int i 0 i value i 方法二 long sum 0 sum value 1 value 2 當value值等於10000,使用方法一,執行10次有4次會產生15毫秒左右耗時,使用方法二,執行10次無耗時產生。當v...