屏障

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) --多线程排序对比的更多相关文章

  1. 多线程实践—Python多线程编程

    多线程实践 前面的一些文章和脚本都是只能做学习多线程的原理使用,实际上什么有用的事情也没有做.接下来进行多线程的实践,看一看在实际项目中是怎么使用多线程的. 图书排名示例 Bookrank.py: 该 ...

  2. Linux sort -n 与 -g 排序对比

    公司业务需要,天天用awk统计数值然后排序,出问题了,如下: count.sh 是一个统计脚本,把awk输出的值按占比.条数.类型 在重新输出 awk -F\| '{print $16}' *MQTT ...

  3. Linux多线程实践(10) --使用 C++11 编写 Linux 多线程程序

    在这个多核时代,如何充分利用每个 CPU 内核是一个绕不开的话题,从需要为成千上万的用户同时提供服务的服务端应用程序,到需要同时打开十几个页面,每个页面都有几十上百个链接的 web 浏览器应用程序,从 ...

  4. Linux命令:pigz多线程压缩工具【转】

    学习Linux系统时都会学习这么几个压缩工具:gzip.bzip2.zip.xz,以及相关的解压工具.关于这几个工具的使用和相互之间的压缩比以及压缩时间对比可以看:Linux中归档压缩工具学习 那么P ...

  5. 多线程编程之Linux环境下的多线程(三)

    前面两篇文章都讲述了Linux环境下的多线程编程基础知识,也附带了典型实例.本文主要比较一下Linux环境与Windows环境下的多线程编程区别. 看待技术问题要瞄准其本质,不管是WIN32.Linu ...

  6. 多线程编程之Linux环境下的多线程(一)

    一.Linux环境下的线程 相对于其他操作系统,Linux系统内核只提供了轻量级进程的支持,并未实现线程模型.Linux是一种“多进程单线程”的操作系统,Linux本身只有进程的概念,而其所谓的“线程 ...

  7. Linux多线程编程(一)---多线程基本编程

    线程概念 线程是指运行中的程序的调度单位.一个线程指的是进程中一个单一顺序的控制流,也被称为轻量级线程.它是系统独立调度和分配的基本单位.同一进程中的多个线程将共享该系统中的全部系统资源,比如文件描述 ...

  8. 深入 HTML5 Web Worker 应用实践:多线程编程

    深入 HTML5 Web Worker 应用实践:多线程编程 HTML5 中工作线程(Web Worker)简介 至 2008 年 W3C 制定出第一个 HTML5 草案开始,HTML5 承载了越来越 ...

  9. linux下C语言多线程编程实例

    用一个实例.来学习linux下C语言多线程编程实例. 代码目的:通过创建两个线程来实现对一个数的递加.代码: //包含的头文件 #include <pthread.h> #include ...

随机推荐

  1. ubuntu + 远程桌面连接命令 + rdesktop + 连接windows或者ubuntu远程桌面

    原文 https://www.cnblogs.com/xiaouisme/p/5166469.html sudo apt-get install rdesktop rdesktop 124.42.12 ...

  2. OpenSuSE Linux下安装Oracle10g的步骤

    OpenSuSE Linux下安装Oracle10g的步骤: --root用户 --1.vi etc/profile 添加脚本: if [ \$USER = "oracle" ]; ...

  3. PHP Zip File 函数

    通过 PHP 中的相关函数,你可以实现 zip 文件的解压缩操作! PHP Zip File 简介 Zip File 函数允许您读取压缩文件. 安装 如需在服务器上运行 Zip File 函数,必须安 ...

  4. sublime text package control 被墙的解决办法

    似乎没有办法 只能碰运气, 时好时坏. 或者手动安装 趁着好的时候, 下载离线包 https://packagecontrol.io/Package%20Control.sublime-package ...

  5. Android开发技巧——Camera拍照功能

    本篇是我对开发项目的拍照功能过程中,对Camera拍照使用的总结.由于camera2是在api level 21(5.0.1)才引入的,而Camera到6.0仍可使用,所以暂未考虑camera2. 文 ...

  6. Android 实现串口的移植

    安卓串口的实现,需要底层C++配合,不过这次我们根据framework中的思想,直接用API修改提供给JAVA层调用,这个就比较简单了. DEV项目需要,要实现在Android中实现串口的收发功能,有 ...

  7. linux 防火墙操作

    root/12345 (只能用ROOT操作)iptables -I INPUT -s x.x.x.x -p tcp --dport 8091 -j ACCEPT   #允许x.x.x.x访问本机的80 ...

  8. [OpenCV] How to install opencv by compiling source code

    Introduction Install OpenCV and its dependence ! STEPs 1, compiler sudo apt-get install build-essent ...

  9. MT8127:改变安卓系统权限问题

    找到对应的文件: system/extras/su/su.c 在main函数中,开头我们可以看下以下代码: uid_t current_uid = getuid(); if (current_uid ...

  10. RxJava操作符(02-创建操作)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51645348 本文出自:[openXu的博客] 目录: Create Defer Empty ...