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

2 0
原创粉丝点击