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为四线程下,使用四个线程对数组进行排序,所耗费时间是最少的!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值