多线程处理器中的寄存器文件的制作方法

文档序号:21407601发布日期:2020-07-07 14:41阅读:235来源:国知局
多线程处理器中的寄存器文件的制作方法

本公开涉及由多线程处理器中执行的机器代码指令使用的寄存器文件布置。



背景技术:

对开发为特定应用而设计的处理器(例如图形处理器(gpu)及数字信号处理器(dsp))的兴趣正在上升。另一类最近受到关注的特定于应用的处理器是专用于机器智能应用的处理器,其被申请人命名为“ipu”(智能处理单元)。这些处理器可以被采用为例如加速器处理器,该加速器处理器布置为执行主机分配的工作,例如训练或帮助训练知识模型,例如神经网络,或者执行或帮助执行基于这种模型的预测或推断。

机器智能算法是基于对“知识模型”执行迭代更新,这可以由多个互连节点的图形表示。每个节点表示其输入的函数。一些节点接收对图形的输入,一些接收来自一个或多个其他节点的输入,而一些节点的输出形成其他节点的输入,一些节点的输出提供图形的输出(在一些情况下,给定节点甚至可能具有以下全部:对图形的输入、来自图形的输出和对其他节点的连接)。此外,由一个或多个相应参数(例如权重)对每个节点的函数进行参数化。在学习级期间,目标是基于经验输入数据集,找到各个参数的值,使得图形作为整体针对可能输入范围而生成期望的输出。用于这样做的各种算法在本领域中是已知的,例如基于随机梯度下降(stochasticgradientdescent)的反向传播算法(backpropagationalgorithm)。在基于输入数据的多次迭代中,逐渐调整参数以减少它们的误差,并且因此图形收敛于解(solution)。在随后的阶段,学习的模型然后可以用于对在给定的指定输入集的情况下对输出进行预测,或者在给定的指定输出集的情况下对输入(原因)进行推断。

设计为用于机器智能应用的处理器可以在其指令集中包括专用指令,用于执行机器智能应用中常用的算术操作(指令集是处理器的执行单元配置为识别的基本机器代码指令类型集,每个类型由相应的操作码和零个或更多个操作数定义)。例如,机器智能应用(例如神经网络)中所需的常见操作是在输入数据集上进行内核(kernel)的卷积(convolution),其中内核表示神经网络中节点的权重。为了在数据上进行大尺寸内核的卷积,可以将卷积分成多个向量或矩阵积,每个积(product)输出拟与后续积的输出累加的部分和。已经存在一些处理器,这些处理器在其指令集中包括专用于执行向量和矩阵乘法类型操作的算术指令,以用于执行卷积。



技术实现要素:

处理器还可提供对并发(concurrent)执行多个程序线程的支持。这种支持通常包括用于每个线程的相应上下文寄存器组,其中每组用于保持要并发执行的多个线程中的相应一个的程序状态(“上下文”(context))。保持在给定的线程的上下文寄存器中的程序状态通常包括该线程的程序计数器、记录线程的状态(例如暂停、运行等)的一个或多个控制状态寄存器,以及多个操作数寄存器,包括算术操作数寄存器,用于暂时保持相应线程的算术指令用于操作和输出的值。不同并发线程通过不同的相应执行时隙中的共同执行流水线在时间上交错,每个时隙仅使用不同的相应一组上下文寄存器的寄存器。

通常,每个线程在每个线程的单独算术寄存器文件中包括其自己的相应算术操作数寄存器组。当指令作为给定线程的一部分执行时,隐含的是它总是使用该特定线程的算术寄存器文件中的算术操作数寄存器。

本文识别到可能出现如下的应用:线程可能事实上以一些相同的操作数值操作,也以特定于单独线程的一些其他操作数操作。示例可以是作为卷积的一部分执行的向量或矩阵乘法,由此每个线程中的指令将共同权重集(在线程之间共享)乘以特定于单独线程的输入数据。这种情况的一个特定示例可以在卷积神经网络中发生,其中许多节点实际上包括相同的权重但具有不同的连接。考虑例如这样的场景:每个线程配置为执行神经网络中不同的相应节点的处理,例如卷积共同权重内核与相应的输入数据以检测特定特征。在这些情形下,提供允许给定算术指令以线程之间共享的一个或多个共同权重操作数和特定于单独相应线程的一个或多个操作数的组合操作的机构是有利的。问题绝不是特定于神经网络的,并且可能出现在任何最终使用一些共享操作数值和一些线程特定操作数的应用中。

根据本文公开的一方面,提供了一种处理器,包括:一个或多个寄存器文件;和执行单元,其配置为执行指令集中定义的指令类型的实例,该指令集中的每个指令由操作码和一个或多个操作数组成。执行单元是配置为运行多个并发线程的桶型线程执行单元,每个并发线程在重复序列的交错时隙的不同的相应一个中运行,而对于每个并发线程,该一个或多个寄存器文件包括相应上下文寄存器组,该相应上下文寄存器组布置为保持相应线程的程序状态,每个上下文寄存器组包括由相应线程使用的相应算术操作数寄存器组。该一个或多个寄存器文件其中一个还包括共同于一些或所有并发线程的共享权重寄存器组。指令集中定义的指令类型包括具有操作数的算术指令,该操作数在其中执行算术指令的线程的相应算术寄存器组之中指定源和目的地。执行单元配置为响应于算术指令的操作码而执行包括将来自所述源的输入乘以来自至少一个共享权重寄存器的至少一个权重的操作,并将结果放置于所述目的地。

在实施例中,所述至少一个共享权重寄存器在算术指令的操作码中可以是隐含的,不被算术指令的任何操作数指定。

在实施例中,算术指令可采用另一个操作数,该另一个操作数在共享权重寄存器组之中指定所述至少一个共享权重寄存器。

在实施例中,输入可包括向量,而乘法可包括该输入与来自共享权重寄存器的权重的向量之点积。

在实施例中,所述至少一个共享权重寄存器可包括来自多个共享权重寄存器子集之中的子集,每个子集保持相应的权重向量;并且所述另一个操作数可选择从哪个子集取得权重向量以用于所述乘法。

在实施例中,所述算术指令可包括以下其中一项:向量点积指令、累加向量点积指令、矩阵积指令、累加矩阵积指令,或卷积指令。

在实施例中,所述并发线程可包括多个工作者线程,并且执行单元还可进一步布置为至少在一些时间运行监督者子程序,该监督者子程序包括至少一个配置为管理工作者线程的监督者线程。

在实施例中,监督者子程序可配置为写入共享权重寄存器文件中的权重。

在实施例中,可能只有监督者子程序可以写入共享权重寄存器中的权重,并且工作者线程可能只能够读取共享权重寄存器。

在实施例中,上下文寄存器可对于每可以并发执行的工作者线程包括相应一个上下文寄存器组,并可布置额外上下文寄存器组以保持监督者子程序的程序状态。

在实施例中,监督者子程序可布置为通过最初在所有时隙中运行来开始,并且在启动工作者线程前写入权重;其中监督者子程序可通过将监督者子程序最初在其中运行的一些或所有时隙中的每一个放弃给相应的工作者线程,从而启动每个工作者线程。

在实施例中,指令集可包括运行指令,该运行指令作为监督者子程序的一部分执行时,导致其中执行运行指令的时隙被放弃给其中一个工作者线程,使得工作者线程取代监督者子程序在该时隙中启动。

在实施例中,指令集可包括退出指令,该退出指令在作为其中一个工作者线程的一部分执行时,导致其中执行退出指令的时隙被交回给监督者子程序,使得监督者子程序取代工作者线程再次在该时隙中继续运行。

在实施例中,寄存器文件对于每个并发工作者线程包括单独的算术寄存器文件,相应的算术寄存器文件包括相应的算术操作数寄存器。

在实施例中,寄存器文件可包括单独的权重寄存器文件,其包括权重寄存器。

在实施例中,权重寄存器文件可布置成使得只有监督者子程序可以写入它,并且工作者线程只可以读取权重寄存器文件。

根据本发明的另一方面,提供了操作根据任何上述实施例或本文其他地方所述配置的处理器的方法,该方法包括通过执行单元在处理器上运行包括算术指令的一个或多个实例的程序。

附图说明

为了协助理解本公开的实施例和示出可以如何实现这些实施例,将参考附图作为示例,其中:

图1是示例性多线程处理器的示意框图,

图2示意性地示出了交错时隙的方案,

图3示意性地示出了在多个交错的时隙中运行的监督者线程和多个工作者线程,

图4示意性地示出了示例性处理器的逻辑块结构,

图5是包括组成处理器的阵列的处理器的示意框图,

图6是用于机器智能算法的图形的示意图,

图7示意性地示出了用于实现一种加载-存储指令的地址包入(packing)方案,

图8示意性地示出了步长寄存器组中的预定步长(stride)值的布置,

图9示意性地示出了3d内核k与一体积的输入数据的卷积,

图10示意性地示出了由一系列累加矩阵积指令阶段执行的矩阵乘法,

图11进一步示出了累加矩阵积指令的操作,

