屏障

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. 64. Minimum Path Sum(中等, 又做出一个DP题, 你们非问我开不开心,当然开心喽!^^)

    Given an m x n grid filled with nonnegative numbers, find a path from top left to bottom right which ...

  2. Python List insert()方法详解

    1.功能insert()函数用于将指定对象插入列表的指定位置. 2.语法list.insert(index, obj) 3.参数index: 对象obj需要插入的索引位置.obj: 插入列表中的对象. ...

  3. Docker常见仓库MongoDB

    MongoDB 基本信息 MongoDB 是开源的 NoSQL 数据库实现. 该仓库提供了 MongoDB 2.2 ~ 2.7 各个版本的镜像. 使用方法 默认会在 27017 端口启动数据库. $ ...

  4. 《读书报告 -- Elasticsearch入门 》-- 安装以及简单使用(1)

    <读书报告 – Elasticsearch入门 > 第一章 Elasticsearch入门 Elasticsearch是一个实时的分布式搜索和分析引擎,使得人们可以在一定规模上和一定速度上 ...

  5. Touch 方法&属性 映射工具

    Touch 方法&属性 映射工具(0.5 版本) 标签 : github 线上后门与接口调试: 原先需要测试一个接口(如Dubbo.DAO), 或为线上留后门, 需要写大量的Web层(Api. ...

  6. ERROR: Cannot change version of project facet Dynamic Web Module to 3.0?

    Issue: When you create web app in eclipse with maven configuration, you may get following error. Can ...

  7. Android Studio精彩案例(三)《模仿微信ViewPage+Fragment实现方式二》

    转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 写在前面的话:此专栏是博主在工作之余所写,每一篇文章尽可能写的思路清晰一些,属于博主的"精华"部分,不同于以往专栏 ...

  8. Zookeeper动态更新服务器列表

    -------------------------------------------------------------------------------------- [版权申明:本文系作者原创 ...

  9. 微信小程序基础之交互操作控件

    好久没有写关于微信小程序的文章了,今天简单的发表一篇,内容比较简单,包括:ActionSheet上拉菜单.AlertAction提示框.SuccessAction完成框.LoadingAction加载 ...

  10. 搭建ejabberd集群

    搭建ejabberd集群(金庆的专栏 2016.8)以2台机器搭建一个ejabberd集群.2台机器都是外网一块网卡,内网另一块网卡.新建一个域名,添加2台机器的外网IP.分别用源码安装ejabber ...