您的位置:首页 > 健康 > 美食 > go GMP 模型,为什么要有 P?

go GMP 模型,为什么要有 P?

2024/12/24 2:47:35 来源:https://blog.csdn.net/2401_82869454/article/details/140274082  浏览:    关键词:go GMP 模型,为什么要有 P?

GM 模型

在 Go1.1 之前 Go 的调度模型其实就是 GM 模型,也就是没有 P。

static void
schedule(G *gp)
{...schedlock();if(gp != nil) {...switch(gp->status){case Grunnable:case Gdead:// Shouldn't have been running!runtime·throw("bad gp->status in sched");case Grunning:gp->status = Grunnable;gput(gp);break;}gp = nextgandunlock();gp->readyonstop = 0;gp->status = Grunning;m->curg = gp;gp->m = m;...runtime·gogo(&gp->sched, 0);
}
  1. 调用 schedlock 方法来获取全局锁。
  2. 获取全局锁成功后,将当前 Goroutine 状态从 Running(正在被调度) 状态修改为 Runnable(可以被调度)状态。
  3. 调用 gput 方法来保存当前 Goroutine 的运行状态等信息,以便于后续的使用;
  4. 调用 nextgandunlock 方法来寻找下一个可运行 Goroutine,并且释放全局锁给其他调度使用。
  5. 获取到下一个待运行的 Goroutine 后,将其的运行状态修改为 Running。
  6. 调用 runtime·gogo 方法,将刚刚所获取到的下一个待执行的 Goroutine 运行起来。

GM 模型的缺点:
在这里插入图片描述
Go1.0 的 GM 模型的 Goroutine 调度器限制了用 Go 编写的并发程序的可扩展性,尤其是高吞吐量服务器和并行计算程序。
实现有如下的问题:

  • 存在单一的全局 mutex(Sched.Lock)和集中状态管理:mutex 需要保护所有与 goroutine 相关的操作(创建、完成、重排等),导致锁竞争严重。

  • Goroutine 传递的问题:goroutine(G)交接(G.nextg):工作者线程(M’s)之间会经常交接可运行的 goroutine。上述可能会导致延迟增加和额外的开销。每个 M 必须能够执行任何可运行的 G,特别是刚刚创建 G 的 M。

  • 每个 M 都需要做内存缓存(M.mcache):
    会导致资源消耗过大(每个 mcache 可以吸纳到 2M 的内存缓存和其他缓存),数据局部性差。

  • 频繁的线程阻塞/解阻塞:
    在存在 syscalls 的情况下,线程经常被阻塞和解阻塞。这增加了很多额外的性能开销。

GMP 模型

为了解决 GM 模型的以上诸多问题,在 Go1.1 时,Dmitry Vyukov 在 GM 模型的基础上,新增了一个 P(Processor)组件。并且实现了 Work Stealing 算法来解决一些新产生的问题。

有哪些改进

  • 每个 P 有自己的本地队列,大幅度的减轻了对全局队列的直接依赖,所带来的效果就是锁竞争的减少。而 GM 模型的性能开销大头就是锁竞争。

  • 每个 P 相对的平衡上,在 GMP 模型中也实现了 Work Stealing 算法,如果 P 的本地队列为空,则会从全局队列或其他 P 的本地队列中窃取可运行的 G 来运行,减少空转,提高了资源利用率。

为什么要有 P

  • 一般来讲,M 的数量都会多于 P。像在 Go 中,M 的数量默认是 10000,P 的默认数量的 CPU 核数。另外由于 M 的属性,也就是如果存在系统阻塞调用,阻塞了 M,又不够用的情况下,M 会不断增加。

  • M 不断增加的话,如果本地队列挂载在 M 上,那就意味着本地队列也会随之增加。这显然是不合理的,因为本地队列的管理会变得复杂,且 Work Stealing 性能会大幅度下降。

  • M 被系统调用阻塞后,我们是期望把他既有未执行的任务分配给其他继续运行的,而不是一阻塞就导致全部停止。

因此使用 M 是不合理的,那么引入新的组件 P,把本地队列关联到 P 上,就能很好的解决这个问题。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com