linux下多线程 排序,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下多线程 排序,Linux多线程实践(7) --多线程排序对比的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 猜一猜常吃的糖醋鲤鱼属于哪个菜系?蚂蚁庄
- 下一篇: 魅族与领克汽车官宣!深度融合 打造智行无