图12给出了布置为执行卷积的一连串累加矩阵积指令序列循环的示例,

图13示意性地示出了卷积指令的操作,和

图14给出了一连串卷积指令的示例。

具体实施方式

图1示出了根据本公开实施例的处理器4的示例。处理器4包括采用桶形线程处理单元形式的多线程处理单元10,以及本地存储器11(即,在多瓦片阵列的情况下在同一瓦片上,或者在单一处理器芯片的情况下在同一芯片上)。桶形线程处理单元是一种多线程处理单元,其中流水线的执行时间被划分为重复序列的交错时隙,每个都可以由给定的线程拥有。这还可以称为并发执行,将在稍后更详细地讨论。存储器11包括指令存储器12和数据存储器22(其可以在不同的可寻址存储器单元或同一可寻址存储器单元的不同区域中实现)。指令存储器12存储将由处理单元10执行的机器代码,而数据存储器22存储以执行的代码操作的数据和由执行的代码输出的数据(例如,作为这些操作的结果)。

存储器12存储程序的多个不同线程,每个线程包括用于执行特定任务的相应一系列指令。注意,本文所引用的指令是指机器代码指令,即处理器指令集的基本指令之一的实例,由单一操作码和零个或更多个操作数组成。在实施例中,程序包括多个工作者线程,以及可构造为一个或多个监督者线程的监督者子程序。这些将在稍后更详细地讨论。

多线程处理器是能够通常以并发方式并排执行多个程序线程的处理器。并发执行指线程共享共同执行流水线(或至少流水线的共同部分),并且不同线程通过重复周期中不同的交错时隙中的这个相同的共享执行流水线交错。由于隐藏流水线延迟的机会增加,这提高了性能。处理器包括对多个不同线程共同的一些硬件(例如共同指令存储器、数据存储器和/或执行单元);但是为了支持多线程,处理器还包括一些特定于每个线程的专用硬件。

专用硬件对于至少每个可以并发执行的线程包括单独上下文寄存器组26,即,周期中每个时隙一组。当谈到多线程处理器时,“上下文”指的是相应一个被并排执行的线程的程序状态(例如程序计数器值、状态和当前操作数值)。上下文寄存器指的是用于表示相应线程的这种程序状态的相应寄存器。寄存器文件中的寄存器与通用存储器的不同之处在于:寄存器地址被固定为指令字(instructionword)中的位(bit),而存储器地址可以通过执行指令来计算。

在处理单元10内,来自指令存储器12的多个不同的线程可以通过单一执行流水线13交错(尽管在整个程序的任何给定的时间点,通常只有存储在指令存储器中的总线程的子集可以交错)。多线程处理单元10包括多个上下文寄存器组26,每组26布置为表示不同的相应一个可以并发执行的线程的状态(上下文)。多线程处理单元10还包括共同于并发执行的线程的共享执行流水线13,以及调度器24,用于以交错方式(例如轮循(roundrobin)方式)通过共享流水线调度并发线程以便执行。处理单元10连接到共同于多个线程的共享指令存储器12,以及也共同于多个线程的共享数据存储器22。

执行流水线13包括获取级14、解码级16和执行级18,该执行级18包括执行单元,该执行单元可以执行算术和逻辑运算、地址计算、加载和存储操作,以及其他操作,如指令集架构所定义。

每个上下文寄存器组26包括相应的一个或多个控制寄存器,其至少包括相应线程的程序计数器(pc)(用于跟踪线程当前正在执行的指令地址),并且在实施例中还有一个或多个控制状态寄存器(csr)组,其记录相应线程的当前状态(例如它当前正在运行还是暂停)。每个上下文寄存器文件组26还包括相应的操作数寄存器组,用于临时保持由相应线程执行的指令的操作数,即,在执行时,相应线程的指令的操作码定义的操作用以操作或从其产生的值。每组寄存器26可实现在一个或多个寄存器文件中。

获取级14可以访问每个上下文的程序计数器(pc)。对于每个相应的线程,获取级14从程序存储器12中的下一个地址获取该线程的下一个指令,如程序计数器所指示。程序计数器自动地递增每个执行周期,除非由分支指令分支。然后,获取级14将获取的指令传递给解码级16以进行解码,然后解码级16将解码的指令的指示(indication)连同指令中所指定的任何操作数寄存器的解码地址一起传递给执行单元18,从而执行指令。执行单元18可以访问操作数寄存器和控制状态寄存器,它可以将其用于基于解码的寄存器地址执行指令,例如在算术指令的情况下(例如通过加、乘、减或除两个操作数寄存器中的值,并将结果输出到相应线程的另一个操作数寄存器中)。或者,如果指令定义了存储器访问(加载或存储),则执行单元18的加载/存储逻辑根据指令将来自数据存储器的值加载到相应线程的操作数寄存器中,或者将来自相应线程的操作数寄存器的值存储到数据存储器22中。

连接获取级14以在调度器24的控制下从指令存储器12中获取要执行的指令。调度器24配置为控制获取级14在重复序列的时隙中依次从并发执行线程集中的每一个获取指令,从而将流水线13的资源划分为多个时间上交错的时隙,如将在稍后更详细地讨论。例如,调度方案可以是轮循或加权轮循。以这种方式操作的处理器的另一个术语是桶形线程处理器。

图2示出了由调度器24实现的交错方案的示例。这里根据轮循方案交错并发线程,由此在方案的每个轮次内,轮次被分为时隙顺序s0、s1、s2......sj-1(例如j=4,或j=6),每个时隙用于执行相应的线程。通常,每个时隙是一个执行周期长,并且不同的时隙是均匀的大小,尽管在所有可能的实施例中不一定如此,例如加权轮循方案也是可能的,由此一些线程在每个执行轮次中比其他线程获得更多循环。通常,桶形线程可以采用偶数轮循或加权的轮循调度,其中在后一种情况下,加权可以是固定或自适应的。

然后,不管每次执行轮次的顺序,重复这种模式,每一轮次包括每个时隙的相应实例。因此,请注意,本文所指的时隙指序列中的重复分配位置,而不是序列的给定重复中时隙的特定实例。换句话说,调度器24将流水线13的执行周期分配到多个时间交错(时分多路复用)的执行信道中,其中每个包括重复时隙序列中的相应时隙的重现。在所示的实施例中,有四个时隙,但这仅用于说明目的,其他数量也是可能的。例如,在一个优选实施例中,实际上有六个时隙。

在实施例中,上下文寄存器26对于j个(在示出的示例中j=3,但这不是限制性的)可以并发执行的线程中的每一个包括相应的工作者上下文寄存器文件组cx0...cx(j-1),以及一个额外的监督者上下文寄存器文件cxs。工作者上下文寄存器文件保持工作者线程的上下文,并且监督者上下文寄存器文件保持监督者线程的上下文。注意,在实施例中,监督者上下文与每个工作者具有不同数量的寄存器。因此,处理单元10包括比时隙数量多一个的上下文寄存器文件26,即它支持比它能够进行桶形线程的交错时隙的数量多一个的上下文。

工作者上下文cx0...cxj中的每一个用于表示当前分配给四个执行时隙s0...sj之一的多个工作者线程中的相应一个的状态,用于执行程序员所期望的任何特定于应用的计算任务(再次注意,这可能只是存储在指令存储器12中的程序的工作者线程总数的子集)。额外的上下文cxs用于表示“监督者线程”(sv)的状态,其角色是至少在以下意义上协调工作者线程的执行:在整个程序中的哪一点在时隙s0、s1、s2...中的哪一个中分配要执行哪个工作者线程w。可选地,监督者线程可具有其他“监视者”或协调责任,例如执行外部交换或屏障同步。注意,当然所示j=4的个案只是用于说明目的的一个示例性实现。例如,在另一个实现中,j=6(6个时隙、6个工作者上下文和一个监督者上下文)。

参考图3,在实施例中,监督者线程sv在交错执行时隙的方案中本身不具有其自己的时隙。工作者也是这样,因为对工作者线程的时隙分配是灵活定义的。相反,每个时隙都有其自己的上下文寄存器组,用于存储工作者上下文,其在时隙被分配给工作者时由工作者使用,但在时隙被分配给监督者时不被使用。当给定的时隙被分配给监督者时,该时隙反而使用监督者的上下文寄存器文件cxs。注意监督者总是可以访问其自己的上下文,而没有工作者能够拥有监督者上下文寄存器文件cxs。

监督者线程sv具有在任何和所有时隙s0...s3(或更一般地s0...sj-1)中运行的能力。调度器24配置成:当程序作为整体开始时,通过将监督者线程分配给所有时隙来开始,即,使得监督者sv开始时在所有s0...sj-1中运行。但是,向监督者线程提供了一种机构,用于在某个后续点(直接或者在执行一个或多个监督者任务之后)将从中监督者线程正在运行的每个时隙暂时放弃给相应一个工作者线程,例如图3所示的示例中的初始工作者w0...w3(或更一般地w0...wj-1)。这通过监督者线程执行运行指令来实现,该运行指令至少采用指令存储器12中的工作者线程的地址作为操作数。工作者线程是可以彼此并发运行的代码部分,每个表示要执行的一个或多个相应计算任务。

