2017-06-11 40 views
-3

我正在編寫簡單的程序,我想在Windows和Linux(都是64)上執行它的執行時間。我遇到了一個問題,因爲在Windows桌面上的1 000 000個元素大約需要35秒,而在Linux上,10個元素需要大約30秒。爲什麼差異如此巨大? 我在做什麼錯?我的代碼中有什麼不適合在Linux上?在Linux上的C++代碼比在Windows上慢很多

這裏是我的代碼:

void fillTable(int s, int t[]) 
{ 
    srand(time(0)); 
    for (int i = 0; i < s; i++) 
    { 
     t[i] = rand(); 
    } 
} 
void checkIfIsPrimeNotParalleled(int size, int table[]) 
{ 
    for (int i = 0; i < size; i++) 
    { 
     int tmp = table[i]; 

     if (tmp < 2) 
     { 
     } 


     for (int i = 2; i < tmp; i++) 
     { 
      if (tmp % i == 0) 
      { 
      } 
      else 
      { 
      } 
     } 
    } 
} 
void mesureTime(int size, int table[], int numberOfRepetitions) 
{ 
    long long sum = 0; 
    clock_t start_time, end_time; 
    fillTable(size, table); 

    for (int i = 0; i < numberOfRepetitions; i++) 
    { 
     start_time = clock(); 

     checkIfIsPrimeNotParalleled(size, table); 

     end_time = clock(); 
     double duration = (end_time - start_time)/CLOCKS_PER_SEC; 
     sum += duration; 
    } 
    cout << "Avg: " << round(sum/numberOfRepetitions) << " s"<<endl; 
} 

int main() 
{ 

    static constexpr int size = 1000000; 
    int *table = new int[size]; 
    int numberOfRepetitions = 1; 
    mesureTime(size, table, numberOfRepetitions); 
    delete[] table; 
    return 0; 

} 

和Linux的makefile文件。在Windows上,我使用的是Visual Studio 2015

.PHONY: Project1 

CXX = g++ 
EXEC = tablut 
LDFLAGS = -fopenmp 
CXXFLAGS = -std=c++11 -Wall -Wextra -fopenmp -m64 
SRC= Project1.cpp 
OBJ= $(SRC:.cpp=.o) 

all: $(EXEC) 

tablut: $(OBJ) 
    $(CXX) -o tablut $(OBJ) $(LDFLAGS) 

%.o: %.cpp 
    $(CXX) -o [email protected] -c $< $(CXXFLAGS) 

clean: 
    rm -rf *.o 

mrproper: clean 
    rm -rf tablut 

主要目標是確定時間。

+6

你不讓GCC優化此代碼的任何原因? (如-03選項?) – JVApen

+0

您是否在Windows下以發行模式運行代碼? – Rakete1111

+0

當我使用O3,O2甚至O1運行此項目時,99999999元素的時間爲0秒 – karo96

回答

1

您的代碼的for循環設置爲1,000,000次迭代。正如其他人所指出的那樣,編譯器可以優化這個循環,這樣你就不會學到任何東西。

我用來解決良好編譯器問題的技術是用低成本時間檢查來替代固定循環。

在以下代碼片段中,我使用計時器進行持續時間測量,並使用時間(0)來檢查測試結束。 Chrono並不是我發現的最低成本時間檢查,但我覺得我足夠好,因爲我使用它。 std :: time(0)的測量值約爲5 ns(在我的系統上),大約是我測量的最快速度。

// Note 7 - semaphore function performance 
// measure duration when no thread 'collision' and no context switch 
void measure_LockUnlock() 
    { 
     PPLSem_t* sem1 = new PPLSem_t; 
     assert(nullptr != sem1); 
     size_t  count1 = 0; 
     size_t  count2 = 0; 
     std::cout << dashLine << " 3 second measure of lock()/unlock()" 
       << " (no collision) " << std::endl; 
     time_t t0 = time(0) + 3; 

     Time_t start_us = HRClk_t::now(); 
     do { 
      assert(0 == sem1->lock()); count1 += 1; 
      assert(0 == sem1->unlock()); count2 += 1; 
      if(time(0) > t0) break; 
     }while(1); 
     auto duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us); 

     assert(count1 == count2); 
     std::cout << report (" 'sem lock()+unlock()' ", count1, duration_us.count()); 

     delete sem1; 
     std::cout << "\n"; 
    } // void mainMeasures_LockUnlock() 

FYI - 「類PPLSem_t」是運行的Posix過程信號量設定爲本地模式(unamed,非共享)4-單行的方法。

上面的測試只測量方法調用的開銷,在本次實驗中沒有調用上下文切換(非常慢)。


但是等等,你說...不要鎖定()和解鎖()有副作用嗎?同意。但編譯器知道嗎?它必須假設他們這樣做。

那麼你如何使這有用?

兩個步驟。 1)測量您的鎖定/解鎖性能。 2)將for循環內部的代碼(不是for循環本身)添加到此鎖定/解鎖循環中,然後再次測量性能。

這兩個測量結果的差異是您所尋找的信息,我認爲編譯器無法優化它。

時間測量上我的大戴爾的結果,與Ubuntu 15.10,和g ++ v5.2.1.23,和-O3是

-------------------------------------------------------------- 
    3 second measure of lock()/unlock() (no collision) 
    133.5317660 M 'sem lock()+unlock()' events in 3,341,520 us 
    39.96138464 M 'sem lock()+unlock()' events per second 
    25.02415792 n sec per 'sem lock()+unlock()' event 

所以這大約是12.5納秒爲每個方法之一,並在約3秒內完成了133 10^6次迭代。

您可以嘗試調整達到1,000,000次迭代的時間,或者只是使用迭代計數跳出循環。 (即如果count1 == 1,000,000)break;一種理念)


你的任務,你應該選擇接受它,是要找到一個副作用合適的簡單和快速的方法(或兩個)(你知道會不會發生),並添加將代碼放入該循環中,然後運行,直到循環計數爲1,000,000。


希望這會有所幫助。

+0

嗯,也許這是太多的幫助,但我的PPLSem_t代碼存在於我的其他答案之一。 –

+0

您可以嘗試一個定時循環而不使用帶副作用的方法......它可以工作,因爲編譯器無法猜測您的系統性能。 –

+0

oops ...發現我的計時typedefs丟失。看到我的答案在這裏:https://stackoverflow.com/a/44467595/2785528副本 –

1

您並未在Linux上啓用優化。將-O2-O3添加到您的編譯器標誌(CXXFLAGS),您將看到顯着的性能改進。

+0

當我用O3,O2甚至O1運行這個項目時,99999999元素的時間是0秒 – karo96

+7

@ karo96你去了。編譯器完成了它的工作,並且優化了代碼,因爲它沒有任何副作用。 –

+2

我會說0秒比35秒快得多 –

相關問題