多线程就必定快吗?天真!

 

 

在《多线程排序》中介绍了多线程排序,彷佛看起来多线程快了不少,然而多线程就必定更快吗?html

为何多线程就不必定快?

仍是拿《多线程排序-真香!》中的程序举例,下面是各个线程数量的排序结果:算法

线程数 时间/s

1编程

2.393644数据结构

2多线程

1.367392函数

3工具

1.386448ui

4命令行

1.036919线程

5

1.097992

6

1.218000

7

1.184615

8

1.176258

以上结果可能不许确,可是体现了一些变化趋势,即并非线程数量越多越快,也不是单线程最快,而是线程数为4的时候最快。

为何呢?

缘由在于个人机器只有4个逻辑CPU,所以4是最合适的。为了避免解释太多术语,简单解释一下。一个CPU就像一条流水线,会执行一系列指令,当你不少指定拆成4份(4线程)的时候,它是正好最合适的,少的时候,有一个闲着;而多了,就会存在抢占的状况。举个简单的例子,假设有4个水管能够出水,你如今去接水,那么你在每一个水管下放一个桶去接水,天然要比只在一个水管下去接水要快的,可是若是你的水桶数量多于水管数,为了每一个水桶都要有水,你在这个过程当中就须要去切换水桶,每一个水桶换一下,才能都接得上,而换的这个过程就像线程的上下文切换带来的开销

所以,不是线程越多越快,最合适的才最快

单线程有时候反而更快

说到这你可能更会奇怪了,为何单线程有时候反而会更快呢?仍是拿接水为例,假设虽然有4个水管,可是你只有一个桶,所以你一我的从这个水管里一直接水是最快的;而若是你拿两个桶,这个接一点,又换一下,那个接一点,又换一下,中间显然有切换致使的中断,相同时间内单个桶接的比较多;这就是单核CPU妄图使用多线程提升效率或者每一个线程都须要竞争同一把锁而实际可能会致使更慢的缘故。

举个绑核的例子:

 

$ taskset -c 1 taskset -c 1 ./multiThread 4
thread num:4
time 2.378558

我使用taskset将程序绑定在一个CPU上运行,能够看其时间足足是不绑核的时候的两倍有余。

什么叫都须要竞争呢?举个极端的例子,咱们修改前面的工做线程代码以下:

 

/*比较线程,采用快速排序*/

void * workThread(void *arg)
{
    pthread_mutex_lock(&mutex);
    SortInfo *sortInfo = (SortInfo*)arg;
    long idx = sortInfo->startIdx;
    long num = sortInfo->num;
    qsort(&nums[idx],num,sizeof(long),compare);
    pthread_mutex_unlock(&mutex);
    pthread_barrier_wait(&b);
    return ((void*)0);
}

这里的例子比较极端,在排序的时候都给它们加上了锁(关于锁,后面会有文章进行更加详细的介绍。),即哪一个线程拿到了锁,就能够继续工做,没有拿到的继续等待。使用完成后再释放。
在这样的状况下,看看4线程还有效果吗?

 

$ ./multiThread 4
thread num:4
time 2.480588

是最快的时候两倍多的时间!并且还比单个线程的时候要慢!!!

而另一种状况,好比说从队列中取出数据,而后进行耗时处理,那么对取出数据的操做进行加锁是可行的,多线程的状况仍然能提升处理速度。但若是你仅仅是读取数据,那么单线程的状况可能会比多线程要快,由于它避免了线程上下文切换的开销

扩展介绍-绑核

为何要绑核?

  • 充分利用CPU,减小CPU之间上下文切换

  • 指定程序运行在指定CPU,便于区分

 

$ taskset -c 1 ./proName

将proName绑定在第二个核。

 

$ taskset -c 1-3  ./proName

绑定运行在第二个到第四个核。

 

$ taskset -p 3569
pid 3569's current affinity mask: f

查看进程3569当前运行在哪一个核上。

mask f转为二进制即为1111,所以四个核都有运行。

固然除了命令行,还有函数接口可使用,这里就再也不扩展了。

如何查看机器的CPU数量

物理CPU个数,就是你实际CPU的个数:

 

$ cat /proc/cpuinfo | grep "physical id" | sort -u | wc -l 
1

CPU物理核数,就是你的一个CPU上有多少个核心,如今不少CPU都是多核:

 

$ cat /proc/cpuinfo | grep "core id" | sort -u | wc -l
2

CPU逻辑核数,一颗物理CPU能够有多个物理内核,加上超线程技术,会让CPU看起来有不少个:

$ cat /proc/cpuinfo | grep "processor" | sort -u | wc -l
4

总结

线程上下文切换是有开销的,若是它的收益不能超过它的开销,那么使用多线程来提升效率将得不偿失。所以不要盲目推崇多线程。若是为了提升效率采用多线程,那么线程中最多应为逻辑CPU数。也就是说若是你的程序绑在一个核上或者你只有一个CPU一个核,那么采用多线程只能提升同时处理的能力,而不能提升处理效率。

https://www.yanbinghu.com/2019/12/25/46016.html

来源:公众号【编程珠玑】

做者:守望先生

ID:shouwangxiansheng

 

相关精彩推荐

多线程排序-真香!

我有一个问题,用了多线程后,两个问题有了如今

系统编程-文件读写这件小事

生成随机数的方式你选对了吗?

 

关注公众号【编程珠玑】,获取更多Linux/C/C++/数据结构与算法/计算机基础/工具等原创技术文章。后台免费获取经典电子书和视频资源