建立高效的并发模型 in cpp

来源:互联网 发布:淘宝商城行车记录仪 编辑:程序博客网 时间:2024/05/21 00:49

在C++11中,标准库为我们实现了std::thread,实现多线程变得容易了许多,然而对每个job直接启动一个thread有点奢侈,因为thread的上下文切换是比较慢的,那么有人可能会说使用线程池,但是使用线程池有一个问题,如果一个线程被block,那么这个线程常年占着位置不工作,妨碍了并行度,另外,线程池需要保证一定数量的线程运行,那么在job较少的情况下,CPU资源的浪费较大。
于是,吸收了go的设计思想,这里设计了一种模型,真正做事的线程thread称为M,每个并行的工作单元称为G,G是真正运行的代码,但是G并不与M绑定,而是与一个上下文结构P联系。P有着一个自己的可运行的G队列,P是真正的并行单元,P最多数量与CPU核心数一致,而M的数量可能多于CPU数量,这就可以使得当有一个G在block的时候,仍然能保证最高的并行度(这时候P可以逃离M,选择其他的M)。
这里主要保证了同一时间总有一个线程在空旋,如果有G被提交,那么就有一个新的M开始空旋,旧的M空旋过程中发现空旋数变多了,便开始进入工作状态。M寻找一个空闲的P去运行,在P的队列中拿出G,如果P中没有G可用,P会从其他的P那里偷一半的G来用。而如果M被阻塞,P会逃跑去找另一个M,来保证并发度不损失。
里面涉及到很多锁机制和竞争条件,代码可以子在这里看到:CppGo,M阻塞的情况由于涉及到syscall,暂时还未完成,已完成部分与std::thread的对比如下图:
std::thread * 30
go::commit * 30
可以看到,CPU利用率大大提高,时间明显缩短。

0 0
原创粉丝点击