2016-11-09 43 views
0
#include <vector> 
#include <iostream> 
#include <cmath> 
#include <iomanip> 
#include <sys/time.h> 

using namespace std; 

int main() 
{ 
    struct timeval timeStart, 
        timeEnd; 

的兩個向量循環時創建的隨機0和1。我們將標杆,總結起來的時間向量。優化通過不同長度

int n1 = 450000000; // size of vector v1 
    int n2 = 500000000; // size of vector v2 
    int i; 
    vector<bool> v1(n1); 
    vector<bool> v2(n2); 

    for (i=0; i < n1 ; i++) 
    { 
    v1[i] = rand() % 2; 
    } 
    for (i=0; i < n2 ; i++) 
    { 
    v2[i] = rand() % 2; 
    } 

第一種總和技術。總結這些載體有兩個完整的(獨立的)循環

int sum1 = 0; 
    int sum2 = 0; 
    gettimeofday(&timeStart, NULL); 
    for (i=0; i < n1 ; i++) 
    { 
     sum1 += v1[i]; 
    } 
    for (i=0; i < n2 ; i++) 
    { 
     sum2 += v2[i]; 
    } 
    gettimeofday(&timeEnd, NULL); 
    cout << "Two complete loops took " << ((timeEnd.tv_sec - timeStart.tv_sec) * 1000000 + timeEnd.tv_usec - timeStart.tv_usec) << " us" << endl; 

第二種技術。總結這些載體具有完整的循環和部分環

sum1 = 0; 
    sum2 = 0; 
    gettimeofday(&timeStart, NULL); 
    for (i=0; i < n1 ; i++) 
    { 
     sum1 += v1[i]; 
     sum2 += v2[i]; 
    } 
    for (i=n1; i < n2 ; i++) 
    { 
     sum2 += v2[i]; 
    } 
    gettimeofday(&timeEnd, NULL); 
    cout << "With a reduced second loop, it took " << ((timeEnd.tv_sec - timeStart.tv_sec) * 1000000 + timeEnd.tv_usec - timeStart.tv_usec) << " us" << endl; 

return 0; 
} 

我係統得到的那種

Two complete loops took 13291126 us 
With a reduced second loop, it took 12758827 us 

我本來期望是同一個時間(的輸出,如果編譯器優化的第一個解決方案我將它排除在外),或者我預計完整的兩個循環需要比部分第二循環花費更多的時間(而不僅僅是5%-10%)。

什麼是編譯器最有可能在這裏做什麼?在循環兩個不同長度的向量時,我是否應該考慮在未來使用部分循環?


僅供參考,我與g++ -std=c++11 -o test test.cpp編譯,與版本

g++ --version 
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 
Apple LLVM version 7.0.2 (clang-700.1.81) 
Target: x86_64-apple-darwin15.3.0 
Thread model: posix 
+0

考慮交換兩者的順序,看看你會得到什麼。 – LogicStuff

+0

另外,一個'int i;'可能不是一個優化(或者你認爲的任何東西)。 – LogicStuff

+0

@LogicStuff我會認爲(錯誤地顯然)爲int分配內存只有一次,而不是4次,這確實是戰略性的。不是嗎?是因爲當計算機更經常地初始化時,確保'1'的內存插槽更靠近它循環的向量或類似的東西?我不完全明白你指的是什麼交換。我天真地試圖互換先前使用的技術的順序,但「兩個完整的循環」仍然是兩者中最慢的。 –

回答

1

一個試圖解釋在執行時間的相似之處:

當你這樣做:

for (i=0; i < n1 ; i++) 
{ 
    sum1 += v1[i]; 
} 
for (i=0; i < n2 ; i++) 
{ 
    sum2 += v2[i]; 
} 

您執行2個循環以獲得更多指令,但是您在兩種情況下都會讀取連續的內存S:緩存以最佳的方式(什麼發生在「現代」的電腦大部分時間是更多的內存訪問/高速緩存未命中不是執行代碼)

工作BTW,我懷疑,編譯器能集團的2個循環。

第二種情況需要較少的控制指令數,但內存不連續讀取。

另外:優化器使用的以「展開」循環,從而降低了控制指令的負面影響。

所以你獲得的在一邊的東西,你失去對方。這些優化需要改進,並且根據處理器體系結構的不同,可能會有更大的變化。

+0

在這兩種情況下,緩存利用率都很好:加載緩存行(對於矢量數據)時,整個緩存行將用於計算。具有一個融合循環的變體使用兩條緩存線,但它們都不會導致另一個緩存線的驅逐,因此它本質上是相同的。 – chill