圖4為排序階段cpu的使用率,可以看到只有乙個核達到了100%的利用率。下面為乙個多執行緒(執行緒的數量為核的數量)的排序版本,每個執行緒只對1g資料中的一部分進行快速排序,排序完成後再由另外乙個執行緒進行歸併,將結果寫入檔案。
多執行緒排序**如下:
/*multi_thread_sort.c*/
/*再編譯執行下,以下為測試結果:* author: chaos lee
* date: 2012-06-30
* description: load, merge , store data with single core, but sorting data with
all the cores provided by the smp
*/ #include
#include
#include
#include
#include
#include
#include
#include
#include "../error.h"
#include "timer.h"
uint64_t * buffer = null;
pthread_mutex_t counter_mutex = pthread_mutex_initializer;
pthread_cond_t merge_start = pthread_cond_initializer;
int cores_number;
int counter;
int uint64_compare(const void * ptr1,const void * ptr2)
typedef struct segment_tag
segment_t,*segment_p;
void barrier()
status = pthread_mutex_unlock(&counter_mutex);
if(0 != status)
err_abort("unlocking error.",status);
} void * sort_thread_routin(void * args)
void * merge_thread_routin(void * args)
elapsed_seconds = get_elapsed_time();
fprintf(stdout,"sorting cost %d seconds.\n",elapsed_seconds);
status = pthread_mutex_unlock(&counter_mutex);
if(0 != status)
err_abort("unlocking error.",status);
dprintf(("begin to merge...\n"));
finish_count = 0;
segment_p segs = (segment_p) args;
restart_timer();
while(finish_count }
else }
} segs[j].start++;
if(segs[j].start >= segs[j].end)
fwrite(&tmp,sizeof(uint64_t),1,fp_result);
} elapsed_seconds = get_elapsed_time();
fprintf(stdout,"merging cost %d seconds.\n",elapsed_seconds);
dprintf(("merging is over\n"));
fclose(fp_result);
pthread_exit((void *)0);
} int main(int argc,char *argv)
fp = fopen("data.dat","rb");
if(null == fp)
start_timer();
fread(buffer,size,1,fp);
elapsed_seconds = get_elapsed_time();
fprintf(stdout,"loading cost %d seconds\n",elapsed_seconds);
segments = (segment_p)malloc(sizeof(segment_t)*cores_number);
if(null == segments)
for(i=0;i
sort_threads = (pthread_t *)malloc(sizeof(pthread_t) * cores_number);
if(null == sort_threads)
merge_thread = (pthread_t *)malloc(sizeof(pthread_t));
if(null == merge_thread)
for(i=0;i
status = pthread_create(merge_thread,null,merge_thread_routin,(void *)segments);
if(0 != status)
err_abort("creating thread faulier.\n",status);
for(i=0;i
status = pthread_join(*merge_thread,null);
if(0 != status)
err_abort("joining thread error.\n",status);
free(buffer);
fclose(fp);
return 0;
}
[lichao@sg01 thread_power]$ gcc multi_thread_sort.c -o multi_thread_sort timer.o -lpthread下圖5為多執行緒排序時cpu的利用率,可以看到cpu的四個核都已經達到100%的利用率,即:硬體沒有白投資:d。當然排序的時間效果也很好,幾乎達到了之前的4倍的加速比。另外可以看到檔案的載入速度和回寫速度也有所提高,這點也是讓我比較疑惑的。下面再次執行單執行緒排序版本。[lichao@sg01 thread_power]$ ./multi_thread_sort
loading cost 14 seconds
sorting cost 22 seconds.
merging cost 44 seconds.
圖5 排序階段cpu的利用率
[lichao@sg01 thread_power]$ ./single_thread_sort可以看到載入速度和回寫速度有了顯著的提公升,雖然排序時間還是沒有多大變化。loading cost 17 seconds
sorting cost 81 seconds
writing results cost 12 seconds
再次執行多執行緒排序版本試試:
[lichao@sg01 thread_power]$ ./multi_thread_sort載入速度又延長了,排序速度幾乎不變,回寫速度也提高了不少。我想這主要是因為檔案系統本身提供了緩衝的作用,即上次用過的檔案可以放在交換區,便於迅速載入記憶體吧。這樣第二次使用的時候,由於這些檔案還存放在交換區中,所以以很高的速度傳入記憶體中。回寫的原理應該也一樣。對於1g的檔案回寫到記憶體,只用了23s,大致的回寫速度為50mb/sloading cost 31 seconds
sorting cost 22 seconds.
merging cost 23 seconds.
假設檔案系統一直起作用,並能達到第二次實驗的效果,即分塊排序22s,歸併排序並回寫檔案系統23s,那麼計算和歸併回寫是能夠重合的。對於200g的檔案a來說,分塊排序的處理時間大致為:200*22s=~1.2h,就擴大為1小時15分鐘吧。這樣對檔案b來說也差不多為1小時15分鐘,一共需要2個半小時,接下來開始歸併比較了,假設檔案的緩衝系統能夠啟作用,即速度能達到50mb/s,這樣,對於2個200g的檔案都需要在記憶體中過一遍,大致時間應該為400*10^3/50 = 8000s,大致為2小時15分鐘,所以加上前面的2個半小時,對於2個200g的檔案尋找相同值共需要的時間為 5個小時左右,至少比300萬年好點。
ps: =~這個符號表示約等於
百度2011實習生招聘筆試題
一 簡答題 1 extern c 是什麼意思,作用是什麼?2 至少說出兩個設計模式,闡述內容及其適用情況,最好有偽 3 tcp ip中的time wait是什麼意思?在什麼情況下會出現,簡述其好處和壞處。二 演算法與程式設計 1 某系統每天要執行n個任務 n 1000 任務之間存在複雜的依賴關係,如...
百度2010實習生招聘筆試題
a卷 共三道大題 請先閱讀卷首的試卷說明,在a b卷選擇一套試卷作答,同時作答試卷無效 第一題 簡答題 1 簡要說明樹的深度優先 廣度優先遍歷演算法,及非遞迴實現的特點。2 在處理磁碟資料時,需要首先將其讀入記憶體才能進行處理。如果要讀取的資料已經在記憶體中,則可以直接訪問記憶體。通常來說記憶體是有...
2017百度實習生招聘程式設計題
一 度度熊想去商場買一頂帽子,商場裡有n頂帽子,有些帽子的 可能相同。度度熊想買一頂 第三便宜的帽子,問第三便宜的帽子 是多少?輸入描述 首先輸入乙個正整數n n 50 接下來輸入n個數表示每頂帽子的 均是正整數,且小於等於1000 輸出描述 如果存在第三便宜的帽子,請輸出這個 是多少,否則輸出 1...