簡體   English   中英

使用線程提高以下代碼的效率

[英]increasing efficiency of following code using threads

我正在使用一台具有8核和32GB內存的計算機。 在這台機器上,我正在Windows x64上使用VS2010在c ++中運行代碼,這需要3天才能完成8棵樹(8是外線程的數量)。 我搜索了瓶頸,發現crossCorrelate方法花費了大約75-80%的時間。 現在,我試圖使該方法更有效,代碼如下:

int main(){
    int numThread = 8;
    //create threads, run build_tree method for each of them
    //and join after running all of them
}

//我正在創建8棵樹

void build_tree(int i){  //called millions of times 
    for(some_value to another_val){
        //do some stuff
        read_corresponding_matrices
        crossCorrelate(mat1,mat2);
    }
    //write the results to a file 
}

//每棵樹都在使用自己的數據,樹之間沒有依賴關系。

Mat crossCorrelate(Mat mat1_real, Mat mat2_real){
    Mat mat1, mat2,result;

    //1st multi-threading part  // around 20 ms
    Scalar mean1 = mean(mat1_real);
    subtract(mat1_real,(float)mean1[0],mat1);

    Scalar mean2 = mean(mat2_real);
    subtract(mat2_real,(float)mean2[0],mat2);
    //1st part ends

    Mat tilted_mat2 = flip_cross(mat2);

    Mat planes[] = {Mat_<float>(mat1), Mat::zeros(mat1.size(), CV_32F)};
    Mat planes2[] = {Mat_<float>(tilted_mat2), Mat::zeros(mat1.size(), CV_32F)};

    Mat complexI;

    //2nd multi-threaded part   //around 150 ms
    merge(planes, 2, complexI);                     
    dft(complexI, complexI);                        
    split(complexI, planes);                        

    merge(planes2, 2, complexI);            
    dft(complexI, complexI);                        
    split(complexI, planes2);
    //2nd m-t part ends 

    // do some operations with mat1, mat2, planes etc
    clock_t s11 = clock();
    cout << "total time diff " << s11-s1 << endl;

    return result;
}

這是我要提高效率的方法。 每次通話大約需要600毫秒。 我認為是使方法的一些獨立部分成為多線程,並發現兩個可以並行編寫的地方。

為此,我為每個(第1和第2 mt部分)編寫了兩個簡單的代碼,然后運行這些方法:

t1 = boost::thread( subtract_mean, mat1_real, mat1); 

subtract_mean(mat_ori, mat){
    Scalar mean1 = mean(mat_ori);
    subtract(mat_ori,(float)mean1[0],mat1);
}

同樣,第二個線程為每個dft創建兩個線程。(dft_thread)

該代碼包含大量計算,因此,當我運行它時,cpu的使用率約為90%。

在使用內部線程運行之前,我期望會有更好的結果,但事實並非如此。

這是我的問題: 在沒有dft_threadsub_thread情況下運行時,為什么我的代碼運行得更快? 如何使crossCorrelation更快? 我可以一次使用一次,一次使用一次的內部線程,這樣會使我的代碼更快嗎? 有沒有在我的代碼中插入內部線程的聰明方法?

編輯 :我做了一些新的測試:我沒有內螺紋,並檢查了當樹大小= 16的外螺紋數量為1-2-4-6-8時會發生什么。結果如下:

numThread 1 ------ 2 ------ 4 ------ 6 ------ 8

時間花費 29 ----- 35 ----- 51 ----- 77 ----- 104(以秒為單位)

avg_time 29 ---- 17.5 ---- 12.7 ---- 12.8 ---- 13(以秒為單位)

我認為這表明,我可以使線程速度提高2.5倍。 我曾預期/認為使用8線程的速度快5-6倍。 是應該的嗎? 我做錯了什么還是對線程的理解失敗了?

EDIT2 :我又做了一個測試:

第一個: running the code with 6 thread

第二個是將Visual Studio項目復制5次並同時run 6 process at the same time all of them are running with one thread (多線程與並行處理)

multithreading takes 141 mins whereas, parallel processing takes 70 mins.

請注意:用一個線程運行一個進程需要53分鍾。

可能是什么原因呢? 有人看到這種異常情況嗎? 我認為兩者使用相同數量的資源時應該具有相同的速度(也許多線程會更快一些),對嗎?

謝謝,

並不是一個真正的答案,但作為注釋,它不會很可讀:

  1. 嘗試避免經常調用的任何函數的任何參數/返回

    如果可以使用全局變量代替const那么const參數是不夠的。 例如在crossCorrelate(mat1,mat2); mat1,mat2可以是全局的(當然每個線程都擁有)。 在最佳情況下,參數由指針引用。 在那種情況下,它沒什么大不了的,但仍然可以花一些時間。 更糟糕的是,每次調用都會將其復制到新對象中。 當矩陣很大時,這需要時間。 並且也不要忘記構造函數/析構函數也被稱為...

  2. 避免在經常執行的代碼中進行動態分配

    如果可能,僅分配一次。 現代C / C ++引擎具有非常好的內存管理器,因此這不會花費很多時間,但有時甚至1-5%

  3. 檢查DFT

    如前所述,應將其計算為DFFT 我不確定您是否具有足夠快的DFFT實現方式,但是如果您的輸入數據始終都具有相同的矩陣大小,那么您可以預先計算權重並一直使用它們。 它將大大加快DFFT / IDFFT的速度。

    BTW merge,dft,split也可以重寫(就位且沒有參數)。 或者,您可以使用雙重緩沖技術(在執行時交換指針)。

    如您所寫,您無法進入源代碼,因此請嘗試使用其他DFFT / IDFFT

    NTT / INTT呢? 如果您的算法僅將FFT用於其屬性,則有時NTT會更快,但如果輸入數據很復雜,那么您別無選擇。

  4. 您正在讀取矩陣(我從某些文件中假設)

    檢查其性能。 如果它是二進制文件,則沒有任何改善的地方,但是如果它是文本形式,請檢查讀取效率。 例如, WinAPI ini文件的讀取速度比用C ++有效地編寫ini解析器的速度慢大約1000倍,特別是對於大文件。

  5. 您可以嘗試通過更好的線程管理來提高性能

    • 根據CPU數量使用線程數。 如果您有4xCPU,則100個線程不會比4個線程快,但實際上會慢一些。
    • 您可以更改線程/進程優先級/類
    • 有時放置良好的Sleep()實際上可以加快速度
    • 您可以使用相似性掩碼來更好地配置哪個線程在哪個CPU上運行,有時會有所幫助。

PS。 順便問一下,您的矩陣有多大?

[Edit1]

當您使用並行/多線程時,您一次訪問的資源是N倍...

  • 您的單個矩陣為1K x 1K x浮點數= 4 MB
  • FFT后,您切換到復數,因此它變為8 MB
  • 您正在2個矩陣(例如AB)上執行某些操作,因此16 MB
  • 如果您不使用就地算法(例如A=ABC=AB ),則您使用的是24 MB

因此,請檢查您計算機上的CACHE大小,並且存在瓶頸(至少在我看來)。 同樣,當您使用矩陣作為操作數或返回值而沒有引用(不是指針而是對象)時,則可以為它們每個添加8 MB。 N = 1024時,還要考慮2D (I)DFFT內部的遞歸調用量! 堆垃圾的數量太可怕了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM