用于处理器中的线程组的可扩展负载均衡的技术的制作方法

未命名 09-22 阅读:48 评论:0
用于处理器中的线程组的可扩展负载均衡的技术1.相关申请的交叉引用2.本技术涉及以下共同转让的共同未决的美国专利申请,将这些专利申请中的每一个的全部内容通过引用合并于此:3.2022年3月10日提交的题目为“用于高效访问多维数据结构和/或其他大数据块的方法和装置(methodandapparatusforefficientaccesstomultidimensionaldatastructuresand/orotherlargedatablocks)”的美国申请no.17/691,276;4.2022年3月10日提交的题目为“协作组阵列(cooperativegrouparrays)”的美国申请no.17/691,621;5.2022年3月10日提交的题目为“分布式共享存储器(distributedsharedmemory)”的美国申请no.17/691,690;6.2022年3月10日提交的题目为“虚拟化处理器中的硬件处理资源(virtualizinghardwareprocessingresourcesinaprocessor)”的美国申请no.17/691,759;7.2022年3月10日提交的题目为“跨多个计算引擎的程序控制的数据多播(programmaticallycontrolleddatamulticastingacrossmultiplecomputeengines)”的美国申请no.17/691,288;8.2022年3月10日提交的题目为“具有异步事务支持的硬件加速的同步(hardwareacceleratedsynchronizationwithasynchronoustransactionsupport)”的美国申请no.17/691,296;9.2022年3月10日提交的题目为“处理器和存储器中的快速数据同步(fastdatasynchronizationinprocessorsandmemory)”的美国申请no.17/691,303;10.2022年3月10日提交的题目为“高效矩阵乘法和与一组线程束相加(efficientmatrixmultiplyandaddwithagroupofwarps)”的美国申请no.17/691,406;11.2022年3月10日提交的题目为“不需要硬件复位的处理组件之间的执行软件的灵活迁移(flexiblemigrationofexecutingsoftwarebetweenprocessingcomponentswithoutneedforhardwarereset)”的美国申请no.17/691,808;以及12.2022年3月10日提交的题目为“用于高效访问多维数据结构和/或其他大数据块的方法和装置(methodandapparatusforefficientaccesstomultidimensionaldatastructuresand/orotherlargedatablocks)”的美国专利申请no.17/691,422。
背景技术
::13.用户希望随着图形处理单元(gpu)技术的改进以及处理核心单元的数量随着每代而每芯片增加,深度学习和高性能计算(hpc)计算程序继续扩展。所期望的是单个应用程序的解决方案的更快时间,不仅仅通过运行n个独立的应用程序来扩展。14.现代gpu是多处理器系统。每个gpu的处理器数量(我们称它们为“流式多处理器”或“sm”,但其他供应商可能会用其他名称来称呼它们,例如“执行单元”或“核心”)逐代增加,并且变得更具挑战性以与gpu的大小成比例地扩展应用程序的性能。图1a示出了包括顺序相关的计算密集层的长链的示例深度学习(dl)网络。使用诸如例如将输入激活与权重矩阵相乘以产生输出激活的运算来计算每个层。所述层通常通过将工作划分为输出激活图块(tile)而跨gpu或gpu集群并行化,每个输出激活图块都表示一个sm或处理核心将处理的工作。15.由于潜在大量的计算深度学习需求,通常目标更快。并且与连续地执行所有这些计算相比,并行执行许多计算将加速处理具有直观意义。事实上,应用通过在给定gpu实现上运行而实现的性能益处的量通常完全取决于它可以并行化的程度。但是存在不同的并行化方法。16.在概念上,为了加速进程,可以使每个并行处理器执行多个工作,或者可以替代地保持每个并行处理器上的工作量恒定并且添加更多处理器。考虑重铺几英里长的高速路的工作量。你作为项目经理想要在最短的时间量内完成重铺工作以最小化业务中断。显然,如果你有几名工作人员在道路的不同部分并行工作,道路重铺工程将更快地完成。但是,哪种方法将使工作更快速地完成呢——要求每个道路工作人员做更多的工作,还是增加更多的工作人员,每个工作人员做相同的工作量?结果是,答案取决于工作的性质和用于支持该工作的资源。17.图1b的弱扩展示例示出了每个处理核心运行的激活图块的大小增长,从而表明每个处理核心做更多工作。图1c的强扩展示例同时保持每个处理核心执行的工作量恒定(固定大小的网络由固定图块大小指示),而增加并行操作的处理核心的数量(如由省略号指示)。表现出线性强扩展的应用具有等于所使用的处理器的数量的加速。参见https://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html;https://hpc-wiki.info/hpc/scaling_tests。对于一些应用,诸如dl训练,问题大小通常将保持恒定,因此仅强扩展适用。18.因此,此类应用的用户通常想要强扩展,这意味着单个应用可以在不必改变其工作负载(例如,通过增加其批大小来创建更固有的并行性)的情况下实现更高的性能。当在提供更多并行处理器的新的、容量更大的gpu平台上运行现有的(例如,重新编译的)应用时,用户还期望提高的速度性能。如以下描述的,gpu开发已经满足或甚至超过市场在更多并行处理器和在那些并行处理器上运行的增加数量的并行执行线程之间的更多协调/协作方面的期望——但是仍需要进一步的性能改进以实现强扩展。19.增加的gpu计算并行性和复杂性20.多年来,gpu硬件已经变得越来越复杂并且能够实现增加的并行性。例如,图2a示出了较旧的gpu架构,该较旧的gpu架构提供具有16个sm的流式执行模型,这16个流式多处理器在每个具有四个sm的集群(gpc)中,其中每个sm表示gpu实际面积(realestate)的大部分。在此上下文中,sm或“流式多处理器”是指按照诺德奎斯特(nordquist)的usp7,447,873中所述架构的处理器,包括对其的改进和改进,并且例如在多代nvidiagpu中实现。在许多情况下,此类sm已被构建为提供快速的本地共享存储器,从而在sm上执行的所有线程之间实现数据共享/重用和同步。21.相比之下,更多最近的gpu的半导体基板布局的图2b图示示出并行计算能力的显著增加,包括非常大量的(例如,128个或更多个)sm,每个sm仅表示gpu半导体基板实际面积的一小部分——其中数学计算硬件和每个sm内的并行处理核心的数量也随时间增长。22.图2c示出了包括高级计算硬件能力的现代sm的示例架构图,该现代sm包括许多并行数学核心,这些并行数学核心除了纹理处理单元之外还包括多个张量核心。例如,2017nvidiavoltagv100sm被划分成四个处理块,每个处理块具有16个fp32核心、8个fp64核心、16个int32核心、用于深度学习矩阵算术的两个混合精度张量核心、l0指令高速缓存、一个线程束调度器、一个分派单元和64kb寄存器文件——并且将来的gpu设计可能继续该趋势。这种增加的计算并行性使得能够显著减少计算处理时间。23.同时,图3和图4示出了现代gpu可以提供各种不同的硬件分区和层次结构。在这些示例中,gpu内的sm本身可分组成较大功能单元。例如,gpu的图形处理集群(gpc)可包括多个纹理处理集群(tpc)和流式多处理器(sm)的附加阵列(例如,用于计算能力)以及其他支持硬件,例如用于实时光线追踪加速的光线追踪单元。每个sm又可被分区成多个独立的处理块,每个处理块具有一个或若干个不同种类的核心(例如,fp32、int32、张量等)、线程束调度器、分派单元和本地寄存器文件。24.图5和图5a示出了一些gpu实现方式(例如,nvidiaampere)可以如何实现作为微gpu运行的多个分区,诸如μgpu0和μgpu1,其中,每个微gpu包括整个gpu的处理资源的一部分。当gpu被分区为两个或更多个单独的更小的μgpu以供不同客户端访问时,资源(包括物理存储器设备165,诸如本地l2高速缓存存储器)通常也被分区。例如,在一种设计中,被耦合到ugpu0的物理存储器设备165的第一半部可对应于第一组存储器分区位置,且被耦合到ugpu1的物理存储器设备165的第二半部可对应于第二组存储器分区位置。gpu内的性能资源还根据两个或更多单独的较小处理器分区来分区。资源可包括二级高速缓存(l2)资源170和处理资源160。这种多实例gpu(“mig”)特征的一个实施例允许将gpu安全地分区成用于cuda(“计算统一设备架构”)应用的许多单独的gpu实例,从而为多个用户提供单独的gpu资源以加速其相应的应用。25.关于此类先前gpu硬件及其如何进展的更多信息,参见例如usp8,112,614;usp7,506,134;usp7,836,118;usp7,788,468;us10909033;us20140122809;林德霍姆(lindholm)等人,“nvidiatesla:统一图形和计算架构(aunifiedgraphicsandcomputingarchitecture),”ieeemicro(2008);https://docs.nvidia.com/cuda/parallel-thread-execution/index.html(2021年检索到的);肖凯特(choquette)等人,“volta:性能和可编程性(performanceandprogrammability)”,ieeemicro(第38卷,发布于2018年3月/4月2日),doi:10.1109/mm.2018.022071134。26.协作组api软件实现27.为了利用由现代gpu提供的增加的并行性,cuda版本9中的nvidia引入了基于软件的“协作组”api,用于定义和同步cuda程序中的线程组以允许内核动态地组织线程组。参见例如https://developer.nvidia.com/blog/cooperative-groups/(2021年检索的);https://developer.nvidia.com/blog/cuda-9-features-revealed/(2021年检索的);鲍勃·克罗维拉(bobcrovella)等人,“协作组(cooperativegroups)”ꢀ(09/17/2020),https://vimeo.com/461821629;us2020/0043123。28.在协作组api之前,执行控制(即,线程同步)和线程间通信两者通常限于在一个sm上执行的线程块(也称为“协作线程阵列”或“cta”)的级别。协作组api扩展cuda编程模型以描述在网格内和跨网格或跨多个网格并因此潜在地(取决于硬件平台)跨设备或多个设备的同步模式。29.协作组api提供cuda设备代码api,用于定义、分区和同步线程组——其中,“组(group)”是可编程的并且可以跨线程块延伸。协作组api还提供主机侧api,用于启动其线程全部由基于软件的调度调度以并发地启动的网格。这些协作组api基元实现cuda内的协作并行性的附加模式,包括跨整个线程网格或甚至跨多个gpu的生产者-消费者并行性和全局同步,而不需要底层gpu平台的硬件改变。30.例如,协作组api提供全网格(grid-wide)(并且因此通常是全设备(device-wide))同步屏障(“grid.sync()”),该同步屏障可以用于防止网格组内的线程行进超过屏障,直到定义的网格组内的所有线程已经到达该屏障。这种全设备同步基于网格组(“grid_group”)的概念,该网格组在同一网格内定义一组线程,由软件调度为驻留在设备上并且可在该设备上调度,其方式为使得网格组中的每个线程可以向前进展。线程组的大小范围可以从几个线程(小于线程束)到整个线程块、到网格启动中的所有线程块、到跨越多个gpu的网格。较新的gpu平台(诸如nvidiapascal和voltagpu)实现全网格和多gpu同步组,并且volta的独立线程调度实现以任意交叉线程束和子线程束粒度对线程组的显著更灵活的选择和分区。31.因此提供协作组api用于跨或甚至超出网格的协作/合作线程,但具有某些限制。例如,协作组api使用软件而不是硬件来提供并发地执行。在没有硬件级的并发保证的情况下,附加的api调用对于评估gpu占用以便预测网格组是否可以启动通常是必要的——并且因此在许多情况下确定sm占用被留给软件应用。另外,虽然在一些平台上提供对全系统同步/存储器屏障的某些硬件支持,但是缺乏用于跨在不同sm上运行的线程块并因此跨设备或跨多个设备高效地共享数据带宽的高性能机制。作为一个重要的示例,不能跨多个sm高效地利用数据读取通常将导致冗余数据检索——其产生数据带宽不能跟上计算带宽的性能瓶颈。因为协作组api是基于软件的,所以它不能在硬件级上解决这些挑战。参见例如张(zhang)等人,nvidiagpu中的单设备和多设备同步方法的研究(astudyofsingleandmulti-devicesynchronizationmethodsinnvidiagpu),(arxiv:2004.05371v1[cs.dc]2020年4月11日);卢斯蒂格(lustig)等人,“nvidiaptx存储器一致性模型的正式分析(aformalanalysisofthenvidiaptxmemoryconsistencymodel)”,编程语言和操作系统的架构支持的第二十四届国际会议的论文集,第257-270页(2019年4月)https://doi.org/10.1145/3297858.3304043;韦伯(weber)等人,“朝向模块化整数gcd算法扩展摘要的多gpu实现方式(towardamulti-gpuimplementationofthemodularintegergcdalgorithmextendedabstract)”ꢀicpp2018年8月13-16日,尤金(eugene),俄勒冈州(orusa)(acm2018);乔格(jog)等人,“owl:提高gpgpu性能的协作线程阵列感知调度技术(cooperativethreadarrayawareschedulingtechniquesforimprovinggpgpuperformance))”(asplos’13,2013年3月16-20日,休斯顿,德克萨斯州,美国)。[0032]数据带宽跟不上处理带宽[0033]虽然已经有可能增加每代新的gpu硬件的数学吞吐量,但是越来越难以向新的gpu硬件中的sm或处理核心(例如,张量核心)的其他集合馈送足够的数据来维持强扩展。图6对不同类型的数学计算(例如,张量浮点32位精度、浮点16精度、“脑”浮点16位精度、整数8位精度、整数4位精度以及二进制)针对各种不同gpu生成并且还针对不同数据呈现(稀疏和密集)比较数学带宽(每时钟每sm的乘积-加法计算的数量)。图6的左手侧示出了理论数学计算带宽如何随着gpu计算硬件能力的增加而呈指数增加(例如,通过向gpu添加具有张量核心或其他核心的大规模并行sm)。同时,然而,图6的右手侧示出了保持gpu计算硬件被提供有数据的相应的数据带宽要求还没有保持步调。[0034]经验已经显示,存储器带宽和互连带宽(例如,从存储器系统到sm中)以及处理带宽不扩展。用于支持张量核心和其他数学计算的gpu系统内的基本数据流(即,从互连到系统dram存储器,到l2高速缓存,到l1高速缓存中的共享存储器,到sm内的数学计算处理器)的图7流程图表明,为了实现强扩展,有必要提高跨计算和存储器层次结构的所有级别(端到端)的速度以及馈送和效率。[0035]已经尝试并实现了各种技术(诸如存储器管理改进、高速缓存改进等)以增加数据带宽。然而,经由导线增加更多的数据带宽会耗费面积和功率。增加更多的高速缓存成本面积和功率。所需要的是在不需要彻底检修和使存储器访问/管理层次结构复杂化的情况下,利用一个或更多个算法中固有的更多并行性,同时更高效地使用现今和将来可用的处理核心和高速缓存/互连层次结构的方式。同时,一旦提供了解决此类数据带宽问题的新硬件平台,就非常需要跨硬件平台的并发并行处理资源提供高效的工作负载均衡。附图说明[0036]图1a示出了在gpu上运行的示例应用。[0037]图1b示出了弱扩展深度学习场景。[0038]图1c示出了强扩展深度学习场景。[0039]图2a和图2b示出了增加的gpu硬件并行性。[0040]图2c是gpu内的最近流式多处理器的框架构图。[0041]图3示出了示例现有技术gpu硬件分区。[0042]图4示出了具有图形处理集群的示例现有技术gpu硬件。[0043]图5示出了示例现有技术μgpu分区。[0044]图5a是最近gpu架构的框架构图,该最近gpu架构包括被分区为不同μgpu分区的流式多处理器和关联的互连。[0045]图6示出了针对不同gpu生成的示例增加的数学吞吐量和关联的数据带宽。[0046]图7示出了提高跨所有级别的计算和存储器层次结构的速度和馈送以及效率以实现强扩展的示例需要。[0047]图8示出了cta的示例现有技术网格。[0048]图9示出了cta的现有技术网格如何映射到gpu硬件分区上的示例。[0049]图10a示出了cta的示例现有技术网格。[0050]图10b示出了示例新的cga层次结构。[0051]图11a示出了cta的示例现有技术网格。[0052]图11b示出了将cta分组为cga的示例新的cga层次结构。[0053]图12、图12a示出了示例cga网格布置。[0054]图13示出了包括与其他相关电路交互的计算工作分配器电路的框图。[0055]图14示出了包括改进的cga负载均衡器的示例计算工作分配器电路框图。[0056]图15示出了包括用于将cta分配到不同硬件分区级别内的sm的硬件工作分配器电路的分层计算工作分配器电路。[0057]图16a示出了示例流程图,该示例流程图示出了使用负载均衡的推测性或“影子状态”启动。[0058]图16b示出了示例cga启动操作,该示例cga启动操作包括对基于硬件的查询模型的推测性或影子状态启动,如果推测性或影子状态启动成功,则保存保留信息,然后使用保存的预留信息实际启动cga(在真实硬件上,而不是查询模型)。[0059]图16c、图16d示出了包括cga的推测性或“影子状态(shadowstate)”启动以提供基于硬件的并发保证的硬件实现的操作步骤的示例非限制性流程图。[0060]图17示出了源和目标sm之间的示例通信。[0061]图18a-18d示出了sm间通信。[0062]图19是sm间通信的另一个视图。[0063]图20是非程序计数器误差检查的流程图。[0064]图21示出了示例非限制性负载均衡场景。[0065]图21a-21z、图21aa-21ii是一起示出计算工作分配器如何将cga内的cta分配给sm的浏览图表动画(i)。[0066]图22和图23是浏览图表动画的延续,该浏览图表动画示出了示例网格的最后cta的负载均衡分布。[0067]图24、图25a-25g、图26和图27一起是另一个浏览图表动画(ii),该浏览图表动画(ii)示出了计算工作分配器如何将cga内的cta分配给示例实施例中的sm。[0068]图28a-28c一起是示出了计算工作分配器如何在cga内跨gpu硬件的多个分区或层次结构对cta的分配进行负载均衡的浏览图表动画(iii)。具体实施方式[0069]实现或旨在实现扩展的一种方法是通过负载分配和负载均衡。一般而言,负载均衡是个过程,其中将固定数量的(例如,处理)资源分配给任意数量的传入任务。负载均衡的简单示例是我们许多人每次为汽车加油时所经历的。我们开车进入加油站,然后拉起燃油泵,该泵目前旁边没有汽车。当我们将燃料泵入汽车后,我们会离开,另一辆车可以代替我们。如果加油站很忙,一些汽车可能需要排队等候加油。汽车有时会从一条线路换到另一条线路,具体取决于不同驾驶者完成向各自汽车中加油、完成信用卡或其他支付交易等所需的时间。在繁忙的加油站,我们的想法是让每辆加油机保持近100%占用泵送燃料——尽管由于各种原因这并不总是可能的(例如,不同的车辆有不同大小的油箱,因此可能需要更长或更短的时间来加油,一些司机用信用卡在外面快速支付,而其他人在里面支付现金,一些司机想检查他们的油或洗他们的挡风玻璃等)。[0070]类似的负载均衡考虑适用于在现代gpu的高度并行系统中加载sm或其他处理资源——尽管用于在现代gpu中工作的负载均衡技术通常比在加油站管理汽车更复杂。特别是,希望在sm或其他处理资源之间平均分配计算工作,以便所有此类资源保持忙于执行指令,并且所有资源几乎同时释放用于更多工作。然而,由于各种原因,一个执行线程或一组线程可能比另一个执行线程或一组线程花费更长的时间来处理。gpu通过利用工作特性并在容量可用时动态分配工作来最大限度地利用处理资源的能力会对全局效率和处理时间产生巨大影响。参见例如陈(chen)等人,“单个和多个gpu系统上的动态负载均衡(dynamicloadbalancingonsingle‑ꢀandmulti-gpusystems)”,2010年ieee并行和分布式处理国际研讨会(ipdps),2010,第1-12页,doi:10.1109/ipdps.2010.5470413;林(lin)等人,“使用混合整数非线性编程在异构gpu上实现高效工作负载均衡(efficientworkloadbalancingonheterogeneousgpususingmixedintegernon-linearprogramming)”,应用研究与技术杂志(journalofappliedresearchandtechnology)第12卷,第6期,第1176-1186页(2014年12月),https://doi.org/10.1016/s1665-6423(14)71676-1;usp9,715,413;usp9,524,138;usp9,069,609;usp8,427,474;usp8,106,913;usp8,087,029;usp8,077,181;usp7,868,891;us20050041031。[0071]对于初学者来说,为了扩展性能,跨sm的统一利用率通常非常有帮助。因此,示例gpu实施例中的负载均衡理想地集中在单个单元,例如cwd(=计算工作分配器)。由于cwd是中心化的,它可以一次比较所有sm的工作量,以达到理想的统一性。然而,在示例实施例中,与先前的gpu架构相比,工作的性质和并发并行的数量发生了显著变化。具体来说,“协作组阵列”的概念在负载均衡中引入了大量附加的复杂性,但也为有效负载均衡带来了大量附加的机会,以显著提高gpu的全局处理效率和吞吐量。[0072]先前的cta网格层次结构[0073]在一个示例上下文中要进行负载均衡的“工作”粒度可以是“协作线程阵列”或cta(=协作线程阵列)。先前的cuda编程模型使用cta作为gpu软件(sw)的并行性的基本构建块。在一个这样的模型中,cta可以具有多达1024个线程,并且所有线程被保证在同一sm上同时启动和执行。在这种模型中,因为一个sm运行cta中的所有线程,所以线程可以利用sm内和/或连接到sm的共享存储器资源,以在线程之间共享数据、同步、通信等——这确保在并发地执行的线程上的数据局部性和数据重用。在这种模型中,cta的每个线程都可以分配到自身的资源,例如私有存储器,并且同步通常发生在线程级别。[0074]在这种基于sm的编程模型中,cta声明cta在其上运行的sm本地的一些量的共享存储器。该共享存储器存在于cta的有效期期间,并且对于cta中的所有线程可见。cta内的线程可以通过该共享存储器彼此通信以用于数据共享和同步两者。存在着色器指令(例如,“__syncthreads()”)以跨cta中的所有线程进行屏障同步。例如,为了协调cta内线程的执行,可以使用屏障指令来指定线程等待,直到cta中的所有其他线程已经到达的同步点。参见例如usp10977037。[0075]同时,sm的线程束调度器调度cta中的所有线程束在sm上并发地执行,以保证cta中的所有线程同时执行。在现代gpu中,sm具有满足或超过cta中最大线程数的并行计算执行能力——这意味着整个cta(或在某些情况下,多个cta)可以在同一个sm上同时执行。[0076]由于许多应用程序需要超过1024个线程,因此用于计算应用程序的原始cuda编程模型基于“网格”(cta的集合称为“网格”,因为它可以或可以由多维数组表示)。图8和11a示出了示例层次结构,其中网格包括多个cta。每个sm调度多个(例如,32个或其他可编程值)线程的并发地执行,这些线程被分组为“线程束”(使用纺织品(textile)类比)。通常,线程束在sm上以simd方式执行,即,线程束中的所有线程共享相同的指令流并以锁步方式一起执行(这有时称为单指令多线程,或simt)。[0077]由于在单个sm上执行的单个cta是现有模型中软件的并行性的基本单元,因此gpu硬件在现有模型中不保证跨cta在较高级别(例如,网格级别)的任何协作。如图9所示,网格中的所有cta在同一gpu上运行,共享同一内核并且可经由全局存储器进行通信。但是,在现有模型中网格的不同cta可以同时全部在gpu硬件上执行,或者它们可以顺序地运行,例如取决于gpu的大小和由此网格或其他网格引起的负载。现有模型通过潜在地在不同时间在不同sm上独立地执行这些cta,不可能在它们之间高效地共享操作(例如,存储器数据检索、同步等)。并且,即使它们确实并发地执行(诸如在协作组api下),它们可能无法高效地共享存储器或数据带宽以提供跨该组的紧密协作耦合。例如,如果网格被拆分为多个cta,则从硬件观点来看,机器非并发地运行那些cta将是合法的——如果算法需要两个或所有cta并发地运行并且来回传递信息,则导致死锁。[0078]cta编程模型如上描述已经很好地为开发者服务,其提供了多年和多代gpu在sm级别的数据局部性和数据重用。然而,如以上所讨论的,随着时间的推移,gpu已经变得更大,例如每gpu包括超过100个sm,并且到l2高速缓存和存储器系统的互连不再是平坦的交叉开关,而是分层的并且反映分层硬件域级别(例如,gpu、μgpu、gpc等)。在此类更高级的gpu中,将sm定义为数据局部性的基本单元的机制通常粒度太小。为了最大化性能和可扩展性,所需要的是新的编程/执行模型,其允许软件以比单个sm(其现在小于gpu的1%)大得多的单位控制局部性和并发性,同时仍维持跨所有线程(如cta)共享数据和同步的能力。应用应该能够控制数据局部性和数据重用以最小化延迟。这对于想要通过创建跨gpu硬件的较大部分的协作线程集来进行强扩展(见上文)的深度学习和hpc应用尤其如此。[0079]协作组阵列[0080]本文的示例非限制性实施例提供新级别的层次结构——“协作组阵列”ꢀ(cga)——以及关联的新编程/执行模型和支持硬件实现方式,其提供了分配所有并发工作的高效负载均衡。例如跨可用处理和其他硬件资源的cga。参见上文已标明的2022年3月10日提交的题为“协作组阵列(cooperativegrouparrays)”的美国申请no.17/691,621。[0081]在一个实施例中,cga是cta的集合,其中硬件保证cga的所有cta被启动至cga指定或与其相关联的同一硬件组织级别。该硬件被配置为确保在目标硬件级中有足够的处理资源来启动cga的所有cta,然后才启动任何其他,并且跨这些处理资源对cta进行负载均衡,以最大限度地提高全局执行速度和吞吐量。[0082]如图11b所示,网格是cga阵列,并且每个cga是cta阵列。在这种情况下,“cga”和“集群(cluster)”是同义词,“cta”是一种“线程块”。这样的cga提供相对于应用所需的存储器和相对于彼此的共同调度,例如,对cta在gpu中被放置/执行的位置的控制。这使得应用能够在紧密协作的cta集群或阵列中的所有线程之间看到更多的数据局部性、减少的等待时间和更好的同步。[0083]例如,cga让应用利用现代gpu中的互连和高速缓存子系统的层次结构性质,并且使其在未来随着芯片增长而更容易扩展。通过利用空间局部性,cga允许更高效的通信和更低的延时数据移动。gpu硬件改进通过允许cga控制并发cta线程在机器上的何处相对于彼此运行来保证新cga层次结构级别定义的多个cta的线程将针对期望的空间定位并发运行。[0084]如以上讨论的,在一个实施例中,cga由硬件保证将同时地/并发地启动和执行的cta组成。cga中的cta可以(并且在一般情况下将)在gpu内的不同sm上执行。即使cta在不同sm上执行,gpu硬件/系统仍然提供跨sm保证:cga中的cta将被调度为并发地执行。如下文详细解释的,cga的所有cta的这种高性能并行启动能力可以得到负载均衡算法的支持,以进一步提高性能和吞吐量。gpu硬件/系统还提供高效机制,通过该机制并发地执行的cta可以彼此通信。这允许应用在cga中的cta之间明确地共享数据并且还实现cga中的cta的各个线程之间的同步。[0085]在示例实施例中,cga内的各个线程可以从公共共享存储器读取/写入——这使得cga中的任何线程能够与cga中的任何其他线程共享数据。cga中的cta之间的共享数据节省了互连和存储器带宽,这通常是应用的性能限制器。cga因此增加gpu性能。如上所述,在先前编程模型中,通常不可能在两个cta之间直接共享数据,因为不能保证两个cta将在相同的相关硬件域中同时运行。在没有cga的情况下,如果需要两个cta共享相同的数据,则它们通常将都必须使用两倍的带宽来从存储器中提取该数据。就像两个父母各自去商店买牛奶一样。相反,已知有效利用数据局部性对gpu性能是重要的。参见例如拉尔(lal)等人,“gpu高速缓存中的局部性的定量研究(aquantitativestudyoflocalityingpucaches)”,奥尔奥格鲁(orailoglu)等人(编),嵌入式计算机系统:架构、建模和模拟(embeddedcomputersystems:architectures,modeling,andsimulation),(samos2020),计算机科学讲座笔记(lecturenotesincomputerscience),第12471卷。springer,cham.https://doi.org/10.1007/978-3-030-60939-9_16。[0086]现在,使用并发地执行和由硬件支持的附加共享存储器,有可能直接在一个cta的线程与另一个cta的线程之间共享数据——这实现了跨桥接硬件(例如,跨sm)分区的cta的依赖性。[0087]因为cga保证其所有cta与已知的空间关系并发地执行,因此其他硬件优化是可能的,诸如:[0088]·跨gpu或gpu的分区的负载均衡[0089]·通过向并发地执行cga的cta的所有sm广播标识符来高效地传达某些信息,例如网格标识符[0090]·与另一个(或多个其他)sm共享一个sm内的存储器[0091]·将从存储器返回的数据多播至多个sm(cta)以节省互连带宽;[0092]·直接sm到sm通信用于cga中的生产者线程与消费者线程之间的较低延时数据共享和改进的同步[0093]·用于在cga中的所有(或任何)线程上同步执行的硬件屏障[0094]·以及更多(参见以上列出的共同未决的共同转让的专利申请)。[0095]这些特征通过更高效地使用处理资源、放大存储器和互连带宽、减少存储器延时、以及减少线程到线程通信和同步的开销来提供更高的性能。因此,所有这些特征最终导致应用的强扩展。[0096]层次结构的新级别-cga[0097]在示例实施例中,cga由多个cta构成——即,被构造成协作地执行的多个线程集合或束。每个这样的线程集合或束提供早已由先前cta提供的所有优点和结构——诸如例如在相同的sm上运行。然而,cga提供的附加覆盖定义cta将在何处以及何时运行,并且特别地,保证cga的所有cta将在公共硬件域内并发地运行,该公共硬件域提供对cta之间的数据、消息传递和同步的动态共享,以及跨可能跨越任意数量的sm的处理资源的集合对cta进行负载均衡的可能性。[0098]示例实施例支持针对不同gpu硬件域、分区或其他组织级别的不同类型/级别的cga。具体地,cga可以定义或指定该cga中的所有cta都应该运行在其上的硬件域。以此类推,正如当地高中体育团队可能在当地划分、区域或州际比赛一样,cga可能需要其所引用的cta全部在gpu的同一部分(gpc和/或μgpu)上、在同一gpu上、在gpu的同一集群上等上运行。同时,可以使用集中式工作分配器形式的负载均衡硬件来均衡该硬件集合中所有sm的cga内的cta的加载,例如gpc和/或μgpu、gpu和/或gpu集群。[0099]示例分层硬件集合/分区[0100]在示例实施例中,cga定义/指定的层次结构被绑定到或以其他方式反映gpu硬件分区(其反映存储器访问和/或通信能力),以便提供期望的资源和数据重用和数据局部性。例如,正如gpu可以包括如图3和图4所示的多个gpc,gpu_cga可以由多个gpc_cga构成。图10b示出了提供反映与现有技术图10a情况相关的不同硬件域的附加嵌套层次结构级别的示例cga层次结构,例如:[0101]·gpu_cgas[0102]·μgpu-cgas[0103]·gpc_cgas。[0104]在示例非限制性实施例中,硬件保证某个cga内的所有cta并发地启动到sm上,所述sm是由与某个cga相关联的硬件域指定符所指定的硬件域的一部分,例如:[0105]·用于gpu_cga的所有cta被启动到作为同一gpu的一部分的sm上;[0106]·用于μgpu_cga的所有cta被启动到作为同一μgpu的一部分的sm上;[0107]·用于gpc_cga的所有cta被启动到作为同一gpc的一部分的sm上。[0108]此外,相同的启动硬件可以跨gpu、μgpu和/或gpc的处理资源对cga的cta进行负载均衡,以实现更高的处理效率和吞吐量。[0109]更详细地,cga的一些实施例还支持μgpu分区(诸如图5、图5a中所示)并且提供若干新的能力和硬件保证,诸如:[0110]·cga为网格(内核)级别和cta级别之间的线程提供新的层次结构级别[0111]·gpc_cga将所有cta放置在同一gpc内[0112]·μgpu_cga将所有cta放置在同一μgpu的sm内,在一些实现方式中,该同一μgpu与大型gpu内的存储器互连层次结构相匹配[0113]·gpu_cga将所有cta放置在同一gpu内[0114]·abc_cga将所有cta放置在abc硬件域内,其中“abc”是在gpu架构内或跨gpu架构的任何gpu硬件域、组织或层次结构。[0115]这些示例级别(网格、gpu_cga、μgpu_cga、gpc_cga和cta——参见图10b)可以被嵌套以进一步控制sm资源在每个级别处的放置。例如,gpu_cga可以由μgpu_cga构成,μgpu_cga由gpc_cga构成,gpc_cga由cta构成。此嵌套可支持层次结构的每一级别及所有级别的常规动态并行性。参见例如https://developer.nvidia.com/blog/cuda-dynamic-parallelism-api-principles/[0116]示例协作组阵列网格[0117]随着cga的添加,现在有许多更可能的网格类型示例在图12、图12a中示出,其中每个网格类型指定或以其他方式与特定硬件域相关联:[0118]图12(1):cta网格——这是传统网格。在实施例中,此网格表示cta的三维网格(xxyxz)。网格的示例尺寸可以是例如18x12x1cta。[0119]图12(2):cta的gpc_cga网格——每个gpc_cga的cta的三维网格一起启动并且总是放置在同一gpc上。因此,这种类型的网格指定的硬件域是“gpc”。网格中的共同图案化的相邻正方形构成将被调度以同时运行的cga。因此,标记为“gpccga”的六个cta都将在同一gpc上一起启动,并且它们都不会启动,直到它们都可以一起启动。示例网格尺寸是6x6x1gpccga,其中每个gpccga具有3x2x1cta的尺寸。在一个示例中,gpc_cga支持sm到sm通信、全局存储器中的cga线性存储器和基于硬件的cga屏障。[0120]图12(3):cta的gpu_cga的网格——这是其中每个gpu_cga的cta被一起启动并且总是被放置在同一gpu上的网格。因此,由这种类型的网格指定的硬件域是“gpu”。在一些环境中,多个gpu可以被配置为gpu集群;在这种情况下,图12(3)网格迫使gpu_cga的所有cta在公共gpu上运行。这个网格意味着作为cuda的协作组api特征的替换,但是现在由硬件来保证共同调度。示例网格尺寸是2x2x1的gpucga,每个gpucga子网格包括9x6x1的cta。[0121]图12(4):cta的gpc_cga的gpu_cga的网格。这是具有cga层次结构的两个级别的网格。gpu_cga具有在图12(3)中描述的能力,并且gpc_cga具有在图12(2)中描述的能力。因此,这种类型的网格指定两个嵌套的硬件级别:gpu和gpc。该示例例如允许开发者调度gpucga在单个gpu上运行,并且该gpucga内的每个gpccga在该gpu内的同一gpc上运行。示例网格尺寸是2x2x1的gpucga,每个gpucga子网格包括3x3x1的gpccga,每个gpccga子子网格包括3x2x1的cta。[0122]基于硬件的cga启动保证&负载均衡[0123]在示例实施例中,上述每种cga类型中的所有cta是共同调度的。这意味着gpu硬件将不允许cga中的任何cta启动,除非/直到相关gpu硬件域上有空间供cga中的所有cta启动。这种硬件保证允许软件依赖于cga中的所有线程将同时执行的事实,因此诸如屏障同步和跨所有线程的数据共享之类的事情是可能的。cga中的任何单个cta都不能无限期地等待启动——在一个实施例中,要么启动整个cga,要么不启动。此外,通过使用我们称为“cwd”的集中式分层cta启动设施或电路,可以在gpu或其他相关硬件域的sm之间对cta进行负载均衡。[0124]在一个示例布置中,硬件维护cga中正在运行的cta(即尚未退出的cta)的数量的计数,并且软件可以跨cga中所有正在运行的cta中的所有线程执行屏障同步。在示例实施例中,每个cga具有分配给它的(至少一个)硬件屏障,并且cga中的所有cta可以引用该cga硬件屏障。参见上文标明的2022年3月10日提交的题为“具有异步事务支持的硬件加速同步(hardwareacceleratedsynchronizationwithasynchronoustransactionsupport)”的美国申请no.17/691,296。例如,此硬件屏障可用于引导所有cta并确认它们已全部启动。[0125]改进的集中式工作分配器[0126]在图13、图14、图15所示的一个或更多个实施例中,使用主计算工作分配器(“cwd”)硬件电路420在gpu上启动cga,同时提供cga的所有cta可以同时启动的基于硬件的保证。关于用于调度工作的现有技术示例gpucwd和mpc的更多信息,参见示例20200043123,特别是图7和该在先专利公开的相关联的描述,并且还参见例如usp10,817,338和usp9,069,609。这种传统的cwd420在过去成功使用时存在三个扩展问题:[0127]1)负载均衡:每个cta都必须启动到利用率最低的sm。它通常一次完成一个cta。cwd420比较所有sm之间的利用率度量以选择一个用于cta的sm,然后cwd重新开始下一个cta的过程。要向许多sm启动cta,此过程可能会变得非常低效。此外,先前的cwd没有很好的方法来处理对不同范围的分层硬件域的启动。[0128]2)光栅化吞吐量:一旦解决了负载均衡问题#1,生成许多多维id的数学运算(见下文讨论)将成为瓶颈。[0129]3)cta传输带宽:即使解决了上述问题#1和#2,也很难将许多多维id传输到物理上远离cwd420的sm。例如,在像cuda这样的计算api中,ctaid是3d并表示为32b-16b-16b元组。将64b数据传输到许多(可能数百个)sm将需要大量带宽。[0130]值得一提的是,就网格启动开销而言,更高的cta启动吞吐量也是可取的。例如,如果sm有足够的资源来容纳8个cta,则现有技术的cwd将需要超过1000个周期来填充所有128个sm。这需要很长时间,会引入延迟并降低效率。[0131]另一个需要解决的问题是上述新型工作单元的负载均衡,称为cga(=协作组阵列)。如上所述,cga可以被视为cta的集合,这些cta被共同安排并限制在“gpc”中(作为一个示例)。如上所述,gpc是gpu内的一组sm。例如,一个示例gpu架构由8个gpc组成,每个gpc由18个sm组成。如上所述,cga的概念可以扩展到多个层次结构。例如,gpc可以由多个“cpc”组成,每个“cpc”都包括一定数量的sm。本文的示例性非限制性技术向多级cga嵌套和相关的分层硬件域和范围提供负载均衡算法。[0132]具有负载均衡和推测性/影子状态启动的增强型cwd结构和功能[0133]在本文的实施例中,图13、图14和图15示出的改进的cwd420是集中式电路,其被扩展/增强以提供负载均衡的推测性或基于影子状态cga的硬件启动能力,以确认资源可用于启动跨相关硬件域的cga中的所有cta。如果cga的所有cta不能同时启动,则cwd420不启动cga的任何cta,而是等待,直到相关gpu硬件域的足够资源变得可用,以使得cga的所有cta可被启动,从而它们并发运行。在示例性实施例中,cwd420使用提供负载均衡的多级工作分布架构支持多级cga的嵌套(例如,gpu-cga内的多个gpc-cga)。因为cwd420是集中式的,它可以查看所有sm的状态并根据这些状态做出良好的负载均衡决策。[0134]更详细地,图13&图14中示出的cwd420在使用推测性或影子状态启动技术确定cga的所有cta可适合在指定硬件域中可用的硬件资源上之后启动cga中的cta。以这种方式,一个示例模式中的cwd420确保在启动cga的任何cta之前,跨所有gpc或其他相关硬件域有足够的资源用于cga的所有cta。在一个实施例中,启动cga的cta的算法可从传统(非cga)网格启动借用一些技术,同时首先确认cga的所有cta可以确保它们将同时运行的方式启动。另参见图16c,其示出了cpu执行操作550-560以生成网格启动命令并将其发送到gpu以供cwd420处理的示例流程图。[0135]图14示出了cwd420的基本架构,cwd420包括负载均衡器422、资源跟踪器(trt)425(0)、425(1)、…425(n-1)、tpc启用表430、本地存储器(lmem)块索引表432、信用计数器434、任务表436和优先级排序的任务表438。每个trt425(0)、425(1)、…425(n-1)与对应的tpc340(0)、340(1)、…340(n-1)通信。关于这些各种结构的传统操作的更多细节,参见例如usp10,817,338;us20200043123;us20150178879;usp10,217,183;以及usp9,921,873。在示例实施例中,这些和其他结构的功能沿着以下线在示例实施例中被增强以适应cga:[0136][0137][0138]负载均衡示例[0139]本文的示例技术通过一次对所有sm进行负载均衡来解决负载均衡问题(例如,与一次负载均衡一个sm的现有方法相反)。cwd420首先查询所有sm的空闲槽。sm的空闲槽数定义为“在sm的剩余资源(例如共享存储器、寄存器和线程束id)中可以容纳多少cta”。参见usp9,921,873。每个sm都可以报告它在网格光栅化开始时拥有的空闲槽的数量。可以在图14所示的任务表436中维护这样的空闲槽的计数(例如,将多达预定数量的任务分配给相关联的任务id的多位值)。空闲槽可以抽象出cga或网格的cta需要在gpu处理硬件上运行的资源需求(例如,每个cta需要运行的资源可以由网格定义为对网格中的所有cta是统一的,例如如执行线程数、寄存器数、存储器分配等)。空闲槽越多,sm被利用/占用的越少,这表明未来向sm发起的cta对数学逻辑和存储器带宽的竞争将更少,这通常会导致更快的执行。因此,空闲槽是衡量即将推出的cta的预期“速度”的指标。[0140]在一个实施例中,gpc内部有(至少)两种负载均衡分布模式:[0141]a)负载均衡模式:它是在下面讨论的图21中使用的模式。它相当于将具有与cga相同数量的cta的网格启动到具有与gpc相同数量的sm的gpu时的分布。[0142]b)多播模式:这是一种负载均衡模式,但有一个限制:只有一个cta可以从这个cga发送到同一个sm(可以向一个sm发送多个cta,但不能从同一个cga)。这可以用来确保cga可以享受多播存储器加载机制,因为在某些提供程序多播的实施例中,在同一sm上运行的同一cga中只有一个cta能够访问来自存储器系统的多播数据。在其他实施例中,可能不存在这样的约束,但是将cga的仅一个cta分配给每个sm而不是双倍、三倍等可能仍然存在优势。[0143]下面将更详细地讨论这两种负载均衡模式。以下算法描述适用于“负载均衡模式”。[0144]示例非限制性负载均衡算法[0145]大量cta的负载均衡看起来很像将水(cta)倒入干涸的湖中,其深度与空闲槽成正比。参见图21、21a-21z、21aa-21ii、22、23,它们是浏览图表动画,显示了cwd420将cta分配给空闲sm槽的示例。在所示示例中,相关的有32个sm硬件分区,但任意数量的sm可能存在于给定的gpu或分区中。[0146]在这个特定示例中,一些sm,例如sm3、sm4、sm6、sm8、sm18和sm31,已经几乎或完全被先前分配的工作占用。这些sm不能接受附加的工作。他们没有可用的空闲槽(slot)来承担新的工作(在某些实现中可能希望不要完全加载任何sm,因为sm尝试同时执行的工作越多,执行每项工作的速度就越慢)。[0147]一些sm,如sm10、sm11、sm12、sm17、sm18等,已经在执行一些先前分配的工作,但有开放的空闲槽,这意味着更多的处理资源可以潜在地用于执行新工作。他们有一些空闲位置,但并非空置。[0148]一些sm,如sm2、sm5、sm7等,没有执行任何先前分配的工作,因此完全可以用于新工作。他们有许多(所有)空闲槽开放。[0149]相关硬件分区的示例使用状态如图21所示,其中一些sm有很多空闲槽,而一些sm没有空闲槽,例如由于动态gpu操作,可能会发生这种情况。当gpu在重置或其他主要初始化事件后首次启动时,sm不做任何工作,并且所有sm都有最大数量的空闲槽。当cwd420将第一个cga的工作分配给这个完全未被占用的sm集合时,它可以在所有sm之间自由分配工作,而无需任何特殊的负载均衡算法来实现高效的负载均衡。但是,随着gpu继续运行,cga中的某些cta可能会先于其他cta完成,从而释放出可供新启动的cga重用的槽。就像上面描述的加油站类比一样,加油站不需要完全空置来接受需要加油的新车——而是可以在加油槽可用时动态地为汽车分配加油槽。然而,cga比cta提出了更困难的调度挑战,因为cga需要并行分配多个资源(即cga中的每个cta一个sm空闲槽)。一个类比可以是跨多个工人团队(cga)调度项目与跨一组个人工人(cta)调度任务。因此,cwd420在示例实施例中执行的负载均衡比加油站的简单“先到先得”负载均衡甚至cta的负载均衡更复杂且不同。[0150]图21示出了示例cga(由2d网格表示),其中包括137个cta,将分布在包括32个sm或其他核心处理器的gpu上执行。由于在一个实施例中构造cwd420的分层方式(详情如下),32个sm的这个抽象集合可以分布在gpu内的一个或更多个gpu硬件域中,例如在一个gpc或更多个gpc内、在一个cpc或更多个cpc等。在一个实施例中,它们甚至可以分布在多个gpu上。在此示例中,cwd420的工作是(a)保证(在硬件中)所有137个cta将同时启动和运行,以及(b)以最大化速度的方式跨sm集合对cta进行负载均衡和吞吐量。cdw420通过使用推测性或影子状态启动机制(见下文)预先安排所有cta的所有启动,然后(假设并发地执行保证适用于当前加载的sm硬件集合),“同时”启动所有cta。这里,“同时”不限于字面上在单个处理周期中向所有sm启动所有cta,因为实际上,cwd420可能需要一些时间来向许多sm中的每一个传送适当的指针信息和指令可能分布在半导体晶片的表面上(参见图2b)。[0151]负载均衡浏览图表动画i[0152]图21及以下是浏览图表动画(i)。要在您的计算机或其他设备上使用本专利的电子副本查看此浏览图表动画,请将图21的大小调整为刚好填满屏幕并以横向而不是纵向查看(例如,使用顺时针“旋转”),然后反复按下计算机上的“下页(pagedown)”按钮,依次进入图21a-21z、图21aa-21ii。然后,您将看到cdw420如何填充sm0-sm31的空闲槽的动画。当然,您也可以翻阅这些数字的纸质副本。此动画显示cwd420似乎一次处理每个cta以用于推测性(speculative)/影子状态启动目的。然而,即使在那里,当将cta分配给sm以用于推测性/影子状态启动时,cwd420也以集中方式运行以考虑sm集合中所有sm的当前加载。[0153]从这些图中可以看出,cta“填充”了gpu的sm(意味着每个cta被调度在一个sm上执行),cta被调度在空闲槽数最多的sm上执行,然后逐渐填充“湖”向上(图16a框202、204)。填充“湖”的可用“水”量(填充处理资源的工作)对应于网格中cta的数量。请注意,随着浏览图表动画的进行,cwd420首先将工作分配给具有最多空闲槽位的sm。[0154]在一个实施例中,不允许cwd420启动比sm可以接受的更多的cta(图16a框2006),因此如果“湖”在网格用完cta之前变满,则暂停过程(图16框2008))并等待已启动的cta完成以释放更多空闲槽。如果“湖”容量(空闲槽的总数)多于cta,则“水”位上升到一定水平并停止。[0155]有几个选项可以在具体逻辑中实现这一点。一种是二分查找。如果最大空闲槽位(最大湖深)为n,cwd420会试探性地尝试n/2的最终水位,并查看水量(已启动cta的数量)是否会大于网格中剩余的cta。如果是,由于cwd420没有足够的cta来满足这个水位,cwd接下来尝试n/4。如果否,cwd420尝试3n/4。它重复这个过程,直到找到均衡。[0156]上述方法对于较大的n值是有效的,但对于较小的值,cwd420可以简单地将sm从最大空闲时隙扫描到较低值(在图21中向上)。在每次迭代中,cwd420推测性地(影子状态)向具有当前空闲槽的sm启动cta。如果使用这种方法,则要特别注意最终的空闲时隙级别,如图22所示。这是流体类比失效的地方,因为cta工作单元是离散的,因此在一个实施例中的cta不会被传播跨多个sm。[0157]在一个实施例中,cwd420通过对图22所示的该最终空闲时隙级别应用附加标准来同时选择sm的子集以分配工作。在一个实施例中,该标准是sm之间的预定优先级或其他优先级。在图22示例中,sm0具有最高优先级,并且sm优先级随着sm#向右增加而降低。cwd420同时计算每个sm的“位1计数(popcount)”(populationcount),从左到右的最终空闲槽级别,然后选择位1计数(popcount)小于剩余cta数量的sm。在一个实施例中,“位1计数”通过自下而上的减少和自上而下的累积在o(logn)时间内获得(图16a框2004)。图23示出了一个示例结果,其在一个实施例中同时选择多个sm以将cta启动到而不是一次选择一个这样的sm。sm优先级可以按任何顺序分配,“填湖”不需要从左到右执行(它可以从右到左或以任何其他预定或非预定顺序执行)。[0158]浏览图表动画ii[0159]图24、25a-25g、26和27一起是另一个浏览图表动画(ii),示出了计算工作分配器可以将cga内的cta分配给示例实施例中的sm的另一种方式。在该实施例中,cwd420不是一次分发一个cta,而是一次分发一行或一层cta。如上所述,对于较小的n值,cwd420可以简单地将sm从最大空闲时隙扫描到较低值(图24中向上)。在每次迭代中,cwd420推测性地向具有当前空闲槽的sm发起cta。基本上,这个实施例不是一一显示cta的下降,而是一次将“湖”填满一整行。推测性启动成功后,可以将cta并行加载到sm(tpc)中(见下文)。上面描述的二分搜索算法也有效。对于cga,也会同时启动多个cga。[0160]浏览图表动画i和ii的替代结局——推测性启动失败[0161]另一方面,如果推测性或影子状态启动应确定cga太大而无法在可用处理资源上启动(图16a,“是”退出到框2006),cwd420将确定没有足够的sm空闲槽可同时启动所有cta,因此此时会为此cga发出“失败”指示(图16a,框2008)。没有实际启动该cga的cta,系统必须稍后尝试启动此cga(例如,当更多sm槽可用时)但可能会尝试启动较小的cga,再次使用上面讨论的负载均衡算法(图16a框2012、2000)。当然,如果网格由正常(即非cga)cta组成,如果cwd420的cta比总空闲槽位多,那么简单地所有空闲槽位应立即由cta填充,并且随着更多cta完成,cwd将启动剩余的cta。[0162]负载均衡的gpc组织[0163]如上所述,许多gpu具有分区或其他细分,例如gpc。在一个实施例中,cwd420在负载均衡时将这些分区或其他细分考虑在内。为了启动cga,cwd420选择gpc,然后为cga中的cta选择gpc中的sm。选择的目标是最大化性能:哪些gpc和sm最有可能让cga运行最快并最快完成?这里的一个假设是cga中的cta经常同步并进行锁步进度,因此最慢的cta决定了cga的执行速度。[0164]附加浏览图表动画iii[0165]图28a、28b、28c是浏览图表动画(iii),它示出了硬件域层次结构的cga调度算法——在这种情况下,多个gpc每个都包括sm,其中cga-gpc必须在单个gpc上运行并且不能跨越gpc之间的边界。在示例实施例中,该算法还以分层方式操作。在顶层(图15框420a),选择“最佳”gpc,并行启动cga。cwd的下一个管线阶段(图15框420b)为cga中的cta选择sm。因此,cta是并行启动的,并且问题#1再次得到妥善解决。[0166]现在,如何选择最好的gpc?在一个实施例中,它是通过从每个gpc查询“速度”来完成的,如图28a所示。如上所述,我们希望将cga发送到“最快”的gpc。但在一个实施例中,“gpc”并不是真正的gpc。从cwd到gpc的往返延迟很大,应避免查询该距离。相反,在一个实施例中,cwd420在内部实例化一组模仿gpc,并将查询发送给它们。这样的模仿模拟了sm向cwd420报告的空闲槽(参见上面的讨论),因此cwd考虑了每个gpc中每个sm的当前加载。在图28a所示的示例中,gpc0包括8个sm,其中5个(sm3-sm7)满载,其中两个(sm1,sm2)部分加载,其中一个(sm0)完全未占用。等等。[0167]gpc的这种模仿或模型允许cwd420提供为上述cga网格定制的推测性或影子状态启动能力。每个查询都以样本cga的形式出现。收到样本cga(在本图中为cga1)后,模仿gpc会尽力将cga的cta发送给sm。模仿gpc有两种跨sm负载均衡cta的模式——一种是简单的负载均衡,另一种是“多播”模式。在模仿gpc尝试cta启动后,如果它没有找到足够的空闲槽,它会向顶层回复“失败”。如果它确实找到了足够的空闲槽,使用负载均衡模式之一,它分配cta,然后计算收到cta的sm之间的最小剩余空闲槽。如上所述,剩余的空闲时段是预期cta的“速度”的指标。而cga中最慢的cta成为瓶颈。因此,剩余的最小空闲槽位就是cga的“速度”。[0168]顶层重复这个查询启动过程,直到网格中的cga或空闲槽用完为止。[0169]该算法可以扩展到多级cga层次结构。图28a、28b、28c显示了当我们具有三个层次结构时的情况:一个网格由gpccga组成,这些gpccga由预定义数量的cpccga组成,每个cpccga由cta组成。在顶层,该算法向每个模仿gpc查询gpccga的速度(图15)。然后,每个模仿gpc重复向每个cpc(在gpc中)查询cpccga的速度,并“推测性地”启动cpccga,直到启动gpccga的所有cpccga(图15)。gpccga的速度就是上次查询的速度,因为gpccga的速度会是gpccga中最慢的cta的速度。一旦顶层决定接受gpccga速度并向模仿gpc发送启动消息,则为推测性gpccga保留的空闲槽被提交,并且gpccga在实际硬件上真正启动。否则,预订将被取消。更多层次的层次可以通过附加的cwd420硬件层和/或通过递归地重用每个层次的可用硬件(例如,以节省芯片空间和相关的功率)来适应。[0170]在此图中,由于gpc0已被占用,因此无法在gpc0上启动任何gpc-cga。同时,gpc1确实有足够的资源来启动gpc-cga,但这样的启动会耗尽gpc的所有可用处理资源。但同时,gpc2和gpc3都可以启动一个有空闲槽的gpc-cga,这意味着通过选择gpc2和/或gpc3的负载均衡算法能够最大限度地提高启动的gpc-cga的运行速度。在所示示例中,即使gpc2比gpc3负载更轻,cwd420不一定更喜欢gpc2而不是gpc3,但是其他示例实施例可以根据例如有多少(以及哪些特性)gpc-cga等待运行来考虑这种差异。图28c之后的场景是cwd420将启动gca2到gpc2,以便两个cga将在同一个gpc上运行。[0171]也就是说,在一个实施例中,具有相同最大速度的所有gpc同时接收cga。在图25c中,gpc2和gpc3同时接收cga。最重要的是,每次cga发布都包括同时进行的多个cta发布。因此可以看出,在示例实施例中,一次(同时)调度多个cta,而不是一次一个。[0172]基于多维id和网格光栅化的扩展[0173]如上所述,出于各种原因,示例实施例中的每个cta都被分配了多维id,cta和gpu可以使用该多维id来识别cta并将cta与数据和其他资源相关联。例如,如上所述,对于数据并行编程模型,每个cta都与支持cta执行的数据相关联。例如,cta可以查询多维id以查找分配给它的数据。例如,如果将图像过滤器网格应用于3d图像,则每个cta可能会查询xyz元组来确定它应该处理图像的哪个部分。如果硬件仅提供整数值作为id,则每个cta必须执行昂贵的除法以将其分解为xyz。因此,当cta被发送到sm时,硬件生成多维(例如,xyz)id是有帮助的。这种多维id生成可以称为“网格光栅化”,因为它类似于计算机图形算法中从屏幕上的三角形中扫描出像素的行为。[0174]当cta是cga的一部分时,这种网格光栅化变得更加复杂,因为分配给cta的多维id现在也应该编码或识别或以其他方式与cta所属的cga相关联。[0175]一旦使用如上所述的集中式cwd420解决了负载均衡问题,就会出现光栅化吞吐量问题;在启动时生成许多多维id的数学运算可能会成为瓶颈。一个相关的问题是cta传输带宽;即使解决了上述问题,也很难将许多id传输到物理上远离集中式cwd420的sm。例如,在像cuda这样的计算api中,ctaid是3d并表示为32b-16b-16b元组。向许多sm传输64b数据需要大量带宽。[0176]将光栅化分布到sm而不需要cwd420或其他集中式硬件来执行光栅化来解决这两个问题。特别地,当cwd420通知sm它们被分配了新的cta工作时,sm内的mpc404可以通过来自其他sm的广播信息被通知所有sm的所有cta的xyzid分配。在一个实施例中,这些xyz坐标由sm生成是确定性的;例如,可以先增加x坐标值,一旦增加了y坐标值,再从初始值开始,同样可以在增加z坐标值后从初始值重新开始y坐标值。每个sm都被编程为根据它接收到的广播启动分组独立地执行此过程。这种分布式id坐标分配过程使cwd420不必向任何sm发送任何xyzid分配。因此,xyz分配分布在所有sm上,并且可以由同时执行的硬件同时执行。示例实施例进一步提供了下文描述的用于软件查询硬件以获知xyzid分配的机制。该解决方案提供了两全其美:用于实施负载均衡算法的集中式决策电路,以及用于在cwd确实安排cta执行时执行详细记录保存(ctaid生成)的分散(分布式)电路。[0177]在一个实施例中,id生成的负担从cwd420转移到sm。cwd420执行负载均衡并将消息发送到负载均衡算法选择的sm以触发cta启动。在一个实施例中,cwd420向所有sm广播所有cta启动消息,使得每个sm都可以观察到整个cta启动序列。因此,每个sm都可以告诉网格内的当前光栅化位置。该方案解决了传输带宽问题,因为cwd到sm的流量不再需要携带多维id。[0178]这个想法的幼稚实现仍然会留下光栅化吞吐量问题,因为即使所有sm并行执行光栅化,每个sm将消耗与cwd执行相同计算的情况相同的时间。为了解决这个问题,每个sm只偶尔计算一次多维id。大多数情况下,它只是计算自上次计算多维id以来的cta数量。可称为计数delta(δ)。而当多维id是绝对需要的时候,即sm发起cta或者delta(δ)溢出时,sm将delta(δ)分解为多维版本,然后将分解后的delta(δ)添加到最后计算的id。该技术解决了光栅化吞吐量问题。这是一个3d示例。[0179]a)将delta分解为xyz的步骤。在代码中,griddim.x和y分别是网格的x和y维度。“%”是类似于c++的模运算符。请注意,由于我们可以将delta的精度保持在较低水平,因此这些除法不需要昂贵的逻辑。[0180]zdelta=delta/(griddim.x*griddim.y)[0181]delta_tmp=delta%(griddim.x*griddim.y)[0182]ydelta=delta_tmp/griddim.x[0183]delta_tmp=delta_tmp%griddim.x[0184]xdelta=delta_tmp[0185]b)更新当前x、y和z的步骤[0186]xcurrent=xcurrent+xdelta[0187]ifxcurrent》=griddim.xthenxcurrent-=griddim.xandc=1elsec=0[0188]ycurrent=ycurrent+ydelta+c[0189]ifycurrent》=griddim.ythenycurrent-=griddim.yandc=1elsec=0[0190]zcurrent=zcurrent+zdelta+c[0191]该算法能够实现典型案例的峰值cta启动吞吐量,与以前以集中方式将多维id分配给cta的方法相比,该算法提高了36倍。[0192]cwd420的详细实施[0193]在一个实施例中,cwd420从前端212接收用于在与gpu协作的cpu上执行的各种进程的任务。在示例实施例中,每个任务可以对应于一个cga。在cpu上执行的每个进程都可以发出此类任务。[0194]在示例实施例中,调度器410从前端212接收任务并将它们发送到cwd420(图16,框502、504)。cwd420从多个cga查询和启动cta。在一个实施例中,它一次在一个cga上工作,但在其他实施例中,协调并行是可能的。在一个实施例中,对于每个cga,cwd420针对由查询模型定义的影子状态推测性地启动cga中的所有cta,如上所述(使用gpc的基于硬件的模型而不是实际的gpc,如图16b),递增“启动”寄存器以存储推测性/影子状态启动(参见图16b)。如果在针对查询模型定义的影子状态推测性地启动cga的所有cta之前sm或硬件域中的其他处理器中的所有空闲槽用尽,则cwd420终止该启动,并可稍后再次尝试。相反,如果对于cga中的所有cta存在足够的空闲槽,则cwd420从在推测性/影子状态启动过程中累积的“启动”寄存器生成sm_mask(该sm_mask数据结构存储用于在cga启动的相关硬件域中的每个sm上运行的每个cta的预留信息(图16a,框2010;参见图16b)),并且一直移动到下一cga。硬件分配cga序列号,并将其附加到每个sm_mask,该cga序列号指定哪个sm在启动时获得哪个cta。其还将cga位的end_附加到最后一个,以防止来自不同cga的sm_mask的交错。在一个实施例中,发送到sm的启动分组可以包括针对每个sm_mask的多个cta启动指令——通过不再需要启动的cta和启动分组之间的一一对应关系来提高性能。应当注意,在一个实施例中,cwd420维护整个gpu的两个模型——一个是不断更新的,另一个是不断更新的模型的快照,它定义了影子状态并用于推测性启动。只要推测性启动负载均衡会话发生得非常快,即在统计上可能快照变得足够过时以导致严重的低效率(cwd420控制所有启动,因此唯一的不准确之处是某些cta可能会完成),这种安排就可以工作并且正在执行它们的sm相应地变得可用,并且在使用现已过时的模型的正在进行的负载均衡会话中没有考虑到这一点)。[0195]在一个实施例中,gpucga序列号被附加到启动命令,并且被预加到为每个gpccga生成的sm_mask。这个gpucga序列号用于将每个gpccga的sm_mask映射到gpucga,并且在将掩码发送到各个sm中的m管道控制器(mpc)之前由任何重排序单元使用。硬件因此可以提供掩码的多个迭代波,以确定何时将cga中的所有cta映射到sm,从而使得cga可以启动。一旦sm掩码准备好,它们被广播(与关联的cgaid)到gpu的所有sm工作调度器(参见图16b)。广播也是lmem_blk_idx分组,其将lmem_blk_idx(参见图14的lmem块索引表432)从cwd420运载到sm。这些操作完成了在真实硬件上的实际启动。[0196]图15示出,在一个实施例中,cwd420包括用于分配由gpccga构成的gpucga的两个级别的工作分配器(wd):[0197]·gpu2gpc工作分配器420a[0198]·多个gpc2sm工作分配器420b(0)、420b(1)、420b(2)、...。如上所述,第一级420a跨gpc分配gpccga。第二级(gpc到sm工作分配器420b)将cta分配到gpc内的sm。在gpu到gpc级别之前或高于其的另一个级别可以用于将μgpucga分配给μgpu(在一个实施例中,当存在μgpu时,gpu由μgpu构成,μgpu由gpc构成,并且gpc由tpc或sm构成)。[0199]gpu2gpcwd420a将gpucga的可能多个(1个或更多个)成分(constituent)gpccga分配到相应的gpc2sm工作分配器(图16,框506)。gpc2sm工作分配器420b各自将gpccga的cta分配到gpc内的sm(使用例如负载均衡模式或多播模式,如下所述)。图15的统一工作分配器(uwd)420a/420b保证gpucga中的所有gpccga可以一起启动,并且每个gpccga中的所有cta可以一起启动。在支持cga的更深嵌套的其他实施例中,这个uwd可以被扩展到所需要的任何数量的级别(例如,用于增加gpc到cpc的层次结构)和任何层次结构的任何数量的同时调度的硬件范围。[0200]在一个实施例中,uwd420a、420b执行以下进程:[0201]i.cga的推测性启动(图16,框508)[0202]阶段1:[0203]第一步骤是状态快照:从任务表436(图14)读取剩余数量的gpucga,并且基于remaining_gpu_cga将其箝位。在实施例中,负载均衡会话可以一次限于gpu_gpc_cga。[0204]阶段2:[0205]对于gpccga,cwd420执行查询+启动进程,直到不再有剩余的gpccga,其中“查询”构成针对查询模型的“推测性”(“影子状态”)启动,并且“启动”构成实际启动。因此,在一个实施例中,“推测性”或“查询”启动是针对查询模型在影子状态上执行的,但尚未执行实际启动(在其他实施例中,例如,具有重复的硬件,“推测性”可以指以下操作:实际执行,但在知道它是否有效之前执行,例如在“推测性执行”中)。在一个实施例中,在启动任何cta之前,对cga结构中的所有cta完成“查询”。例如,在具有多个gpccga的gpucga的情况下,cwd420将仅在其gpccga的所有成分都被保证接收gpu上的空闲槽时才启动gpucga。为了确定,(gpucga的)每个成分gpccga在任何cta被启动之前被推测性地启动并且检查(但是实际上没有被启动到sm)。[0206]在一个实施例中,每个gpucga可以在两次传递(pass)中被处理:[0207]传递i:推测性启动以“检查所有成分gpccga是否将找到家”[0208]假设gpucga中的gpccga的数量是“n”。为了确定以上情况,cwd420推测性地启动n个gpccga。[0209]参见图15,gpu2gpcwd420a向所有gpc2smwd420b发送查询命令。每个个体gpc2sm对分配给它的gpccga的所有cta执行推测性调度,并为该查询产生快速和有效的响应。在示例实施例中,由于推测性启动测试将针对gpucga内的每个gpccga重复,所以每个gpc2sm包括空闲槽寄存器和每sm的启动槽寄存器,用于存储其先前的响应。在每sm具有单个空闲槽和启动槽寄存器的实现方式中,在gpccga的第一推测性调度之后的迭代中使用的每sm的空闲槽值可以是“空闲槽值”——“当前启动槽值”,以考虑已经推测性地调度的cga。[0210]gpu2gpcwd收集来自gpc2smwd的响应,对“有效”的数量进行计数并且累积至计数器。这完成了第一查询迭代。gpu2gpcwd继续再次查询所有gpc2smwd,直到计数器达到每gpucga的gpccga的数量。如果gpu2gpcwd未能收集足够的“有效”,则gpu2gpcwd将终止会话,因为没有足够的空闲槽来保证gpucga中的所有gpccga中的所有cta可以被一起启动(图16d,“否”退出到判定框510)。[0211]在一些实施例中,不同的gpc可以具有不同数量的sm。在一个实施例中,cwd420还可实现每gpc的计数器,用于追踪在给定gpc上可同时执行的gpccga的数量。基于对应gpc中的sm的数目(例如,对于给定芯片数目)初始化每个计数器。每当启动新的gpccga时,cwd420递减适当的gpc计数器,并且每当从给定的gpc到达cga_complete分组时递增适当的计数器。[0212]在示例实施例中,cwd420可以使用不同的基于硬件的模式来将gpc_cga中的cta分配到gpc内的sm/核心,所述基于上文描述的硬件的模式:[0213]·load_balancing——(上文描述的)cta被发送至gpc或其他硬件域内的最小负载的sm/核心。该模式允许cwd420将cta放置在gpc或其他相关硬件域内的任何位置。例如,这可导致来自同一cga的多于一个cta(或者甚至用于小cta的所有cta)在同一sm上运行。[0214]·multi_cast——cwd420跨gpc或其他相关硬件域内的sm/核心分配cta,每sm至多来自同一cga的一个cta。该模式保证每个cta将在不同的sm上运行——这意味着由那些多个sm提供的所有互连和资源可被使得用于承载执行cga。在一个实施例中,cta被首先调度到其中两者(所有)sm/核心都可获取cta的分区上,然后调度到其中仅一个(少于所有)sm可用的分区上。[0215]multi_cast模式保证cta跨sm/核心很好地分布(而不是允许在同一sm上的多个cta),这为cga提供最大互连资源。例如multi_cast模式可以用在gpc_cga上,gpc_cga想要利用sm和通用网络接口控制器(gnic)中的新多播硬件和软件,例如张量存储器访问单元(tma),如2022年3月10日提交的题为“用于高效访问多维数据结构和/或其他大数据块的方法和装置(methodandapparatusforefficientaccesstomultidimensionaldatastructuresand/orotherlargedatablocks)”的上述美国专利申请no.17/691,276中所描述的。关于multi_cast方法的更多信息可以在2022年3月10日提交的题为“跨多个计算引擎的程序控制的数据多播(programmaticallycontrolleddatamulticastingacrossmultiplecomputeengines)”的上述美国专利申请no.17/691,288中找到。[0216]传递ii:“重置。然后,查询+启动”cga的实际启动(图16d,框512)[0217]如果传递1(推测性启动)成功,则为整个gpucga保证足够的空闲资源,cwd420开始传递2=>这是实际启动。这涉及:[0218]·重置所有gpc2smwd的启动槽寄存器;[0219]·分配gpucga序列号(用于重新排序);[0220]·逐一启动(gpucga的)成分gpccga;以及[0221]·对每个gpc2smwd重复“查询”和“启动”,以在sm上的每个gpccga中启动cta。[0222]在示例实施例中,cwd420还负责在线性存储器池中分配cga存储器槽以及刷新和回收槽。假设cwd420确定存在足够的资源并且以上阶段2完成或正在进行,则cwd420将信息传递到驻留在gpc内的gpm功能电路块。每个gpm分配屏障槽,当gpccga中的所有cta完成时,还分配cga_id和轨道。每个sm中的mpc(m-管道控制器)电路404同时跟踪每cta的槽,并且参与启动cta到其关联的sm上以实际进行工作。在此上下文中,在一个实施例中,cdw420就像纸牌游戏中的发牌者一样,并且sm是纸牌游戏的参与者。cwd420的工作是将“启动”卡分发给游戏中的每个sm“玩家”。同时,所有的sm都在看着卡被分发给彼此的sm,这样当一个sm最终收到自己的启动卡时,它可以根据之前收到的广播将自己得出的xyzid值写在卡上在比赛期间。任何新的sm都可以参与游戏,只要被告知另一个sm上次分配的当前xyzid值是什么。在一个实施例中,还有一种状态同步,其中cwd420向下发送束或网格的某些维度,然后在启动时,cwd将当前xyz偏移传送给任何新的sm及其相关的内部mpc。在其他实施例中,每个新到达的网格可以提示重新初始化xyzid坐标。[0223]当工作完成时,sm向gpm报告cta完成状态。当gpm电路接收到cga中的所有cta已完成的状态信息(图16d,框514)以及对cga的所有存储器分配已被刷新的状态信息(图16d,框516)时,gpm电路可发信号通知cwd420以释放池中的cga存储器槽,使得它可被分配给另一cga(图16d,框518)。[0224]使用上述技术,应用程序可以在gpc或其他硬件分区中启动许多小型cga,但随着cga大小的增长,数量会减少。在某个点(取决于硬件平台),没有cga可以再适合gpc或其他硬件分区,这可能会损害代码的可移植性。如果假设每个平台至少有一个gpc和4个tpc,那么保证跨未来架构兼容性的最大cga大小是8个cta。给定的应用程序可以根据查询平台动态调整cga大小,以确定可在gpu中同时运行的cga数量,作为1)cta资源需求和2)每个cga的cta数量的函数。[0225]cta分配和跟踪[0226]示例硬件实现在每个sm中提供了一个新的s2r寄存器,有助于跟踪cga内的cta(即,允许cta确定它是cga内的哪个cta)。在一个实施例中,sm执行s2r(特殊寄存器到寄存器)操作以返回cga内的线性ctaid。特别是,称为gpc_local_cga_id的附加基于硬件的多位标识符(使用的位数可能取决于支持的同时活动cga的数量)用于识别gpc命名空间内的cga并跟踪数量该cga的活跃cta。这个相同的值gpc_local_cga_id可以例如用于索引分布式共享本地存储器、引用屏障和其他cta间通信机制。[0227]s2r寄存器使着色器软件能够读取此线程的gpc_local_cga_id。gpc_local_cga_id在每次gpc_cga启动时分配给本地gpc,并在cga启动时跨相关硬件域广播。它在cga的生命周期内被跟踪,并在cga中的最后一个线程组完成时被释放。在一个实施例中,只要硬件看到gpccga启动的第一个数据包(见下文),它就会分配唯一的gpc_local_cga_id,然后跟踪其本地gpc内的所有活动gpccga。每当硬件接收到gpccga中所有cta的共享存储器刷新指示时,它都会回收gpc_local_cga_id。硬件维护可用gpc_local_cga_id的空闲列表或空闲向量,如果gpc_local_cga_id用完则停止cga启动。[0228]在上面讨论并显示在图12a中的示例网格中,标记为“c”的cta需要能够告诉(学习)它在六ctacga中的哪个cta,一旦由硬件分配(即,每个协作线程阵列现在有序合作组数组的一部分)。知道整个网格的尺寸和上面讨论的各种局部网格层次结构的尺寸,就可以将整个网格内的cta的坐标转换为cta在其cga内的坐标。在示例实施例中,每个网格或cga是根据使用3维坐标的层次结构中的下一级来定义的。如上所述,每个cta通过硬件寄存器将其ctaid(x,y,z)暴露给着色器中的软件。对于gpc_cga,新的s2r硬件寄存器可用于确定或发现gpc_cga中由启动程序预设的一维cga_cta_id。在一个实施例中,该cga_cta_id可以直接用于共享存储器索引(这在寻址共享存储器时很有用,因为可以使用其对应的cga_cta_id来引用共享存储器的每个段)。[0229]图12a的示例是针对包含gpc_cga的网格内的cta#c,整个网格内cta的坐标为(7,3,0),但gpc_cga内的cga_cta_id是一维坐标cgactald=4。这样就维持了基于整个网格内的3d坐标的编程模型,同时在其cga内为cta提供了一个附加的坐标。[0230]cga跟踪[0231]在如图13所示的一个实施例中,gpm跟踪cga中活动cta的总数。例如,当cga启动时,gpm将计数设置为cga中已经启动的cta的总数。当mpc指示cta已经退出时,gpm递减该计数。当计数已经递减到零(意味着cga中不再有cta是活动的)时,gpm确定cga已经完成。但在示例实施例中,gpm尚未将cgaid释放到池中以供重新使用。这是因为即使cga中的所有cta都已经完成,也可能存在一些未完成的(outstanding)dsmem(分布式共享存储器)访问请求。因而,示例实施例提供协议以确保cga中的cta在释放与那些cta相关联的cgaid之前已经完成其所有dsmem存储器访问(和其他访问)。在一个实施例中,gpc不释放cgaid,直到cga中的每个cta已经退出并且其所有存储器指令/访问已经完成。[0232]这样做是为了防止新的cga读取或写入(或从其接收读取或写入)先前使用相同的cgaid的失效的(defunct)cga。在一个实施例中,gpc_local_cga_id提供针对此的保护,因为当新的cga启动时,可能不存在来自cgaid的非当前用户的进行中(inflight)的dsmem访问。[0233]如以上所讨论的,当cga完成执行时,基于硬件的调度器(gpm)释放之前由cga使用的资源(例如,共享存储器、在sm上运行所需的线程束槽等),从而使得cwd420可以重新分配资源以启动新的cga。类似地,当cta完成执行时,基于硬件的调度器(gpm)释放cta先前使用的资源(例如,共享存储器、在sm上运行所需的线程束槽等)。一旦cta结束,就使用协议来挑剔(fault)对该cta的共享存储器的任何dsmem存储器访问。在一个实施例中,当cga中的所有cta都完成执行时,基于硬件的调度器保留cgaid并向正在该cga中运行cta的sm中的每一个发送dsmem存储器刷新(图16d,框516),然后等待响应。一旦运行cga中的cta的所有sm确认先前分配给该cga的共享存储器的存储器刷新,则gpm最终可将cgaid释放至重用池。[0234]在启动侧,cga中的每个cta需要知道cga中的所有其他cta在哪里执行,因此cta可以将事务发送给那些其他cta。该映射信息在启动期间被编程。[0235]sm内的映射表[0236]gpc_local_cga_id[0237]图18a-18b和19示出了用于允许sm与其他sm通信的示例实施例架构的不同视图。sm可以与另一个sm通信的消息之一是sm正在执行的cta的local_cga_id。在一个实施例中,这种sm到sm消息的分组格式包括u008字段“gpc_local_cga_id”。每个gpc都有自己的cgaid池,gpm在cga启动时将其中一个号码分配给cga。然后,该分配的编号用作例如指向由cga中的各种cta使用的dsmem分布式内存段的指针。在一个实施例中,“gpc_local_cga_id”还用作用于跟踪每个gpc_cga的屏障状态的id。[0238]图17示出了由每个sm维持的示例映射表布置。在一个实施例中,sm基于分段的地址确定目标,然后选择正确的分组类型以使互连知道这是sm2sm事务,并且基于如图17所示的路由表中的查找来提供物理smid。在一个实施例中,sm将gpc_cga内的逻辑ctaid映射到cta在其上运行的物理sm,以及在sm上的该cta的物理共享存储器。每次cta启动时,gpc上的所有sm可能需要知道它,因为这些sm中的任何一个都可能正在执行作为相同cga的一部分的cta。在一个实施例中,mpc404在每次启动新的cta时通知(广播消息到)所有sm。作为响应,每个sm更新其维护的映射表。在一个实施例中,cam结构被用于该映射以允许来自远程(其他)sm的dsmem寻址。如图17所示,cam结构被存储在ram中,作为由smcgaslot值索引的sm到sm映射表5004。映射表5004向sm标识cga中的其他cta在哪些其他sm上执行。定义5004示例表的伪码如下所示:[0239][0240]在本示例中,gpc_local_cga_id因此被用作该cga中的所有sm可以引用的本地cgaid。该表允许每个sm查找tpc_id和sm_id_in_tpc,其有效地为另一个sm的地址。该结构的索引是cga中的(逻辑)ctaid(该id对于每个cga是本地的)。因此,给定指示(可能正在运行的所有cga中的)哪个cga和逻辑ctaid的槽id,sm可查找正在运行该cta的该其他sm的sm_id,使得它可通过互连与该其他sm通信,以用于涉及例如分配给该其他sm上的该cta的dsmem段的事务。[0241]随着附加cta被启动和完成,表5004继续被更新,其中,每个sm随时间推移维护其自身的映射表5004。同时,硬件(mpc和gpm与sm协作)阻止cga同步屏障是有效的,直到cga中的所有cta已经启动并且所有sm已经接收到广播信息以构建其映射表5004,以便防止cga中的任何cta脱离屏障同步体制。[0242]在一个实施例中,图17中所示的第二表5002由每个sm维护以将线程束映射至cga槽。特别是,sm自身的内部线程束调度器依据线程束调度执行槽(例如,某一数目(例如64个线程束)可同时在任何给定sm上运行)。sm维护映射信息,以将线程束数目映射到cga_slot信息。因此,例如,一个sm上的线程束可发出ld指令,该ld指令被映射到执行同一cga中的其他线程束(cta)的另一sm的dsmem中。它首先使用表格5002识别cga_slot(槽),然后使用表格5004来确定将指令传递到哪个sm。综上所述,在源sm中,当cta(sm的物理线程束id=x)访问另一cta的共享存储器(由同一cga中的逻辑cta_id=a寻址)时,cta首先查找bl_table,以获得sm_cga_slot,然后查找cga_cga2sm_dir,以获得每以下伪代码的目的地sm(tpc_id和sm_id_in_tpc的元组)的gpc_local_cga_id和sm_id:[0243]gpc_local_cga_id=cga_cta2sm_dir[bl_table[x].sm_cga_slot].gpc_local_cga_id;[0244]destination_sm_id=cga_cta2sm_dir[bl_table[x].sm_cga_slot].sm_id_of_cta_in_cga[a];[0245]源sm然后使用根据以上指令格式的gpc_local_cga_id和sm_id将指令在互连5008上引导至目标sm的dsmem内的位置。[0246]图17还示出了目标sm在互连5008上接收的请求。当目标sm接收到该请求时,它可以使用如在以下伪代码中描述的表5010执行查找以找到dsmem基数和大小:[0247]·传入sm,cam匹配[cta中的gpc-localcga_id和cta_id]以找到共享存储器基数和大小[0248][0249][0250]目标sm匹配gpc_local_cga_id和cta_id_in_cga(注意:cta_id_in_cga被包括,因为可能存在运行在给定sm上的cga的多于一个cta)。如果存在匹配,则生成有效查找标签(如果不存在匹配,则这可能意味着cta不再在sm上运行并且接收sm相应地生成错误通知,该接收sm将该错误通知发送给始发sm)。假设有效的查找标签,所述表然后用于在保持共享存储器的物理存储中查找dsmem基数和大小(dsmem分配是可重定位的,并且因此可以在物理存储中的任何地方)。如上所述,表5010(在一些实施例中可以是内容可寻址存储器或cam)可以在硬件中复制以提供多个并发查找。目标sm然后将检查伴随指令出现的偏移,确保其在范围内,且接着对指定的dsmem存储器偏移执行读、写、原子操作或其他请求动作。如果指令指定超出范围的偏移,则检测到错误并且向源sm通知该错误。[0251]cga/cta退出和错误处理协议[0252]在一个实施例中,某些种类的错误不归因于程序计数器(pc)。通常,实施例将保留过去的pc的fifo,并且可以将任何存储器错误与给定的线程束、线程和pc相关联。当确定不存在可归因于该pc的错误时,pc可从fifo的末尾掉落。然而,某些类型的错误在目标sm处被检测或可检测,但不由源sm检测或可检测,因此不能与源sm的pc相关联。这种错误例如可以包括在目标处“未发现cga/cta”或者具体地目标sm检测到gpc_local_cga_id和cta_id_in_cga不在shmem_basecam中(通常因为cta已经退出),或者目标sm检测到绑定之外的地址,诸如addressoffset>shmem_base+shmem_size(例如,由于目标sm将其dsmem共享存储器分配的一部分提前释放至cga)。为了处理这样的错误,一个实施例不向目标或目的地sm报告错误,而是使目标sm负责使用类似于确认消息传递的错误消息传递向源sm报告这样的错误。当接收到错误分组时,源sm发布错误并将其归到cga,但不一定将其归到特定的线程束和/或pc,因为该信息可能不再可用。在源sm处,陷阱处理程序可以使用sr寄存器读取坏线程束的gpc_local_cga_id和cta_id_incga。如果cga已经退出(对于存储和原子来说是可能的),则错误可以被忽略/丢弃,因为它现在是有争议的。[0253]在源sm侧上可检测的其他类型的错误可以提供有效的线程束id(warpid)和pc,例如:[0254]cta_id_in_cga>cga中的cta的最大数目[0255]cta_id_in_cga在sm2sm表中具有无效的sm_id[0256]地址偏移>可能的最大共享存储器大小[0257]cga退出[0258]在一个实施例中,cga退出是多步骤过程。首先,运行cta的sm检测到线程束已经发送了warp_exit命令。这意味着cta想要退出,但如上所述,dsmemsm到sm写入和对l2线性存储器的cga写入可能仍在进行中。因此,cta实际上不退出,而是mpc被通知并且cta等待mpc授予退出许可。当cta中的所有线程束完成时,mpc向sm发送inval_cta_entry,以使图17中所示的cga共享存储器sm_cga_cta_slotcam条目无效。mpc然后将cta_complete发送到gpm和cwd,并将cta标记为需要存储器刷新。当cga中的所有cta都完成时,mpc将包括sm_cga_slot的cga资源解除分配,并向sm发布dsmem刷新。在接收到刷新完成的确认之后,mpc发送dsmem_flush_done。作为响应,在接收到来自cga中所有cta的dsmem_flush_done后,gpm回收gpc_local_cga_id,并向cwd发送cga_complete。[0259]由此,虽然cga线程块分组构造对于保证跨sm的并发性和负载均衡是有用的,但用于保证并发性的其他技术可代替地或组合地使用。例如,一些实施例可以使用软件布置(如协作组api)来布置以实现跨线程块集合的并发和负载均衡,或者还可使用其他技术来提供或保证gpu硬件的同一相关硬件域或分区内的并发性和跨gpu硬件的同一相关硬件域或分区的负载均衡(例如,利用分布式共享存储器的所有线程不仅并发地运行,而且可以在sm上启动和发现,所有这些sm都在特定硬件域(诸如被称为gpc的gpu的子部分)内,例如,因为各个线程可以通过查询已经在哪个gpc上启动了线程来测试)。虽然这样的其他技术是可能的,但cga层次结构在效率和确定性方面提供了某些优势。[0260]出于所有目的,本文引用的所有专利、专利申请以及公开物均通过引用结合在此,如同明确阐明一样。[0261]虽然已经结合目前被认为是最实际和优选的实施例描述了本发明,但应理解的是,本发明并不限于所公开的实施例,而是相反,意图覆盖包括在所附权利要求的精神和范围内的各种修改和等效布置。当前第1页12当前第1页12
技术特征:
1.一种处理系统,包括:一组处理器,以及工作分配器,其将线程块分配给所述一组处理器以供执行,所述工作分配器被配置为:(a)跨所述一组处理器均衡所述线程块的加载,以及(b)保证所述一组处理器能够并发地执行所述线程块,其中相应线程块被指派标识符坐标以在所述处理器上执行。2.根据权利要求1所述的处理系统,其中所述线程块由网格表示,并且所述处理器中的每一个处理器被配置为光栅化所述网格的相应部分。3.根据权利要求2所述的处理系统,其中所述网格包括三维网格。4.根据权利要求1所述的处理系统,其中所述处理器包括流式多处理器,并且所述工作分配器包括硬件电路。5.根据权利要求1所述的处理系统,其中所述工作分配器包括被配置为跨处理器集合分配工作的第一工作分配器,以及被构造为将工作指派给各个处理器的多个第二工作分配器。6.根据权利要求1所述的处理系统,其中所述工作分配器包括所述一组处理器的查询模型,并且使用所述查询模型针对所述一组处理器的影子状态来启动所述线程块,以测试所述线程块是否能够并发地启动。7.根据权利要求6所述的处理系统,其中所述工作分配器维护持续更新的实时查询模型,以及存储影子状态的进一步的查询模型。8.根据权利要求6所述的处理系统,其中所述工作分配器以迭代或递归方式使用所述查询模型来测试线程块组的多个层次级别的启动。9.根据权利要求1所述的处理系统,其中所述工作分配器通过同时选择多于一个处理器以启动其上线程块,而跨所述一组处理器对所述线程块进行负载均衡。10.根据权利要求1所述的处理系统,其中所述相应线程块是协作组阵列cga的一部分。11.根据权利要求10所述的处理系统,其中所述工作分配器选择性地不启动多于一个线程阵列,所述线程阵列是所述处理器中的任何一个处理器上的公共阵列的一部分。12.根据权利要求1所述的处理系统,其中所述一组处理器各自包括独立地导出或计算唯一线程块标识符的硬件。13.根据权利要求1所述的处理系统,其中所述工作分配器被配置为基于所述处理器的相应加载水平来确定哪些处理器可能最快地执行新工作。14.一种处理方法,包括:接收表示线程块的协作组阵列的网格;推测性启动所述线程块,其包括基于占用水平跨一组处理器对所述线程块进行负载均衡;以及如果所述推测性启动揭示所述网格将在所述一组处理器上并发地执行,则在所述一组处理器上启动所述线程块。15.根据权利要求14所述的处理方法,还包括处理器中的每一个处理器以分布式方式光栅化所述网格。16.根据权利要求15所述的处理方法,还包括向处理器广播线程块指派,每个处理器通
过响应于所述广播确定多维标识符的全局进程并在所述全局进程中为其自身的线程块指派生成多维标识符来光栅化所述网格。17.根据权利要求14所述的处理方法,其中所述推测性启动由硬件电路执行。18.根据权利要求14所述的处理方法,包括跨所述处理器执行所述负载均衡。19.根据权利要求14所述的处理方法,其中网格是三维的并且所述标识符是三维的。20.一种处理系统,包括:启动测试电路,其被连接以接收启动线程组阵列的指令,所述启动测试电路被配置为确定所述线程组阵列中的所有线程组是否能够在一组处理器上并发地执行,其中所述一组处理器中的至少一些处理器已经在执行其他任务;以及启动电路,所述启动电路以所述启动测试电路确定所述线程组阵列中的所有线程组能够并发地执行为条件,在均衡跨所述组的所述处理器的加载的同时,并发地启动所述线程组阵列中的所有线程组。

技术总结
本公开涉及用于处理器中的线程组的可扩展负载均衡的技术。处理器通过集中工作分配来支持新的线程组层次结构,以通过跨处理核心的推测性启动和负载均衡来提供线程组阵列中的线程组的硬件保证并发地执行。通过在处理核心之间分配网格光栅化来实现效率。之间分配网格光栅化来实现效率。之间分配网格光栅化来实现效率。


技术研发人员:广田源太郎 T
受保护的技术使用者:辉达公司
技术研发日:2022.10.13
技术公布日:2023/9/20
版权声明

本文仅代表作者观点,不代表航家之家立场。
本文系作者授权航家号发表,未经原创作者书面授权,任何单位或个人不得引用、复制、转载、摘编、链接或以其他任何方式复制发表。任何单位或个人在获得书面授权使用航空之家内容时,须注明作者及来源 “航空之家”。如非法使用航空之家的部分或全部内容的,航空之家将依法追究其法律责任。(航空之家官方QQ:2926969996)

航空之家 https://www.aerohome.com.cn/

航空商城 https://mall.aerohome.com.cn/

航空资讯 https://news.aerohome.com.cn/

分享:

扫一扫在手机阅读、分享本文

评论

相关推荐