Linux多线程实践(7) --多线程排序对比
屏障
int pthread_barrier_init(pthread_barrier_t *restrict barrier,const pthread_barrierattr_t *restrict attr,unsigned count); int pthread_barrier_destroy(pthread_barrier_t *barrier);int pthread_barrier_wait(pthread_barrier_t *barrier);? 屏障允許任意數量的線程等待,?直到所有的線程完成處理工作,?而線程不需要退出,?所有線程達到屏障之后可以接著工作.
??init:在初始化屏障時,?可以使用第三個參數count指定,?在允許所有線程繼續運行之前,?必須到達屏障的線程數目.
??wait:可以使用pthread_barrier_wait函數來表明,?線程已經完成工作,?準備等所有其他線程趕上來;
????調用wait的線程在屏障計數未滿足條件時,?會進入休眠狀態.?如果該線程是最后一個調用wait的線程,?就滿足了屏障計數,?所有的線程都被喚醒.
??對于一個任意線程,?pthread_barrier_wait函數返回了PTHREAD_BARRIER_SERIAL_THREAD.?剩下的線程看到的返回值是0.?這使得一個線程可以作為主線程,?他可以工作在其他所有線程已完成的工作結果上.
?
單線程與多線程排序
單線程排序
bool compare(long a, long b) {return a < b; }#define NUMNUM 8000000L long int nums[NUMNUM]; //待排序數組(約32M)int main() {srandom(time(NULL));for (unsigned long i = 0; i < NUMNUM; i++)nums[i] = random();struct timeval start, end;//計時開始gettimeofday(&start,NULL);sort(nums,nums+NUMNUM,compare); //單線程排序,快速排序gettimeofday(&end,NULL);//計算用時long long startusec = start.tv_sec * 1000000 + start.tv_usec;long long endusec = end.tv_sec * 1000000 + end.tv_usec;double elapsed = (double)(endusec - startusec) / 1000000.0;printf("sort took %.4f seconds\n", elapsed);//將排序后的結果寫入文件, 以便查看是否已經排好序FILE *fp = fopen("save.txt", "w+");for (unsigned long i = 0; i < NUMNUM; i++)fprintf(fp, "%ld ", nums[i]); }三次排序用時如下:
??sort?took?3.2435?seconds
??sort?took?3.2221?seconds
??sort?took?3.2134?seconds
(附-主機配置:?雙核四線程(Intel(R)?Core(TM)?i3-2350M?CPU?@?2.30GHz))
?
多線程排序(使用屏障同步)
#define NTHR 8 /* 線程數 */ #define NUMNUM 8000000L /* 待排序數 */ #define TNUM (NUMNUM/NTHR) /* 每個線程分配到的需要排序的數 */ long nums[NUMNUM]; long snums[NUMNUM]; pthread_barrier_t b; //屏障bool compare(long a, long b) {return a < b; } //排序線程 //對nums數組的從idx~idx+TNUM部分進行快速排序 void *workThread(void *arg) {long idx = (long)arg;sort(&nums[idx],&nums[idx+TNUM],compare);pthread_barrier_wait(&b);pthread_exit(NULL); }//對已經排好序數組nums的NTHR部分進行合并 void merge() {long idx[NTHR]; //idx保存數組nums的NTHR部分的起始位置for (long i = 0; i < NTHR; i++)idx[i] = i * TNUM;for (long sidx = 0; sidx < NUMNUM; sidx++){long minidx;long num = LONG_MAX;//從NTHR部分的數組中查找出最小的一個, 將其index保存到idx[minidx]中for (long i = 0; i < NTHR; i++){//idx[i] < (i+1)*TNUM 確保是在一個部分之中,//不會產生兩個部分相互比較的情況if ((idx[i] < (i+1)*TNUM) && (nums[idx[i]] < num)){num = nums[idx[i]];minidx = i;}}snums[sidx] = nums[idx[minidx]];idx[minidx]++;} }int main() {srandom(time(NULL));for (unsigned long i = 0; i < NUMNUM; i++)nums[i] = random();//創建NTHR個線程分別對數組相鄰的NTHR部分進行排序struct timeval start, end;pthread_t tid;gettimeofday(&start, NULL);pthread_barrier_init(&b, NULL, NTHR+1);for (unsigned long i = 0; i < NTHR; i++)pthread_create(&tid, NULL,workThread, (void *)(i * TNUM));pthread_barrier_wait(&b);merge();gettimeofday(&end, NULL);//計算用時long long startusec = start.tv_sec * 1000000 + start.tv_usec;long long endusec = end.tv_sec * 1000000 + end.tv_usec;double elapsed = (double)(endusec - startusec) / 1000000.0;printf("sort took %.4f seconds\n", elapsed);//將排序后的結果寫入文件, 以便查看是否已經排好序FILE *fp = fopen("save.txt", "w+");for (unsigned long i = 0; i < NUMNUM; i++)fprintf(fp, "%ld ", snums[i]); }八線程排序:
??sort?took?1.5556?seconds
??sort?took?1.5676?seconds
??sort?took?1.5719?seconds?
四線程排序:
??sort?took?1.4132?seconds
??sort?took?1.4315?seconds
??sort?took?1.4738?seconds
二線程排序:
??sort?took?2.0581?seconds
??sort?took?2.2358?seconds
??sort?took?1.7775?seconds
(附-主機配置:?雙核四線程(Intel(R)?Core(TM)?i3-2350M?CPU?@?2.30GHz))
?
總結:?可以看到盡管在分別進行排序之后還要有合并(merge)這一步,多線程排序(計算密集型任務)還是要優于單線程排序(在CPU為多核的情況下),而且在CPU為四線程下,使用四個線程對數組進行排序,所耗費時間是最少的!
總結
以上是生活随笔為你收集整理的Linux多线程实践(7) --多线程排序对比的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 归纳几点html编码要素--杜绝浏览器不
- 下一篇: XenApp的工作过程