Linux多线程实践(7) --多线程排序对比
来源:互联网 发布:化工设备画图软件 编辑:程序博客网 时间:2024/06/03 13:21
屏障
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 8000000Llong 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) --多线程排序对比
- Linux多线程实践
- linux多线程实践1
- Linux多线程实践(7) --Posix条件变量
- Linux与Windows多线程对比
- Linux多线程编程(实践)
- Linux编程实践----第一个多线程程序
- Linux多线程实践(2) --线程基本API
- Linux多线程实践(1) --线程理论
- Linux多线程实践(2) --线程基本API
- Linux多线程实践(3) --线程属性
- Linux多线程实践(4) --线程特定数据
- Linux多线程实践(1) --线程理论
- Linux多线程实践(2) --线程基本API
- Linux多线程实践(4) --线程特定数据
- Linux多线程实践(3) --线程属性
- Linux多线程实践(1) --线程理论
- Linux多线程实践(2) --线程基本API
- c/c++获取时间
- C++多态性:虚函数的调用原理
- Linux多线程实践(6) --Posix读写锁解决读者写者问题
- Android PullToRefresh使用详解(五)--下拉刷新的ScrollView
- 【Uva 1584】 Circular Sequence
- Linux多线程实践(7) --多线程排序对比
- C++ const成员函数
- Ignatius's puzzle
- 对象的垃圾回收和四种引用
- Java基础——成员变量、局部变量和静态变量的区别
- UIButton
- Linux多线程实践(8) --Posix条件变量解决生产者消费者问题
- Android Framework 学习
- 出色技术团队的4要素