运行指令作用于调度器24,从而将当前时隙(该指令本身在该时隙中被执行)放弃给由操作数指定的工作者线程。注意,在运行指令中隐含的是,在其中执行该指令的时隙正被放弃(在机器代码指令的上下文中,隐含指不需要操作数来指定这点----从操作码本身隐含地理解)。因此,交出的时隙是其中监督者执行运行指令的时隙。

监督者线程sv在一个或多个其他时隙中的每一个中执行类似的操作,以将其一些或全部时隙分配给工作者线程w0...wj-1中的不同的相应工作者线程(从指令存储器12中较大组的可能工作者线程中选择)。一旦它对最后时隙这样做,监督者就会被暂停(后来当工作者w将其中一个时隙交还时,将从它停下来的地方继续)。因此,监督者线程sv能够将不同的工作者线程分配给不同交错执行时隙s0...sj-1(例如,如图所示j=4,或j=6),每个工作者线程执行一个或多个任务。当监督者线程确定是时候运行工作者线程时,它使用运行指令将该工作者分配给其中执行运行指令的时隙。

在一些实施例中,指令集还包括运行指令的变型:“全部运行”(run-all)。这个指令用于一起启动多于一个工作者的集,全部都执行相同的代码。在实施例中,这在处理单元的时隙s0...s3(或更一般地s0...s(j-1))的每一个中启动工作者。

一旦启动,当前分配的工作者线程w0...wj-1中的每一个继续执行在由相应的运行指令指定的代码中定义的一个或多个计算任务。在此结束时,相应的工作者线程然后将其中它正在运行的时隙交给监督者线程。这是通过在相应工作者线程中执行退出指令来实现的。退出指令作用于调度器24,从而将当前时隙(该指令本身在该时隙被执行)交回监督者线程。然后,作为响应,调度器24继续在该时隙中运行监督者。

图4示出处理器4的更多示例性细节,包括执行单元18和上下文寄存器26的细节。处理器对于m个能够并发执行的线程中的每一个包括相应的指令缓冲器53。上下文寄存器26对于每个工作者m上下文和监督者上下文包括相应的主要寄存器文件(mrf)26m。上下文寄存器还对于至少每个工作者上下文包括相应的辅助寄存器文件(arf)26a。上下文寄存器26还包括共同的权重寄存器文件(wrf)26w,所有并发执行的工作者线程可以访问该共同的权重寄存器文件以从其读取。wrf可以与监督者上下文相关联,因为监督者线程是唯一可以写入wrf的线程。上下文寄存器26还可对于每个监督者和工作者上下文包括相应控制状态寄存器组26csr。执行单元18包括主要执行单元18m和辅助执行单元18a。主要执行单元18m包括加载-存储单元(lsu)55和整数算术逻辑单元(ialu)56。辅助执行单元18a至少包括浮点算术单元(fpu)。

在j个交错时隙s0...sj-1中的每一个中,调度器24控制获取级14将相应线程的至少一个指令从指令存储器11获取到对应于当前时隙的j个指令缓冲器53中的相应一个中。在实施例中,每个时隙是处理器的一个执行周期,尽管不排除其他方案(例如加权的轮循)。在处理器4的每个执行周期中(即为程序计数器提供时钟的处理器时钟的每个周期),获取级14视乎实现方式,获取单一指令或小“指令束”(例如二指令束或四指令束)。然后,经由解码级16将每个指令发布到辅助执行单元18a的fpu或主要执行单元18m的lsu55或ialu56之一,这分别视乎指令(根据其操作码)是存储器访问指令、整数算术指令,还是浮点算术指令。主要执行单元18m的lsu55和ialu56使用来自mrf26m的寄存器执行其指令mrf26m内的特定寄存器由指令的操作数指定。辅助执行单元18a的fpu使用arf26a和wrf26w中的寄存器执行操作,其中arf内的特定寄存器由指令的操作数指定。在实施例中,wrf中的寄存器可以在指令类型中是隐含的(即,对于该指令类型是预定的)。辅助执行单元18a还可以包含辅助执行单元18a内部的逻辑锁存器(latch)形式的电路,用于保持一些内部状态57,用于执行一个或多个类型的浮点算术指令的操作。

在获取和执行指令束的实施例中,给定指令束中的各个指令同时在下面的独立流水线18m、18a(如图4所示)中并行执行。在执行两个指令的束的实施例中,两个指令可以在下面相应的辅助流水线和主要流水线同时执行。在这种情况下,主要流水线布置为执行使用mrf的指令类型,并且辅助流水线用于执行使用arf的指令类型。将指令配对成合适的互补束可以由编译器处理。

每个工作者线程上下文具有其自己的主要寄存器文件(mrf)26m的实例和辅助寄存器文件(arf)26a的实例(即,对于每个桶型线程时隙具有一个mrf和一个arf)。本文关于mrf或arf描述的功能应理解为以每个上下文为基础而操作。然而,线程之间共享单一共享权重寄存器文件(wrf)。每个线程仅可以访问其自己的上下文26的mrf和arf。然而,所有当前运行的工作者线程可以访问共同wrf。因此,wrf提供由所有工作者线程使用的共同权重集。在实施例中,只有监督者可以写入wrf,而工作者仅可以从wrf读取。

处理器4的指令集包括至少一种加载指令,其操作码在执行时使lsu55从数据存储器22加载数据到其中执行加载指令的线程的相应arf26a中。arf内目的地的位置由加载指令的操作数指定。加载指令的另一个操作数指定相应mrf26m中的地址寄存器,其保持指针,该指针指向数据存储器22中从其加载数据的地址。处理器4的指令集还包括至少一种存储指令,其操作码在执行时使lsu55从其中执行存储指令的线程的相应arf存储数据到数据存储器22。arf中存储的源的位置由存储指令的操作数指定。存储指令的另一个操作数指定mrf中的地址寄存器,其保持指针,该指针指向数据存储器22中存储数据的地址。一般而言,指令集可包括独立的加载和存储指令类型,和/或至少一种加载-存储指令类型,其将加载操作和存储操作结合在单一指令中。如稍后将更详细地讨论,指令集可包括特定类型的加载-存储指令,其以单一指令执行两个加载操作和一个存储操作。注意给定处理器4的指令集可包括多个不同种类的加载、存储和/或加载-存储指令类型。

处理器的指令集还包括用于执行算术操作的一种或多种算术指令。根据本文公开的特定实施例,这些可包括至少一种使用共同权重寄存器文件wrf26w的算术指令。这种指令采用至少一个操作数,该操作数指定其中执行算术指令的线程的相应arf26a中的对应算术操作的至少一个源。然而,算术指令的至少一个其他源在共同于所有工作者线程的共同wrf中。在实施例中,这个源在相关算术指令中是隐含的(即,对于这种算术指令是隐含的)。在机器代码指令的意义上,隐含是指不需要操作数来指定。即,在这情况下,wrf中的源的位置是操作码固有的(对于该特定操作码是预定的)。替代地,在其他实施例中,算术指令可以采用操作数,该操作数在wrf中一些不同权重寄存器组之中指定要从哪个权重寄存器组取得权重。然而,在wrf中找到权重的源(与通用mrf或arf相反)这事实仍然是隐含的。

响应于相关类型的算术指令的操作码,辅助执行单元18a中的算术单元(例如fpu)执行算术操作,如操作码所指定,该算术操作包括以线程的相应arf中指定的源寄存器和wrf中的源寄存器中的值操作。它还将算术操作的结果输出到线程的相应arf中的目的地寄存器,其由算术指令的目的地操作数明确地指定。

可采用共同wrf26w中的源的算术指令的示例性类型可包括:一个或多个向量乘法指令类型、一个或多个矩阵乘法指令类型、一个或多个累加向量乘法指令类型和/或累加矩阵乘法指令类型(其将乘法的结果从指令的一个实例累加至下一个),和/或一个或多个卷积指令类型。例如,向量乘法指令类型可以将来自arf26a的显式输入向量乘以来自wrf的权重的预定向量;或者,矩阵乘法指令类型可以将来自arf的显式输入向量乘以来自wrf的权重的预定矩阵。作为另一示例,卷积指令类型可以卷积来自arf的输入矩阵与来自wrf的预定矩阵。具有共同于多个线程的共享权重寄存器文件wrf使每个线程能够将共用内核与其自己的相应数据相乘或卷积。这是有用的,因为这是机器学习应用中时常出现的情况,例如,其中每个线程表示神经网络中不同的节点,而共同内核表示正被搜索或训练的特征(例如,图像数据的区域或体积中的边缘或特定形状)。

