【转】浅谈多核CPU、多线程、多进程 浅谈多核CPU、多线程、多进程

浅谈多核CPU、多线程、多进程

1.CPU发展趋势html

核心数目依旧会愈来愈多,依据摩尔定律,因为单个核心性能提高有着严重的瓶颈问题,普通的桌面PC有望在2017年底2018年初达到24核心(或者16核32线程),咱们如何来面对这突如其来的核心数目的增长?编程也要与时俱进。笔者斗胆预测,CPU各个核心之间的片内总线将会采用4路组相连:),由于全相连太过复杂,单总线又不够给力。并且应该是非对称多核处理器,可能其中会混杂几个DSP处理器或流处理器。程序员

 

2.多线程与并行计算的区别数据库

(1)多线程的做用不仅是用做并行计算,他还有不少颇有益的做用。编程

还在单核时代,多线程就有很普遍的应用,这时候多线程大多用于下降阻塞(意思是相似于数组

while(1)网络

{多线程

if(flag==1)架构

break;并发

sleep(1);负载均衡

}

这样的代码)带来的CPU资源闲置,注意这里没有浪费CPU资源,去掉sleep(1)就是纯浪费了。

阻塞在何时发生呢?通常是等待IO操做(磁盘,数据库,网络等等)。此时若是单线程,CPU会干转不干实事(与本程序无关的事情都算不干实事,由于执行其余程序对我来讲没意义),效率低下(针对这个程序而言),例如一个IO操做要耗时10毫秒,CPU就会被阻塞接近10毫秒,这是何等的浪费啊!要知道CPU是数着纳秒过日子的。

因此这种耗时的IO操做就用一个线程Thread去代为执行,建立这个线程的函数(代码)部分不会被IO操做阻塞,继续干这个程序中其余的事情,而不是干等待(或者去执行其余程序)。

一样在这个单核时代,多线程的这个消除阻塞的做用还能够叫作“并发”,这和并行是有着本质的不一样的。并发是“伪并行”,看似并行,而实际上仍是一个CPU在执行一切事物,只是切换的太快,咱们无法察觉罢了。例如基于UI的程序(俗话说就是图形界面),若是你点一个按钮触发的事件须要执行10秒钟,那么这个程序就会假死,由于程序在忙着执行,没空搭理用户的其余操做;而若是你把这个按钮触发的函数赋给一个线程,而后启动线程去执行,那么程序就不会假死,继续相应用户的其余操做。可是,随之而来的就是线程的互斥和同步、死锁等问题,详细见有关文献。

如今是多核时代了,这种线程的互斥和同步问题是更加严峻的,单核时代大都算并发,多核时代真的就大为不一样,为何呢?具体细节请参考有关文献。我这里简单解释一下,之前volatile型变量的使用能够解决大部分问题,例如多个线程共同访问一个Flag标志位,若是是单核并发,基本不会出问题(P.S.在什么状况下会出问题呢?Flag有多个,或者是一个数组,这时候只能经过逻辑手段搞定这个问题了,多来几回空转无所谓,别出致命问题就行),由于CPU只有一个,同时访问这个标志位的只能有一个线程,而多核状况下就不太同样了,因此仅仅volatile不太能解决问题,这就要用到具体语言,具体环境中的“信号量”了,Mutex,Monitor,Lock等等,这些类都操做了硬件上的“关中断”,达到“原语”效果,对临界区的访问不被打断的效果,具体就不解释了,读者能够看看《现代操做系统》。

(2)并行计算还能够经过其余手段来得到,而多线程只是其中之一。

其余手段包括:多进程(这又包括共享存储区的和分布式多机,以及混合式的),指令级并行。

ILP(指令级并行),x86架构里叫SMT(同时多线程),在MIPS架构里与之对应的是super scalar(超标量)和乱序执行,两者有区别,但共同点都是能够达到指令级并行,这是用户无法控制的,不属于编程范围,只能作些有限的优化,而这有限的优化可能只属于编译器管辖的范畴,用户能作的甚少。

(3)典型的适于并行计算的语言

Erlang和MPI:这两个前者是语言,后者是C++和Fortran的扩展库,效果是同样的,利用多进程实现并行计算,Erlang是共享存储区的,MPI是混合型的。

C#.NET4.0:新版本4.0能够用少许代码实现并行For循环,以前版本须要用很繁琐的代码才能实现一样功能。这是利用了多线程实现并行计算。Java和C#3.5都有线程池(ThreadPool),也是不错的很好用的多线程管理类,能够方便高效的使用多线程。

CUDA,仍是个初生牛犊,有很大的发展潜力,只不过就目前其应用领域颇有限。其目前只能使用C语言,并且还不是C99,比较低级,不能使用函数指针。我的感受这因为硬件上天生的局限性(平均每一个核心可用内存小,与系统内存通信时间长),只适用于作科学计算,静态图像处理,视频编码解码,其余领域,还不如高端CPU。等之后GPU有操做系统了,能充分调度GPU资源了,GPU就能够当大神了。游戏中的物理加速,实际上多核CPU也能很好的作到。

其余语言。。。恩。。留做未来讨论。

 

3.线程越多越好吗?何时才有必要用多线程?

线程必然不是越多越好,线程切换也是要开销的,当你增长一个线程的时候,增长的额外开销要小于该线程可以消除的阻塞时间,这才叫物有所值。

Linux自从2.6内核开始,就会把不一样的线程交给不一样的核心去处理。Windows也从NT.4.0开始支持这一特性。

何时该使用多线程呢?这要分四种状况讨论:

a.多核CPU——计算密集型任务。此时要尽可能使用多线程,能够提升任务执行效率,例如加密解密,数据压缩解压缩(视频、音频、普通数据),不然只能使一个核心满载,而其余核心闲置。

b.单核CPU——计算密集型任务。此时的任务已经把CPU资源100%消耗了,就不必也不可能使用多线程来提升计算效率了;相反,若是要作人机交互,最好仍是要用多线程,避免用户无法对计算机进行操做。

c.单核CPU——IO密集型任务,使用多线程仍是为了人机交互方便,

d.多核CPU——IO密集型任务,这就更不用说了,跟单核时候缘由同样。

 

4.程序员须要掌握的技巧/技术

(1)减小串行化的代码用以提升效率。这是废话。

(2)单一的共享数据分布化:把一个数据复制不少份,让不一样线程能够同时访问。

(3)负载均衡,分为静态的和动态的两种。具体的参见有关文献。