[英]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_thread
和sub_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分鍾。
可能是什么原因呢? 有人看到這種異常情況嗎? 我認為兩者使用相同數量的資源時應該具有相同的速度(也許多線程會更快一些),對嗎?
謝謝,
並不是一個真正的答案,但作為注釋,它不會很可讀:
嘗試避免經常調用的任何函數的任何參數/返回
如果可以使用全局變量代替const
那么const
參數是不夠的。 例如在crossCorrelate(mat1,mat2);
mat1,mat2
可以是全局的(當然每個線程都擁有)。 在最佳情況下,參數由指針引用。 在那種情況下,它沒什么大不了的,但仍然可以花一些時間。 更糟糕的是,每次調用都會將其復制到新對象中。 當矩陣很大時,這需要時間。 並且也不要忘記構造函數/析構函數也被稱為...
避免在經常執行的代碼中進行動態分配
如果可能,僅分配一次。 現代C / C ++引擎具有非常好的內存管理器,因此這不會花費很多時間,但有時甚至1-5%
檢查DFT
如前所述,應將其計算為DFFT 。 我不確定您是否具有足夠快的DFFT實現方式,但是如果您的輸入數據始終都具有相同的矩陣大小,那么您可以預先計算權重並一直使用它們。 它將大大加快DFFT / IDFFT的速度。
BTW merge,dft,split
也可以重寫(就位且沒有參數)。 或者,您可以使用雙重緩沖技術(在執行時交換指針)。
如您所寫,您無法進入源代碼,因此請嘗試使用其他DFFT / IDFFT
NTT / INTT呢? 如果您的算法僅將FFT用於其屬性,則有時NTT會更快,但如果輸入數據很復雜,那么您別無選擇。
您正在讀取矩陣(我從某些文件中假設)
檢查其性能。 如果它是二進制文件,則沒有任何改善的地方,但是如果它是文本形式,請檢查讀取效率。 例如, WinAPI ini
文件的讀取速度比用C ++有效地編寫ini
解析器的速度慢大約1000倍,特別是對於大文件。
您可以嘗試通過更好的線程管理來提高性能
PS。 順便問一下,您的矩陣有多大?
[Edit1]
當您使用並行/多線程時,您一次訪問的資源是N
倍...
A=AB
但C=AB
),則您使用的是24 MB 因此,請檢查您計算機上的CACHE大小,並且存在瓶頸(至少在我看來)。 同樣,當您使用矩陣作為操作數或返回值而沒有引用(不是指針而是對象)時,則可以為它們每個添加8 MB。 當N = 1024
時,還要考慮2D (I)DFFT內部的遞歸調用量! 堆垃圾的數量太可怕了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.