在实施例中,wrf26w中的值可以由监督者线程写入。监督者(其在实施例中通过在所有时隙s0...sm中运行来开始)首先执行一系列放置指令来将一些共同权重的值写入wrf中的预定位置中。然后,它执行运行指令(或全部运行指令)来在一些或所有时隙s0...sj-1中启动相应的工作者。然后,每个工作者包括上面讨论的类型的一个或多个算术指令的一个或多个实例从而以其加载到其相应arf26a中的相应输入数据执行对应的算术操作,但使用由监督者写入wrf26w中的共同权重。当每个线程完成其相应任务时,它执行退出指令以将其时隙交回给监督者。当所有启动的线程已经完成其相应的任务,监督者可以将新的值写入wrf,并启动新线程集(或启动新集以继续使用wrf中的现有值)。

应当理解,标签“主要”、“辅助”和“权重”不一定是限制性的。在实施例中,它们可以是任何第一寄存器文件(每个工作者上下文)、第二寄存器文件(每个工作者上下文)和共享第三寄存器文件(例如监督者上下文的一部分,但所有工作者可访问)。arf26a和辅助执行单元18还可被称为算术寄存器文件和算术执行单元,因为它们用于算术指令(或者至少用于浮点算术)。mrf26m和辅助执行单元18还可称为存储器地址寄存器文件和算术执行单元,因为它们其中一个用途是访问存储器。权重寄存器文件(wrf)26w有这样的名称,是因为它用于保持用于特定类型的算术指令的乘法权重,将在稍后更详细地讨论。例如,它们可以用于表示神经网络中节点的权重。从另一方面看,mrf可以称为整数寄存器文件,因为它用于保持整数操作数,而arf可以称为浮点寄存器文件,因为它用于保持浮点操作数。在执行两个指令的束的实施例中,mrf是由主要流水线使用的寄存器文件,而arf是由辅助流水线使用的寄存器。

然而,在替代实施例中,注意不一定为了这些不同的目的而将寄存器空间26划分成这些独立的寄存器文件。反而,通过主要和辅助执行单元执行的指令可能能够在同一共享寄存器文件中指定寄存器(在多线程处理器的情况下,每个上下文一个寄存器文件)。而且,流水线13不一定需要包括并行组成流水线(例如辅助流水线和主要流水线)以同时执行指令束。

处理器4还包括交换接口51,用于在存储器11和一个或多个其他资源之间交换数据,例如处理器和/或外部装置(例如网络接口或网络附加存储(nas)设备)的其他实例。如图5所示,在实施例中,处理器4可以形成其中一个互连处理器瓦片的阵列6,每个瓦片运行较宽程序的一部分。因此,单独的处理器4(瓦片)形成较宽处理器或处理系统6的一部分。瓦片4可以经由互连子系统34连接在一起,瓦片4通过其相应的交换接口51连接到互连子系统34。瓦片4可以在同一芯片(即管芯)或不同芯片或其组合上实现(即,阵列可以由多个芯片形成,每个芯片包括多个瓦片4)。因此,互连系统34和交换接口51可以相应地包括内部(芯片上)互连机构和/或外部(芯片间)交换机构。

在多线程和/或多瓦片处理器或系统的一个示例性应用中,在多个线程和/或瓦片4运行的程序包括机器智能算法,例如配置为训练神经网络和/或基于神经网络进行推断的算法。在这些实施例中,每个工作者线程,或在每个瓦片上运行的程序的一部分,或每个瓦片上的每个工作者线程用于表示神经网络(一种图形)中不同的节点102;并且,线程和/或瓦片之间的通信相应地表示图形中节点102之间的边缘104。这在图6中说明。

机器智能从学习级开始,其中机器智能算法学习知识模型。该模型包括互连节点(即顶点)102和边缘(即链路)104的图形。图形中的每个节点102具有一个或多个输入边缘和一个或多个输出边缘。一些节点102的一些输入边缘是一些其他节点的输出边缘,从而将节点连接在一起以形成图形。此外,一个或多个节点102的一个或多个输入边缘作为整体形成对图形的输入,而一个或多个节点102的一个或多个输出边缘作为整体形成图形的输出。有时,给定的节点甚至可能具有以下所有这些:对图形的输入、图形的输出和对其他节点的连接。每个边缘104传送值或更常传送张量(n维矩阵),这些值分别形成在其输入边缘和输出边缘上提供给节点102和从节点102提供的输入和输出。

每个节点102表示在其输入边缘上接收的一个或多个输入的函数,该函数的结果是在输出边缘上提供的输出。由一个或多个相应参数(有时称为权重,尽管它们不需要一定是乘法权重)对每个函数进行参数化。通常,由不同节点102表示的函数可以是不同形式的函数和/或可以通过不同参数来参数化。

此外,每个节点的函数的一个或多个参数中的每一个的特征在于相应的误差值。此外,相应的条件可以与每个节点102的参数中的误差相关联。对于表示由单一参数参数化的函数的节点102,条件可以是简单阈值,即如果误差在指定的阈值内,则满足条件,但如果误差超出阈值,则不满足条件。对于由多于一个相应参数参数化的节点102,对于该节点102达到了可接受的误差水平的条件可能更复杂。例如,仅当该节点102的每个参数都落入相应阈值内时,才可以满足条件。作为另一示例,可以组合相同节点102的不同参数的误差来定义组合度量,并且在组合度量的值落入指定阈值的条件下可以满足条件,但是如果组成度量值超出阈值,则不满足条件(或者反之亦然,取决于度量的定义)。无论条件如何,这都给出了节点的参数中的误差是否低于某一可接受程度或水平的度量。通常,可以使用任何合适的度量。条件或度量对于所有节点可以是相同的,或者对于不同的相应节点可以是不同。

在学习级中,算法接收经验数据,即,表示对图形的输入的不同可能组合的多个数据点。随着接收到越来越多的经验数据,算法基于经验数据逐渐调整图形中各节点102的参数,以试图最小化参数中的误差。目标是找到参数的值,使得图形的输出尽可能接近给定输入的期望输出。由于图形作为整体倾向于这种状态,因此图形会被形容为收敛。在适当程度的收敛之后,图形可以用于执行预测或推断,即预测某些给定输入的结果或推断某些给定输出的原因。

学习级可以采用多种不同的形式。例如,在监督方法中,输入经验数据采用训练数据的形式,即对应于已知输出的输入。对于每个数据点,算法可以调整参数,使得输出更接近地匹配给定输入的已知输出。在随后的预测级中,图形然后可以用于将输入查询映射到近似预测输出(或者如果进行推断,则反之亦然)。其他方法也是可能的。例如,在无监督的方法中,不存在每个输入数据一个参考结果的概念,而是改为将机器智能算法留下来在输出数据中识别其自己的结构。或者在强化方法中,算法针对输入经验数据中的每个数据点试验至少一个可能的输出,并且被告知该输出是正还是负(以及潜在地它是正还是负的程度),例如赢或输、奖励或惩罚等等。在许多试验中,算法可以逐渐调整图形的参数,以便能够预测将导致正结果的输入。用于学习图形的各种方法和算法对于机器学习领域的技术人员来说是已知的。

根据本文所公开的技术的示例性应用,每个工作者线程被编程为执行与机器智能图形(例如神经网络)中相应的单独一个节点102相关联的计算。在这种情况下,节点102之间的至少一些边缘104对应于线程之间的数据交换,并且一些可以涉及瓦片之间的交换。在每个瓦片4多个线程的多瓦片布置6的情况下,每个瓦片4运行图形的子图。每个子图包括包含一个或多个监督者线程的监督者子程序,以及表示相应子图的节点102的工作者线程集。

在诸如机器智能的应用中,期望能够有效地将数据流入和流出处理器4(例如瓦片)的数据存储器22。例如,这对伴随一系列复杂的算术指令是特别(但不是唯一地)有用的,例如向量点积指令、矩阵积、累加向量点积、累加矩阵积或专用卷积指令,其将高度算术复杂性包入单一算术指令中。

为了解决这些问题,实施例在处理器4的指令集中提供了加载-存储指令类型,其执行两个加载操作和一个存储操作,然后自动地将独立的步长施加于加载地址和存储地址中的每一个,全部响应于指令的操作码的单一实例。此外,指令使用有效包入将地址包入适当的寄存器文件(例如mrf26m)中,由此将三个地址(两个加载地址和一个存储地址)包入两个寄存器的空间中。这允许利用从mrf26m到lsu的仅仅三个端口以单一指令访问三个存储器地址和步长寄存器(一个相应端口用于访问三个寄存器的其中一个)。

该指令在本文中可被称为“ld2xst64pace”,指的是它加载两个64位值和存储一个64位值,其中“pace”(步幅)是步长的同义词。然而,这个标签或特定位宽不一定当作是限制性的。该指令可能更一般地被简单地称为加载-存储指令(尽管这不暗示它一定是处理器的指令集中唯一一种加载-存储指令)或“ldx2st”(加载两次,并且存储)。其语法(syntax)如下:

ld2xst$adst,$asrc,$maddr,$mstride,strimm

