首页 > 其他分享 >Go Work Stealing 机制

Go Work Stealing 机制

时间:2023-12-11 19:01:23浏览次数:37  
标签:goroutine 队列 Work 线程 Stealing Go 窃取

一、什么是 Work Stealing
Go语言的 Work Stealing 机制是一种用于调度协程(Goroutines)的策略,有助于充分利用多核CPU,提高并发性能,降低锁竞争,从而使Go程序更高效地运行

Work Stealing 机制的核心思想:每个操作系统线程(M)都有一个本地任务队列,它会尽可能地先执行自己队列中的协程。当某个M的P队列为空,而其他P仍有任务时,该M会尝试从其他P中"偷"一些协程来执行,以实现负载均衡

二、Work Stealing 算法

当从本线程M 从绑定 P 本地 队列、全局G队列、Netpoller 都找不到可执行的 G,会从其它 P 里窃取G并放到当前P上面

1)如果全局队列有G,从全局队列窃取的G数量:N = min(len(GRQ)/GOMAXPROCS + 1, len(GRQ/2)) (根据GOMAXPROCS数量负载均衡)

2)如果 Netpoller 有G(网络IO被阻塞的G),从Netpoller窃取的G数量:N = 1

3)如果从其它P里窃取G,从其它P窃取的G数量:N = len(LRQ)/2(平分负载均衡)

4)如果尝试多次一直找不到需要运行的goroutine则进入睡眠状态,等待被其它工作线程唤醒

从其它P窃取G的源码见runtime/proc.go stealWork函数,窃取流程如下:

1)选择要窃取的P

2)从P中偷走一半G

选择要窃取的P
窃取的实质就是遍历所有P,查看其运行队列是否有goroutine,如果有,则取其一半到当前工作线程的运行队列

为了保证公平性,遍历P时并不是按照数组下标顺序访问P,而是使用了一种伪随机的方式遍历allp中的每个P,防止每次遍历时使用同样的顺序访问allp中的元素

offset := uint32(random()) % nprocs
coprime := 随机选取一个小于nprocs且与nprocs互质的数
const stealTries = 4 // 最多重试4次
for i := 0; i < stealTries; i++ {
  // 随机访问所有 P
    for i := 0; i < nprocs; i++ {
        p := allp[offset]
        从p的运行队列偷取goroutine
        if 偷取成功 {
        break
        }
        offset += coprime
        offset = offset % nprocs
     }
}

可以看到只要随机数不一样,遍历P的顺序也不一样,但可以保证经过nprocs次循环,每个P都会被访问到

从P中偷走一半G
挑选出盗取的对象P之后,则调用 runtime/proc.go 函数runqsteal 盗取P的运行队列中的goroutine,runqsteal函数再调用runqgrap从P的本地队列尾部批量偷走一半的 G

func runqgrab(_p_ *p, batch *[256]guintptr, batchHead uint32, stealRunNextG bool) uint32 {
    for {
        h := atomic.LoadAcq(&_p_.runqhead) // load-acquire, synchronize with other consumers
        t := atomic.LoadAcq(&_p_.runqtail) // load-acquire, synchronize with the producer
        n := t - h        //计算队列中有多少个goroutine
        n = n - n/2     //取队列中goroutine个数的一半
        if n == 0 {
            ......
            return ......
        }
        return n
    }
}

三、 Work Stealing 的优点
1)提高线程利用率:当线程M绑定的P⽆可运⾏的G时,尝试从其他P偷取G,减少空转

2)减少锁竞争:每个M都有自己的本地队列,避免了每次多线程访问全局队列时的锁竞争,提高了性能。

3)自动负载均衡:通过偷取其他M的任务,Work Stealing可以自动平衡不同线程的工作负载,提高系统整体的并发性能。

 

标签:goroutine,队列,Work,线程,Stealing,Go,窃取
From: https://www.cnblogs.com/beatle-go/p/17895147.html

相关文章

  • 部署 Argo Rollouts v1.6.3
    创建nsargo-rollouts#kubectlcreatenamespaceargo-rolloutsnamespace/argo-rolloutscreated安装 argo-rollouts#kubectlapply-nargo-rollouts-fhttps://github.com/argoproj/argo-rollouts/releases/latest/download/install.yamlcustomresourcedefinition.api......
  • InstallShield 集成.net Framework的安装包制作
    .netFramework出现之前,一直用innosetup,setupfactory等工具打包,后来,.netFramework1.0/1.1同行的vs2002/2003中有了安装项目,制作也很方便,另外,微软也提供了一个强大的组件:MicrosoftVisualStudio.NET2003引导程序插件。通过MicrosoftVisualStudio.NET2003引导程序插件......
  • HyperWorks2021软件安装教程
    下载软件资源下载产品介绍:HyperWorks一款功能强大的开放式架构仿真软件。拥有先进的技术以及高性能、高效和创新的产品,为用户提供了设计、仿真和制造等服务。支持电磁分析设计、材料建模制造、多物理场分析等功能,用户可以进行庞大且复杂的有限元模型创建操作。软件特色1......
  • mongodb
    mongodb内部培训目录简介基础概念适用场景数据建模嵌入式数据模型标准化数据模型N对N关系事务生产经验一般查询符Null大数据量查询索引创建索引索引名称索引类型单字段索引复合索引多键索引索引的属性唯一索引部分索引稀疏索引HiddenInd......
  • Go 语言字符串使用方式与技巧
    Go语言字符串使用方式与技巧原创 frank Golang语言开发栈 2023-12-1023:00 发表于北京收录于合集#Golang语言156个#Golang进阶学习106个大家好,我是frank。欢迎大家点击标题下方蓝色文字「Golang语言开发栈」关注公众号。公众号主页点击右上角三个点图标,设......
  • golang之泛型
    Go1.18版本增加了对泛型的支持,泛型也是自Go语言开源以来所做的最大改变。 泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。ーー换句话说,在编写某些代码或数据结构时先不提供值的类型,而是之后再提供。泛型是一种......
  • Django笔记四十四之Nginx+uWSGI部署Django以及Nginx负载均衡操作
    本文首发于公众号:Hunter后端原文链接:Django笔记四十四之Nginx+uWSGI部署Django以及Nginx负载均衡操作这一篇笔记介绍如何使用Nginx+uWSGI来部署Django。上一篇笔记中有介绍直接使用uWSGI作为web服务器来部署Django,这一篇笔记介绍如何使用Nginx来部署。使用Ngin......
  • golang按换行符一行一行读取GBK文件
    packageawesomeProject1import( "bufio" "fmt" "github.com/axgle/mahonia" "io" "log" "os")funcmain(){ filename:="/tmp/test.txt" readTbkByLine(filename)}funcreadTbkBy......
  • 初中英语优秀范文100篇-023Good Habits Make Me Better -好习惯让我更优秀
    PDF格式公众号回复关键字:SHCZFW023记忆树1Itisessentialtodevelopgoodhabits,whichmakeabigdifferencetoourlife.翻译养成好习惯非常重要,这对我们的生活产生了巨大的影响。简化记忆习惯句子结构主语:It(虚主语)谓语:is(系动词)表语:essential......
  • Retentive Networks Meet Vision Transformers, 视觉RetNet
    alias:Fan2023tags:RetNetrating:⭐share:falseptype:articleRMT:RetentiveNetworksMeetVisionTransformers初读印象comment::(RMT)RetentiveNetwork(RetNet)因其显式衰减机制而在自然语言处理中受到关注,但它不适合基于图像的任务。本文提出了保留性自我注意力......