$adst指识别辅助(或算术)寄存器文件(arf)26a中的目的地的一个或多个操作数,该目的地包括arf中的一个或多个寄存器。在实施例中,arf中的每个寄存器为32位宽,并且目的地$adst可由四个这种32位寄存器组成:$adst0:dst0+3。ld2xst64pace的目的地操作数可指定arf中这些目的地寄存器其中仅一个的位置(例如最低$adst0),而其他目的地寄存器的位置可以相对于此是隐含的(例如arf中接下来三个连续寄存器)。替代地,在其他实现方式中,不排除多个目的地操作数可以各自由单独的操作数明确且独立地识别(尽管这将需要增加的指令宽度)。

$asrc指识别arf26a中的源的一个或多个操作数,该源包括arf中一个或多个寄存器。在实施例中,arf中的每个寄存器为32位宽,并且源$asrc可由两个这种32位寄存器组成:$asrc0:src+1。ld2xst64pace的源操作数可指定arf中这些源寄存器其中仅一个的位置(例如最低$asrc0),而其他源寄存器的位置可以相对于此是隐含的(例如arf中下一个连续寄存器)。替代地,在其他实现方式中,不排除多个源操作数可以各自由单独的操作数明确地和独立地识别(尽管这将需要增加的指令宽度)。

$maddr指的是一个或多个操作数,其指定主要寄存器文件(mrf)25m中两个寄存器$maddr0:addr0+1的位置,它们之间保持有三个地址:两个加载地址和一个存储地址。在实施例中,mrf中每个寄存器为32位宽。存储器地址操作数可指定mrf中这些寄存器其中仅一个的位置(例如最低$maddr0),其他寄存器的位置可以相对于此是隐含的(例如mrf中下一个连续寄存器)。替代地,在其他实现方式中,不排除存储器地址寄存器可以各自由单独的操作数明确地和独立地识别(尽管这将需要增加的指令宽度)。

strimm是立即操作数组,两个加载地址和一个存储地址各自相应一组。在mrf26m中,提供了包括多个字段的步长寄存器。每个字段保持不同可能步长值的预定集的不同相应一个。步长值是用来递增存储器地址的值(即存储器地址步子(step)),通常用于一连串这种步子。对于两个加载和一个存储中的每一个,在执行本指令实例的相应加载操作或存储操作后,相应的立即步长操作数指定从步长寄存器中的哪个字段取得步长值以施加于相应的加载地址或存储地址。这沿着mrf26m中的地址移动,以有利于加载-存储指令的后续实例。

在实施例中,加载-存储单元55支持一特征,由此立即步长操作数的一个特殊值可以直接地指定数值为1的步长值(即,在所使用的地址空间中增加一个地址单位),而不指向寄存器字段。即,在立即步长操作数可以采用的值的范围之中,其中一个值指定数值为1的步长,而一些或所有其他值指定步长寄存器中的不同可能字段,其保持可编程步长值。这里一个单位指数据访问的原子大小。例如,如果操作数是16位浮点值的4元素向量,递增是1原子/单位,即等同于8字节(64位)。

步长寄存器是mrf26m中的寄存器。在实施例中,工作者本身负责将步长值写入其自己的步长寄存器(在其自己的mrf中)的字段中。替代地,不排除在其他实现方式中,步长寄存器的字段中的步长值可以由监督者线程sv写入,或者可使用多个方法的组合。

对指定$mstride的操作数的要求是处理器4的可选特征,这视乎实现方式。在实施例中,加载-存储指令采用指定mrf26m中步长寄存器$mstride的位置的操作数。因此,程序能够在多个可能步长寄存器之中选择步长寄存器,对步长的选择提供更大的灵活性。然而,在替代实现方式中,不排除$mstride的位置可以是固定或隐含的,并且加载-存储指令中不需要操作数。

图7示出了将三个地址包入mrf26m中的两个32位寄存器中的示例,每个地址为21位。图7还示出了将三个步长值包入mrf中的一个32位寄存器中的示例,每个步长值为10位(在这情况下寄存器的2位未被使用)。因此,加载-存储指令可以经由mrf的仅两个32位宽端口以单一指令访问三个存储器地址。同一指令可以使用第三个32位宽端口来访问步长寄存器,例如包含包入到mrf中的32位宽步长寄存器中的三个10位宽字段中的三个10位步长值(地址差量)(该寄存器的2位未被使用)。注意,图7所示的特定包入仅是示例。例如,在另一个实现方式中,addr2而不是addr1可以横跨两个寄存器。

图8示出mrf26m中的多个步长寄存器$mstridea、$mstrideb、$mstridec......的布置。这些中的任何一个可以被加载-存储指令的对应操作数指定为步长寄存器$mstride。每个可能步长寄存器可包括多个字段,例如在实施例中包括三个字段(尽管视乎实现方式,字段和步长寄存器的数量不一定与加载地址和存储地址的数量一样)。对于两个加载地址和一个存储地址中的每一个,立即数组的相应立即操作数strimm可以指定在步长寄存器$mstride中的一个可能字段,从其取得其相应的步长值(在相应加载或存储之后施加的地址差量)。例如,在实施例中,对于两个加载和一个存储中的每一个,如果步长操作数是2位,则其中三个可能值指定三个步长字段中的不同步长字段,剩下的可能值仅仅指定数值为1的步长,而不引用寄存器中保持的值。例如,00将指定数值为1(原子)的步长,01将指定步长寄存器中的第一字段,10将指定步长寄存器中的第二字段,而11将指定步长寄存器中的第三字段。

注意,在实施例中,步长立即数的其中一个可能值指定数值为1的默认递增,而不是步长寄存器$mstride中的字段。

在操作中,当由执行单元18操作时,加载-存储指令的操作码(由解码级16解码之后)触发lsu55执行以下操作。它将来自存储器22中两个加载地址(如mrf26m中$maddr中保持的地址指定)的值加载到arf26a中的目的地(如$adsc指定)。此外,它将来自arf中的$asrc的值存储到存储器22中的存储地址(如mrf中$maddr中保持的地址指定)。然后,lsu55以相应步长值独立地后递增(post-increment)两个加载地址和一个存储地址中的每一个,该相应步长值来自mrf中的步长寄存器$mstride的相应字段(如三个立即操作数strimm的相应一个指定)。

注意:对于加载-存储指令的当前实例的两个加载地址和一个存储地址中的每一个,分别在当前加载-存储操作的加载操作和存储操作中的每一个之后,当前指令的跨步(stride)操作以相应步长递增相应地址。视乎实现方式,这可表示在加载和存储两者之后一起施加所有递增,例如加载、加载、存储、递增、递增、递增。替代地,跨步操作可以在每次加载和存储之后立即递增相应地址,例如加载、递增、加载、递增、存储、递增。存储确实可以在一次或两次加载之前。重要的是,每个加载地址的递增在其相应加载之后完成,而存储地址的递增在存储之后完成。目的是沿着mrf中的加载地址和存储地址移动,为加载-存储指令的后续实例做好准备。

在实施例中,存储器11(或至少数据存储器22)具有仅两个用于从存储器加载数据的64位端口,以及仅一个用于将数据存储于存储器的64位宽端口。在实施例中,(给定上下文的)mrf26m具有仅三个通往加载-存储单元55的32位宽端口;(给定上下文的)arf26a具有仅一个通往加载-存储单元55的64位宽端口。(注意:在所示的示例中,ialu56用于从mrf26m中检索指针,并从这些指针计算地址,从而传递给lsu55,所以实际上ialu56充当了lsu55的一部分。因此,在这示例中,从mrf26m到lsu55的三个端口包括从mrf26m到ialu56的三个端口。不排除在其他实现方式中,lsu55可以直接从mrf26m中检索指针,并基于这些指针计算其自己的地址)。

在实施例中,arf中四个32位目的地寄存器$adst0:dst0+3(总共128位)可用于从存储器22加载例如16位浮点(f16)值的四元素向量和32位浮点(f32)值的二元素向量。arf中两个32位源寄存器$asrc0:src+1(总共64位)可用于将例如f32值的32位的二元素向量存储在存储器22中。

为了在程序中使用,加载-存储指令散布在其他类型的指令之中,例如算术指令,其从加载指令的目的地取得输入,基于这些输入执行操作,并将结果输出到加载-存储指令的源。即,程序包括加载-存储指令的实例和至少一个算术指令的实例,例如先前所述的向量点积指令、矩阵积指令、累加向量点积指令、累加矩阵积指令或卷积指令;其中至少一些加载-存储指令的目的地是至少一些算术指令的源,并且至少一些算术指令的目的地是至少一些加载-存储指令的源。由于加载-存储指令的高语义密度(semanticdensity),加上其加载和跨步两个功能,这允许程序在加载操作和存储操作耗用小量代码开销(codeoverhead)的情况下有效处理数据。

例如,程序可以包括一连串指令对,每个指令对由加载-存储指令实例以及之后的对应算术指令实例组成。在每个指令对中,加载-存储指令的源设置为来自先前指令对的算术指令的目的地,并且加载-存储指令的目的地设置为当前或后续指令对中的对应算术指令的源。例如,考虑具有以下语法的算术指令“arith”:

arith$adst,$asrca,$asrcb

其中$adst是指定arf26a中的目的地的操作数;而$asrca、$asrcb是指定arf中两个源的操作数(应当理解,“arith”是这里用于具有至少这种语法的任何算术指令的通用名称)。然后,程序可以编程为具有一连串指令对,例如:

……

ldx2stxin-pin,pout,tripacked,strides;arithpout,xin,pin;

ldx2stxin-pin,pout,tripacked,strides;arithpout,xin,pin;

ldx2stxin-pin,pout,tripacked,strides;arithpout,xin,pin;

ldx2stxin-pin,pout,tripacked,strides;arithpout,xin,pin;

……

或:

……

ldx2stxin-pin,pout_a,tripacked,strides;arithpout_a,xin,pin;

ldx2stxin-pin,pout_b,tripacked,strides;arithpout_b,xin,pin;

ldx2stxin-pin,pout_a,tripacked,strides;arithpout_a,xin,pin;

1dx2stxin-pin,pout_b,tripacked,strides;arithpout_b,xin,pin;

……

在实施例中,每对是指令束,即在下面的相应流水线同时执行。例如,在实施例中,加载-存储指令由使用mrf26m的主要流水线执行,而算术指令由使用arf26a的辅助流水线并行地执行。然而,在替代实现中,不排除加载-存储指令和算术指令可以通过单一流水线处理单元逐一执行。

在加载-存储指令(ldx2st)的实例中,xin-pin是arf26a中两个加载操作(例如,4xfl6输入向量xin和2xf32输入向量pin被加载到四个32位寄存器$adsc0:dsc0+3中)的目的地$adsc;pout_a或pout_b指arf中存储的源(例如从两个32位寄存器$asrc0:src0+1存储2xf32值)。“tripacked”指mrf26m中三重包入的地址寄存器对$maddr0:addr0+1(例如,在两个32位寄存器中保持三个21位地址指针)。“strides”指步长操作数$mstride和strimm,其对于两个加载操作和存储操作的每一个,通过参考mrf中由三个立即值strimm指定的步长寄存器$mstride内的字段来指定步长(再参见图8)。在算术指令的实例中,xin、pin指从其取得算术指令的输入的源寄存器,该输入设置为与由当前或先前指令对中的加载-存储指令执行的加载的目的地一样。pout指arf中算术指令的输出的目的地,其设置为与后续指令对中的加载-存储指令的存储操作的源一样。在每个指令对作为两个同时指令的束执行的实施例中,xin、pin设置为与由先前束中的加载-存储指令执行的加载的目的地一样;而pout设置为与下一束中的ldx2st的存储操作的源一样。这会重用相同的寄存器,但由于两个指令并行执行,当前算术指令的输入数据是由先前加载指令读取的。然后,当前ldx2st重用这些相同的寄存器以准备下一个算术指令的输入数据。

因此,在每个指令对中,加载-存储(1dx2st)从先前指令对(例如束)中的先前算术指令存储当前在寄存器pout中找到的输出,并且还将值从存储器加载到寄存器xin和pin中。同一指令对(例如束)中之后的算术指令基于先前加载的值执行算术操作,并输出给寄存器pout,以通过后续指令对中的后续加载-存储指令的存储操作存储。

注意,在实施例中,算术指令在共享wrf26w中至少具有第三隐含源。这些可以由写入wrf的监督者线程设置。因此,监督者设置要由所有执行工作者线程的算术操作隐含地使用的共同权重。

存储器地址“tripacked”指定mrf26m中$maddr0:addr0+1的值也被相应工作者设置为一些初始值。mrf中每个可能步长寄存器$mstride的字段中的步长值也被相应工作者设置。每次执行加载-存储指令时,存储器地址寄存器$maddr0:addr0+1中的三个地址(两个加载地址和一个存储地址)各自以相应的步长值后递增。再参见图7和8。例如,加载-存储指令指定$mstride=$mstridea和strimm=011000(第一立即步长操作数=01,第二=10,第三=00)。这代表执行第一加载之后,它以$mstridea的字段0中的步长值递增第一加载地址;在执行第二加载之后,它以$mstridea的字段1中的步长值递增第二加载地址;并且,在存储之后,它以原子增量递增存储地址(在所使用的地址空间中以数值为1的存储器地址步子增递)。加载-存储指令的后续实例可以设置为指定$mstride的相同或不同值,以及三个立即操作数的每一个的相同或不同值。因此,随着一连串加载-存储指令中的每一个,加载和存储的位置可以以可控制方式移动。因此,代码可以以灵活的方式有效地扫描输入数据空间,而无需额外的整数算术指令来计算新地址。

图9示出了其中这可能是有用的示例性应用,即执行内核k与输入数据xin的多维部分的卷积。例如,输入数据可以是3d体积的输入数据,并且内核k可以是3d内核。输入数据还可被称为输入通道,而输出数据可以称为输出特征通道。在数据被说是多维的情况下,这意味着数据在二维或更多维坐标系中的多个坐标组合中的每个坐标组合处取值,每个维度(即每个轴)表示不同的自变量(并且给定坐标组合处的数据值是因变量)。

这种情况的一个例子是其中每个数据值代表一个像素的图像处理。例如,通常对于红、绿和蓝中的每一个使用8位;然后,那些8位整数值将在卷积操作之前转换成f16值。每个r、g、b值被视为单独的输入平面(即,单独输入通道)。因此,每个2d输入图像具有x、y、z维度,其中r、g、b平面填充z轴。该体积的数据可以例如包括一系列帧(frame),其中体积的两个维度表示帧区域的空间x和y轴,第三维度表示相应于该序列中不同帧的时间轴。在另一示例中,体积的三个维度可表示空间或物体的3d模型或图像的三个空间x、y和z维度。在另一示例中,数据可以仅是表示静止图像的空间x和y轴的两个维度,而z轴表示要同时处理的多个输入图像。注意,所公开技术的应用性不限于图像或图形处理,也不排除维度更高的数据。例如,两、三或更多维度可以表示用户的不同方面或他们在应用学习用户行为等方面的情况。

内核k是预定权重的矩阵。它可以表示神经网络被训练以识别或在后续推断中搜索的特定特征。例如,在图像数据的情况下,内核可表示边缘或一些其他特定类型的形状。在机器学习应用中,神经网络中的每个节点可以对应于相应的内核(尽管如稍后所述,在许多神经网络中,存在使用相同内核值但具有不同连接104的多个节点102)。在实施例中,每个节点102由相应的工作者线程表示,因此每个线程执行内核k与该线程的相应输入数据的相应卷积。至少一些工作者线程可以使用相同的内核k,其值存储在共享权重寄存器文件(wrf)26w中,但每个这种线程卷积该内核与线程自己相应的输入数据,该输入数据经由其自己相应的辅助(或算术)寄存器文件(arf)26a流出和流入存储器22。

三维中的离散卷积(*)可以表示为:

xin*k[x,y,z]=∑_x’,y’,z’(k[x’,y’,z’]xin[x-x’,y-y’,z-z’])

因此,卷积包括在内核可以与输入数据重迭的一些或所有可能位置上系统地扫描内核k。在每个这种位置,输入数据中与内核重迭的部分中的每个像素(或数据点)乘以相应重迭点处的内核值,并且将这些单独乘法中的每一个的结果相加以给出标量输出,表示内核与输入数据在该特定重迭位置处的卷积。然后在内核相对于输入数据xin的不同扫描位置处重复该操作,从而给出相应体积的输出数据(每个内核位置一个标量值)。例如,在图9所示的示例中,内核k开始可以被放置在一体积的输入数据xin内的一个角落中,并且当内核处于该位置时,每个内核值乘以它覆盖的数据点。然后内核沿着体积的长度移动一步,再次执行乘法及求和,而这次在内核处于新位置的情况下执行等等。当沿着体积的整个长度扫描内核时,将其移动到新的坐标位置并再次执行纵向扫描等,直到扫描了整个体积。每个给定位置的内核生成输出数据的一个像素(一个标量值)。因此,输出数据xout将具有与输入数据相同或相似的大小,这取决于卷积扫描的步子大小。

在实践中,这需要分解为更小的操作。这可以通过将数据与给定位置处的内核的卷积分成多个单独的向量点积和部分和来完成。这在图9的中间和右侧示出。例如,内核的大小为3x3x16像素(“像素”不一定是指为了本讨论而提到的图像)。即,它由3乘3乘16个预定权重值组成。这可以分解为九个16元素向量cw(这里也称为内核k的组成内核)。首先,在这九个向量之一和相应位置的输入数据之间取点积(即标量积),得到部分和p(标量)。然后在九个向量中的另一个之间取点积,并与第一部分和累加以得到第二部分和(也是标量)。然后在九个16元素向量中另一个之间取点积,并将其结果与第二部分和累加以得到第三部分和等。一旦完成以累加了全部九个向量,总累加结果给出输出数据xout中的单个点或像素的值。然后,随着内核k在相对于一体积的输入数据xin的不同位置上被扫描而在每个内核位置重复这过程,从而给出相应体积的输出数据xout(每个内核位置一个输出数据点)。

在实施例中,为了帮助以有效的方式执行诸如卷积的计算,处理器4的指令集包括累加积广amp”)指令形式的算术指令。它具有以下的语法:

amp$adst,$asrca,$asrcb,phase

其中$adst再次是指定arf26a中的目的地的操作数;$asrca、$asrcb是指定arf中两个源的操作数。“phase”是指定累加阶段的立即操作数。例如,在实施例中,阶段操作数由两个位组成,指定四个可能阶段0...3的其中一个。在实施例中,amp指令可以被称为f16v4sisoamp,指的是它采用四个半精度(16位)浮点值的一个向量作为第一输入,并且单精度(32位)浮动点值作为第二输入;并输出单精度(32位)浮点值(“siso”指“单精度输入,单精度输出”)。实际上,在实施例中,第二输入是两个单精度浮点值(2x32位)的对,输出也是如此。然而,应当理解,这些特定的精度值和元素数量并不限于所有可能的实施例。

对于诸如amp的一种或多种类型的指令,在实施例中,wrf中的权重的位置是完全隐含的。替代地或附加地,一个或多个其他类型的指令可以采用额外的操作数(未示出)来在wrf中的几个不同权重组中指定使用哪组。例如,一个示例可以是下文提及的细长(slim)卷积(“slic”)指令。

结合先前描述的加载-存储指令(ld2xst),诸如amp指令的指令可用于有效地从存储器中流入数据,执行点积和部分和,并将部分和流回到存储器中。考虑例如包括四个指令对的循环序列的程序,如下所述。

另一个示例性版本是:

再次,在实施例中,每对是指令束,即在下面的相应流水线(例如主要流水线和辅助流水线)同时执行。

每个指令对包括加载-存储指令的实例以及之后的累加积(amp)指令的实例。amp指令的源是由同一或先前指令对中的加载-存储指令执行的两次加载的目的地。在将每个指令对作为两个同时指令的束执行的实施例中,amp的源(xin、pin)设置为与先前束中执行的加载的目的地一样。amp指令的目的地是后续指令对(例如下一个束)中的加载-存储指令执行的一次存储的源。amp指令的源$asrca、$asrcb之一用于从输入数据xin取得输入向量x。另一个源用于取得部分和。amp指令在执行时进行其输入向量x与来自权重寄存器文件wrf26w的权重的对应向量cw(此向量cw是整体或3d内核k的组成内核)的点积。阶段操作数指定目的为累加点积的结果的阶段。在循环的给定实例中的序列的每个指令对中,阶段操作数设置成不同的相应值,指定序列的不同连续阶段。在这些由阶段操作数指定的序列中的连续阶段中,amp指令的效果是累加每个连续点积的结果。累加在序列的第一阶段中,具有输入部分和。

加载-存储指令的跨步功能允许程序随着每个指令对自动地沿存储器地址移至下一条数据,不需要独立的整数算术指令来计算新存储器地址以包括在mrf26m中。所述加载-存储指令从步长寄存器$mstride中选择多个预编程步长中任何一个的能力对处理多维度数据是特别有用的,例如如图9作为示例所示。存储器空间是一维的,但数据可以具有二、三或更多维度。视乎1d存储器空间在多维度数据空间的映射(mapping),随着内核k通过输入数据xin被扫描,有时可能需要产生不同大小的步子来通过存储器空间中的对应存储器地址。例如,当沿着输入数据xin的一个维度纵向扫描内核k时,每个扫描位置处的数据的存储器地址可以以原子步子递增,但当扫描需要在垂直平面中移位时,则存储器地址中可能需要不同大小的步子以获得输入数据xin的下一条或子集(并且独立地,对第二输入和输出地址进行相同的处理)。步长寄存器$mstride或多个步长寄存器(例如$mstridea、$mstrideb......)中的不同字段可以有利地预编程为在存储器空间中具有不同大小的跳跃(jump)。编程者或编译器便可设置立即操作数strimm以选择在每个加载-存储指令的基础上使用哪个跳跃大小(不需要独立的整数算术指令来重新计算下一个地址或下一个步子大小)。

在实施例中,amp指令是累加矩阵积指令。其操作将参考图10至12描述。如图10所示,当被fpu执行时,amp指令执行权重的mxn矩阵(来自wrf26w)与来自输入数据xin的n元素输入向量的乘法。在实施例中,m=8和n=16。注意,矩阵的m行中的每一行对应于来自不同相应内核k0、k1...km-1的组成向量。因此,amp指令用于并行执行m个不同的内核k与输入数据的卷积的一部分。例如,这些内核的每一个可以对应于不同相应特征(例如不同边缘或形状)与输入数据的卷积。在卷积神经网络的情况下,它们是特征过滤器,m个内核中的每一个试图检测输入层中不同的特征的存在。对于给定的内核k,amp指令仅执行点积和累加。然而,矩阵允许多个内核有效地与数据并行卷积。

n元素输入向量被分成n1个段,每段包括n2元素的子向量(因此n=n1xn2)。在实施例中,n1=4和n2=4。amp指令的阶段操作数采用对应于n1个不同段的n1个不同可能值0...n1-1之一。在循环序列的每个实例中,每个连续对中的amp指令采用阶段操作数中的不同值,指定阶段0...n1-1的不同连续一个。每个阶段执行n元素输入向量的n1个子向量的对应一个与矩阵的m行的每一行的点积(从而m个不同内核k的每一个的计算的一部分)。执行单元18中的fpu(在实施例中,在辅助或算术执行单元18a中)具有m个累加器状态$aacc(每个线程)。在实施例中,这些实现为fpu的内部状态57。然而,在替代实现方式中,不排除它们可以实现为其中一个寄存器文件26(例如相应线程的arf26a)中的寄存器。在所示示例中,这些是偶数状态$aacc[0]、$aacc[2]...$aacc[14];而奇数状态$aacc[1]、$aacc[3]...$aacc[15]可以用于在序列的不同循环之间传播值,但这是一个实现细节而非限制性的。

图11以图示方式示出了amp指令的操作。图12给出了一连串amp指令的示例。每个被理解为前接指令对的对应加载-存储指令,如上所示。在图12中,pn是单精度输入部分和n,xn是f16v4输入向量,cwm,n是共同权重状态$cwei_m_n,rn是以pn开始的连续点积累加的最终单精度结果。

在操作中,响应于amp指令的(解码的)操作码,执行单元18(在实施例中为辅助执行单元18a)的fpu执行以下操作。

·从amp指令的其中一个源操作数指定的arf26a中的寄存器,它取得m/n1个部分和,并将这些部分和临时放置在传播器状态中以用于下一个循环。该传播器状态可以实现在fpu的内部状态57中,或者替代实现方式中,它可以是其中一个寄存器文件26(例如arf)中的另一个寄存器。每个阶段取得m/n1个部分和的不同子集。在n1个阶段中,m个这种部分和被带入传播器状态。因此,如果m=8和n1=4,则每个amp指令取得两个部分和(例如两个f32值)作为输入,并将这些部分和保持在传播器状态中,并且在全部四个阶段中,八个部分和被接收。

·从amp指令的其中一个源操作数指定的arf26a中的寄存器,它取得输入向量xin的n2元素段(子向量)。对于矩阵中m行中的每一行(因此m个内核k0...km-1中的每一个),它执行这与来自wrf的权重的对应子向量cw的点积。权重的子向量取自哪一列取决于阶段操作数的值。此外,如果阶段是序列中的第一(即,初始)阶段,则对应一个部分和也被添加到m个点积中的每一个。注意,由于先前循环中的每个amp指令取得相应m/n1个部分和(其中n1是阶段的数量),先前循环将把全部m个部分和放在传播器状态中,为当前循环做好准备。

·对于m行中的每一行,上述计算的结果与已经在m个累加器状态$aacc中对应一个中的任何值累加(求和),从而生成m个结果r0...rm-1中的对应一个。因此,在n1个阶段中,amp指令将执行完整n元素输入向量与来自wrf的权重的对应n元素向量的点积。

·在当前循环中,来自先前循环的m/n1个结果r被输出到由amp指令的目的地操作数指定的arf中的目的地寄存器。每个阶段输出m/n1个部分和的不同子集,并且在n1个阶段中,m个这种部分和被带入传播器状态。因此,在m=8和n1=4的实施例中,每个amp指令输出两个结果(例如两个f32),并且在全部四个阶段中输出全部八个结果r0...r7。

·在当前循环的最后阶段之后(或在覆盖任何结果之前的下一循环的第一阶段开始时),将当前循环的结果r临时置于传播器状态,准备在下一循环中输出。该传播器状态可以实现在fpu的内部状态57中,或者替代实现方式中,它可以是其中一个寄存器文件26(例如arf)中的另一个寄存器。

总括而言,单一部分和被:(1)添加至第一点积结果,并存储在累加器状态中(覆盖先前保持的值),(2)与额外三个点积结果累加,以及(3)复制到临时传播器状态中(在这情况下,该值被写入将来的amp指令的目的地操作数)。步骤(3)的替代方案是将所得的部分和直接从累加器写入amp指令的目的地操作数中。无论是哪种方式,步骤(1)和(3)可能在硬件中重迭,提供4周期循环。

在实施例中,累加器状态不一定需要明确地重置。由于每个矩阵-向量乘法的起点是从存储器读取的输入部分和,输入体积在卷积开始时,所有元素设置为零,而不是重置累加器状态。尽管如此,在实施例中,瓦片4确实允许零初始化(zeroinitialise)所有累加器状态。

注意,当前amp指令的输入传播器状态被保持用于下一个循环。此外,由amp指令输出到arf中的目的地寄存器的结果是应用当前amp的累加操作前的现有累加器状态,它是先前短序列的累加的结果,不包括当前输入。

程序被(程序员或编译器)配置为使得结果r成为后续循环的部分和输入p。确切的关系取决于程序员或编译器,并取决于数据和内核的结构。通常,部分和具有数值为0的初始值(存储器中)。

注意,由于循环之间的滞后,序列需要预热(warm-up)期。在呈现的特定输入向量与由amp指令返回的4阶段计算的结果之间存在延迟。该延迟是固定的,意味着首m个结果无效、无趣或无意义,并在预热代码中被丢弃。在这个没产生有用结果的预热期之后,代码便进入前进的重复循环并将有用结果写入所需的存储器位置(在所示示例中一次64位)。在内部循环后还有冷却期,其中不提供新的输入,但存储最终输出值。图12示出了f16v4sisoamp的″所得延迟″和预热期。

在实施例中,内核数目m=8,输入向量中的元素数量n=16,并且阶段数量n1=4。在实施例中,输入向量的每个元素是f16值,并且每个输入部分和和每个结果是f32值。在这些实施例中,上述过程可以以每个指令对输入向量的四个f16元素和两个f32部分和的速度加载和处理数据,并且可以以每个指令对两个f32值的速度输出和存储数据。即,每个指令对128位输入和64位输出。这对应于lsu55和数据存储器22之间一个64位宽存储端口和两个64位宽加载端口(再参见图4)。此外,由于地址的三重包入,可以经由从mrf26m到lsu的两个32位宽端口和用于步长的另一个端口处理该过程。从arf26a到辅助执行单元18a中的fpu使用两个64位宽端口。图12示出了对于每个16元素输入向量,循环产生8个输出值(每个内核1个输出值)。在这特定情况下,这些输出值每个是32位的。上面的循环每4个节拍(tick)处理16个输入值(每个指令4xf16输入值)。为了维持该输入速度,处理器4需要每4个节拍循环产生8x32位值,即每个循环4x64位存储,或每个节拍1x64位存储。

权重cw取自共享的wrf26w,并对每个线程是相同的。事实证明,在诸如神经网络的应用中,存在许多需要将相同权重集与不同数据相乘(例如卷积的一部分)的情况。例如,神经网络中一些节点可包括完全相同的权重但不同的连接。例如,每个内核k(m=0...m)可表示特征(例如边缘或形状)与输入数据(例如图形像素的面积或体积)的卷积。因此,对应于这些内核的工作者线程不需要独立的权重。反而,仅提供了由监督者拥有的权重状态的一个拷贝(copy)。因此,来自共享权重寄存器文件的共享线程操作数的使用有利地需要较少用于权重的寄存器空间。图12示出了对于每个16元素输入向量,循环产生8个输出值(每个内核1个输出值)。在这特定情况下,这些输出值每个是32位的。上述循环每4个周期处理16个输入值(每个指令4xf16输入值)。为了维持该输入速度,于是处理器4每4个周期循环产生8x32位值,即每个循环4x64位存储,或每个周期1x64位存储。

在实施例中,奇数累加器$aacc[1]、$aacc[3]......$aacc[15]用于交错(stagger)结果(rx),并对部分和输入(px)进行相同操作。每次从后面向引擎馈送两个部分输入,到累加寄存器$aacc[13]和$aacc[15]中。这些值在每个周期向前移,因此在这情况下移到$aacc[11]和$aacc[9]中。当它们到达目的地amp单元,它们移动到偶数累加器中,而不是移动到奇数累加器中以准备进行累加。因此,{$aacc[15],$aacc[13]}->{$aacc[11],$aacc[9]}->{$aacc[7],$aacc[5]}->{$aacc[2],$aacc[0]}。

图13和14示出可受惠于本文所述类型的加载-存储指令的另一种算术指令,即卷积指令,其卷积经由相应线程的arf26a流入的输入数据与来自共同权重寄存器文件(wrf)26w的2d权重集。在实施例中,该指令可以采用半精度浮点向量细长卷积(slic指令)的形式,例如″f16v4slic″,指的是它以f16值的4元素子向量操作。它具有一个半精度和一个单精度输入,以及单精度输出。slic是类似的,并使用相同硬件作为amp。然而,该指令对于2个内核中的每一个执行1x4x4卷积(这是真正的卷积),而不是对于8个内核中的每一个执行1x1x16累加点积。事实上,在实施例中,可以配置为执行1xnx4卷积,其中n是2、3或4。

对于工作者上下文之间的权重共享是适当的情况,累加矩阵积(“amp”)和细长卷积(“slic”)指令促进高性能乘法累加序列。在实施例中,amp和slic指令可以用单精度和半精度数字格式支持,并以

相同的基本方式操作。共同计算配置状态(包括wrf26w中的共享权重)首先由监督者上下文初始化。然后,处理两个输入数据流:输入启动(像素)数据,以及指定后续乘法累加序列的初始值的部分和值(对于卷积,这些是部分计算的输出像素/启动)。产生了单一输出数据流:所得的、累加的部分和值。在最终部分和结果作为输出呈现之前,每个部分和输入值经历固定长度的一系列乘法累加操作。许多点积和累加操作并行地发生,由计算引擎执行。第一被乘数由输入数据流提供,第二被乘数由共同计算配置状态提供。

下表列出了一些示例性amp和slic指令变型,任何或所有这些变型可以在实施例中包括在处理器的指令集中。

注意:对于一些类型的指令,权重的位置是完全隐含的,但对于其他类型的指令,它们采用选择wrf中使用多个不同组中的哪个组的操作数。例如,f16v4sisoslic指令仅需要f16v4sisoamp的权重状态的四分之一。因此,软件允许预加载至4个权重集。权重集的选择由立即操作数的2位指定。另一方面,对于f16v4sisoamp,这采用完全权重状态,因此当中没有选择。

应当理解,仅通过示例方式描述了上述实施例。

例如,本公开的范围是上述架构,其中为监督者线程提供独立的上下文,或者其中监督者线程在时隙中运行然后将其时隙放弃给工作者。监督者可以改为使用通用上下文。或者,在另一布置中,监督者可以在其自己的专用时隙中运行。此外,实现方式不限于甚至具有监督者角色的特定一个线程。此外,本公开的范围不限于处理器4是瓦片阵列中的瓦片。在替代实施例中,处理器4可以例如是独立处理器或单芯片处理器。

执行单元18的实现方式不限于独立的主要执行单元18m和辅助执行单元18a;也不限于独立的mrf和arf。通常,寄存器可以来自任何一个或多个寄存器文件,这些寄存器文件可以在不同的存储器访问和算术操作之间共享,或者是独立的。

使用共享权重寄存器文件的算术指令不限于矩阵积或卷积指令。更一般地,共享权重寄存器文件可用于任何类型的算术指令或指令的组合,例如非累加矩阵积指令,其中以独立指令或通用代码,或卷积以外的其他矩阵乘法序列完成累加,先前积的结果不一定是后续积的输入。其他示例可包括向量点积或累加向量点积指令,即,算术指令不需要并行地应用m个不同的内核。

此外,本公开的范围不限于以上通过示例的方式公开的特定寄存器大小、端口位宽、端口数量、值精度、向量大小或矩阵大小。其他寄存器和端口位宽是可能的,其他精度值和其他向量或矩阵大小(例如就元素数量而言)也是可能的。此外,在其他实现方式中,以其他方式将两个加载地址和一个存储地址包入两个寄存器中是可能的,例如将三个10位地址包入两个16位寄存器中,或将三个42位地址包入两个64位寄存器中。此外,加载地址和存储地址不一定具有相同长度。此外,在替代实现方式中,以其他方式将步长值包入步长寄存器中也是可能的,例如将四个8位步长字段包入32位寄存器中等。

在另一个变型中,本公开的应用性不限于图像处理。这里使用的术语“内核”可以表示应用为包括诸如向量乘法、矩阵乘法或卷积之类的操作或其他操作(例如相关(correlation))的任何过程的一部分的任何权重矩阵。此外,应用能力不限于3d体积的数据。输入数据(和内核)可以是线性或2d的,或者具有更大的多维度(>3个自变量或自由度)。此外,本公开的范围不限于机器学习应用。存在许多其他应用,其中可能期望以共同于并发线程之间的一个或多个操作数和特定于每个线程的一个或多个操作数的组合执行操作。

一旦给出本文的公开内容,所公开技术的其他变型或用例对于本领域技术人员而言将变得显而易见。本公开的范围不由所描述的实施例来限定,而是仅由所附权利要求来限制。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1