CN102314342B - 用于数据并行编程模型的编译器生成的调用存根 - Google Patents
用于数据并行编程模型的编译器生成的调用存根 Download PDFInfo
- Publication number
- CN102314342B CN102314342B CN201110177689.1A CN201110177689A CN102314342B CN 102314342 B CN102314342 B CN 102314342B CN 201110177689 A CN201110177689 A CN 201110177689A CN 102314342 B CN102314342 B CN 102314342B
- Authority
- CN
- China
- Prior art keywords
- function
- kernel
- independent variable
- field
- calculates
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Active
Links
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/40—Transformation of program code
- G06F8/41—Compilation
- G06F8/45—Exploiting coarse grain parallelism in compilation, i.e. parallelism between groups of instructions
Abstract
在此描述的是用于生成用于数据并行编程模型的调用存根以使得用静态编译的高级编程语言编写的数据并行程序可以比传统方法更加声明性、可重用和可移植的技术。借助于所描述的技术中的某一些,由编译器(116)生成调用存根(118),且那些存根将数据并行计算的逻辑排列桥接到用于数据并行计算的目标数据并行硬件的实际物理排列。
Description
技术领域
本发明一般涉及数据并行编程,尤其涉及用于数据并行编程模型的编译器生成的调用存根。
背景技术
在数据并行计算中,并行性起源于跨多个同时分离并行计算操作器或节点而分布大的数据集。作为对比,任务并行计算涉及跨多个同时分离并行计算操作器或节点而分布多个线程的执行。通常,硬件被具体地设计为执行数据并行操作。因此,数据并行程序是为数据并行硬件专门编写的程序。传统上,数据并行编程要求理解数据并行概念的非直观本质并密切熟悉所编程的具体数据并行硬件的高度熟练的程序员。
在超级计算的领域之外,数据并行编程的常见用途是图形处理,这是因为这样的处理是规则的、数据密集的,且可以获得专用的图形硬件。尤其,图形处理单元(GPU)是被设计为从计算机的主中央处理单元(CPU)分担复杂的图形渲染的专用多核处理器。多核处理器是其中核的数量足够大以致传统的多处理器技术不再有效的处理器——此阀值在几十个核的范围内的某处。尽管多核硬件并不必定与数据并行硬件相同,但数据并行硬件可以通常被认为是多核硬件。
其他现有的数据并行硬件包括可从现代主要处理器生产商获得的x86/x64处理器中的单指令多数据(SIMD)、流化SIMD扩展(SSE)单元。
典型的计算机历史上是基于不是专门设计或能够承担数据并行性的传统单核通用CPU。因此,用于传统CPU的传统的软件和应用程序并不使用数据并行编程技术。然而,传统的单核通用CPU正被多核通用CPU代替。
尽管多核CPU能够承担数据并行功能,但很少利用这样的功能。由于传统的单核CPU不能够承担数据并行,大多数程序员不熟悉数据并行技术。即使程序员感兴趣,仍然存在程序员完全地理解数据并行概念和学习足够多以便充分熟悉多核硬件以实现那些概念的大的障碍的需要。
如果程序员清除了那些障碍,他们必须为他们希望他们的程序在其中运行的每一特定的多核硬件配置重新创建这样的编程。也就是说,因为常规的数据并行编程是硬件专用的,对一个数据并行硬件有效的特定解决方案将并不必定对另一数据并行硬件有效。由于程序员为具体的硬件编程他们的数据并行解决方案,程序员面临不同的硬件引起的兼容性问题。
目前,不存在允许普通程序员执行数据并行编程的被广泛地采纳的、有效的和通用的解决方案。普通程序员是不完全理解数据并行概念且不密切熟悉每一不兼容的数据并行硬件场景的程序员。此外,不存在允许程序员(普通的或不不普通的)可以聚焦于正被编程的应用程序的高级逻辑而非聚焦于目标硬件级的具体实现细节的现有解决方案。
发明内容
在此描述的是用于生成用于数据并行编程模型的调用存根以使得以静态编译的高级编程语言编写的数据并行程序可以比传统方法更加声明性、可重用和可移植的技术。借助于所描述的技术中的某一些,由编译器生成调用存根,且那些存根将数据并行计算的逻辑排列桥接到用于该数据并行计算的目标数据并行硬件的实际物理排列。
在所描述的一些其他技术中,编译器映射由数据并行函数的单元数据并行计算(即,“内核”)期望的给定输入数据。
提供本发明内容以便以简化形式介绍下面在具体实施方式中进一步描述的一些概念。本发明内容不旨在标识所要求保护的本主题的关键特征或必要特征。例如,术语“工具”可以指上述上下文和通篇文档所准许的设备、系统、方法、和/或计算机可读介质。
附图说明
参考附图描述具体实施方式。附图中,附图标记最左边的数位标识该附图标记首次出现的图。在各附图中,使用相同的附图标记来指示相同的特征和组件。
图1示出可用于实现在此描述的用于数据并行编程模型的技术的示例计算环境。
图2和图3是一个或多个示例过程的流程图,每一流程图实现在此描述的技术中的某一些,尤其是涉及数据并行编程模型的那些技术。
图4和图5是一个或多个示例过程的流程图,每一流程图实现在此描述的技术,包括涉及用于数据并行编程模型的编译器生成的调用存根的那些技术。
具体实施方式
在此描述的是用来生成用于数据并行编程模型的调用存根以使得用静态编译的高级编程语言编写的数据并行程序可以比传统的方法更加声明性、可重用和可移植的技术。借助于所描述的技术中的某一些,编译器生成调用存根,且那些存根将数据并行计算的逻辑排列桥接到用于该数据并行计算的目标数据并行硬件的实际物理排列。换言之,调用存根桥接将通用化和逻辑数据并行实现(例如,数据并行程序)之间的间隙桥接到具体的和物理的数据并行实现(例如,在数据并行硬件中)。在一些所描述的技术中,编译器生成将给定的输入数据映射到数据并行函数的单元数据并行计算(即,“内核”)所期望的那些数据的代码。
为达到一定程度的硬件无关性,各实现被描述为可以扩展为支持数据并行编程的通用编程语言的一部分。C++编程语言是在此描述的此类语言的主要示例。C++是静态类型的、自由形式的、多风格的编译性通用编程语言。C++可以也被描述为命令式的、过程式、面向对象的和泛型的。C++语言被认为是中级编程语言,这是因为它包括高级和低级语言特征两者的组合。本发明的概念不限于以C++编程语言的表达式。相反,C++语言可用于描述本发明的概念。可以使用的一些替换编程语言的示例包括JavaTM、C、PHP、Visual Basic、Perl、PythonTM、C#、Ruby、Delphi、Fortran、VB、F#、OCaml、Haskell、Erlang和JavaScriptTM。也就是说,所要求保护的本主题中的某一些可以覆盖以C++类型语言、命名法和格式的具体编程表达式。
所描述的实现中的某一些提供了将软件开发者置于对与数据并行资源的交互的许多方面的显式控制中的基本编程模型。开发者分配数据并行存储器资源并启动访问该存储器一系列数据并行调用点。在非数据并行资源和数据并行资源之间的数据传递是显式的且通常是异步的。
所描述的实现提供了与以下各项的深度集成:可编译的通用编程语言(例如,C++),以及适合根据问题域实体(例如,多维数组)而非硬件或平台域实体(例如,将偏移量捕捉到缓冲器中的C指针)来表达解决方案的抽象级。
可以在诸如使用多核处理器或x64处理器中的SSE单元的那些数据并行硬件等的数据并行硬件上实现所描述的实施方式。可以在互连计算机的群集上实现一些所描述的实施方式,互连计算机中的每一个可能具有多个GPU和多个SSE/AVXTM(高级矢量扩展)/LRBniTM(Larrabee新指令)SIMD和其他数据并行协处理器。
以下共同所有的美国专利申请通过引用合并于此,并构成本申请的以部分:于2010年6月18日提交的美国专利申请第12/918,097号,[其标题为:“数据并行编程模型”,于与本申请相同的日期提交,且具有共同的发明人权]。
示例计算基础设施
图1示出可以实现在此描述的技术的示例计算机体系结构100。体系结构100可以包括至少一个计算设备102,计算设备102可以经由网络104被耦合在一起以便与其他设备形成分布式系统。尽管不示出,但用户(通常是软件开发者)可以在编写数据并行(“DP”)程序的同时操作计算设备。也不示出的是,计算设备102具有输入/输出子系统,例如键盘、鼠标、监视器、扬声器等等。其间,网络104表示相互连接的充当单个大型网络(例如,因特网或内联网)的多中不同类型的网络中的任何一个或组合。网络104可以包括基于线缆的网络(例如,有线电视网络)和无线网络(例如,蜂窝式网络、卫星网络等等)。
这一示例计算机体系结构100的计算设备102包括存储系统106、非数据并行(非DP)主机110和至少一个数据并行(DP)计算引擎120。在一个或多个实施方式中,非DP主机110运行通用的多线程的和非DP的工作量,且执行传统的非DP计算。在替换实施方式中,非DP主机110能够执行DP计算,但不能够执行所述DP编程模型所聚焦的计算。主机110(无论是DP或非DP)控制DP计算引擎120。主机110是操作系统(OS)运行在其上运行的硬件。尤其,主机在它正执行代码时提供OS进程和OS线程的环境。
DP计算引擎120执行DP计算和其他DP功能。DP计算引擎120是被优化为用于执行数据并行算法的硬件处理器抽象。DP计算引擎120也可以被称为DP设备。DP计算引擎120可以具有不同于主机的存储器系统。在替换实施方式中,DP计算引擎120可以与主机共享存储器系统。
存储系统106是用于存储程序和数据的位置。存储系统106包括计算机可读介质,例如但不限于磁存储设备(例如,硬盘、软盘、磁条)、光盘(例如,紧致盘(CD)、数字多用盘(DVD))、智能卡和闪速存储器设备(例如,卡、棒、密钥驱动器)。
非DP主机110表示非DP计算资源。那些资源包括例如一个或多个处理器112和主存储器114。驻留在主存储器114中的是编译器116和一个或多个可执行程序,例如程序118。编译器116可以是例如包括在此描述的实现的用于通用编程语言的编译器。更具体地,编译器116可以是C++语言编译器。调用存根118可以是来自编译器116的中间结果。调用存根118可以是例如以HLSL(高级着色语言)、C++或诸如通用中间语言(CIL)等的另一中间表示生成的代码。取决于编译模型是静态的还是动态的,在程序执行的同时调用存根118可以驻留在存储器中。对于静态编译模型,这些存根可以与内核函数组合起来,并变成设备可执行的,在这一情况中,在进行编译之后,这些存根的中间形式可以不驻留在存储器中。在动态编译模型中,编译本身程序执行的部分;因此,在程序正执行的同时,中间存根可以驻留在存储器中。动态编译器可以将它与对应的内核函数组合,以便在运行时产生设备可执行指令。调用存根是设备可执行程序的入口点(在微软的应用程序编程界面的DirectX平台上被称为着色器)。可以为每一并行调用点生成各存根。各存根基于物理线程索引和逻辑计算域计算每一并行活动的逻辑索引(即,它桥接了逻辑排列和物理排列)。然后,各存根经由投影或广播中的任一个将在并行调用点(例如,forall调用点)处提供的自变量映射到所调用的内核函数所期望的参数,并最终调用该内核函数。各存根包括用不同的输入数据和逻辑计算域为给定的并行调用定制内核函数。
另一方面,程序119可以至少部分地是从编译器116的编译所得到的可执行程序。编译器116、调用存根118和程序119是计算机可执行指令的模块,计算机可执行指令是可以在计算机、计算设备或计算机的处理器上执行的指令。尽管在这里被示出为模块,但组件可以被具体化为硬件、软件或其任何组合。而且,尽管在这里被示出为驻留在计算设备102上,但组件可以跨分布式系统中的多个计算设备而分布。
或者,可以把调用存根118看作是可执行程序119的一部分。
DP计算引擎120表示具有DP功能的计算资源。在物理层面上,具有DP功能的计算资源包括能够执行DP任务的硬件(例如GPU或SIMD及其存储器)。在逻辑层面上,具有DP功能的计算资源包括被映射到例如执行DP计算的多个计算节点(例如,122-136)的DP计算。通常,每一计算节点在能力方面是彼此相同的,但是每一节点被分离地管理。类似于图,每一节点具有其自己的输入和其自己的所期望的输出。节点的输入和输出的流是去往/来自非DP主机110或去往/来自其他节点。
计算节点(例如,122-136)是DP硬件计算资源的逻辑排列。逻辑上,每一计算节点(例如,节点136)被排列为具有其自己的局部存储器(例如,节点存储器138)和多个处理元素(例如,元素140-146)。节点存储器138可以被用来存储是节点的DP计算的一部分且可以保存以往的一次计算的值。
通常,节点存储器138分离于非DP主机110的主存储器114。计算引擎120的DP计算操纵的数据语义上分离于非DP主机110的主存储器114。如箭头150所指示,显式地将来自主存储器114中的通用(即,非DP)数据结构的各值复制到与DP计算引擎120相关联的数据的聚集(数据的聚集可以被存储为像节点存储器138那样的局部存储器的集合),且显式地从与DP计算引擎120相关联的数据的聚集复制来自主存储器114中的通用(即,非DP)数据结构的各值。数据值到存储器位置的详尽映射可以受系统的控制(正如由编译器116指导的),这将允许在存在充足的存储器资源时开发并行性。
处理元素中的每一个(例如,140-146)表示DP内核函数(或简单地称为“内核”)的性能。内核是要执行的基本数据并行任务。
操作输入数据集的内核被定义为字段。字段是所定义的基本类型的数据的多维聚集。基本类型可以是例如整数、浮点数、布尔或可用在计算设备102上的任何其他类别的值。
在这一示例计算机体系结构100中,非DP主机110可以是带有其存储器的传统单核中央处理器单元(CPU)的一部分,且DP计算引擎120可以是在分立外围组件互连(PCI)卡上或在与CPU相同的板上的一个或多个图形处理单元(GPU)。GPU可以具有分离于CPU的存储器空间的局部存储器空间。因此,DP计算引擎120具有其自己的局部存储器(如每一计算机节点的节点存储器(例如,138)所表示的),该局部存储器分离于非DP主机本身的存储器(例如,114)。借助于所描述的实现,程序员拥有对这些分离的存储器的访问权。
替代示例计算机体系结构100,非DP主机110可以是多个CPU或GPU中的一个,其DP计算引擎120可以是剩余的CPU或GPU中的一个或多个,其中CPU和/或GPU在相同的计算设备上或在群集中操作。或者,多核CPU的核可以构成非DP主机110和一个或多个DP计算引擎(例如,DP计算引擎120)。
借助于所描述的实现,程序员拥有使用熟悉的主流的函数调用的语法以及概念和传统的非DP编程语言(例如C++)来借助于支持DP的硬件创建DP功能的能力。这意味着普通程序员可以编写将传统的不支持DP的硬件(例如,非DP主机110)的操作用于任何支持DP的硬件(例如,计算引擎120)的程序。至少部分地,可执行程序118表示由普通程序员编写且由编译器116编译的程序。
程序员为DP功能编写的代码在语法、命名法和方法上类似于为传统的非DP功能编写的代码。更具体地,程序员可以使用传递用于函数的数组变量的熟悉的概念来描述用于DP计算的基本函数的规范。
根据所描述的实现产生的编译器(例如,编译器116)处理用于在支持DP的硬件上实现DP功能的许多细节。换言之,编译器116生成将DP计算引擎120的逻辑排列映射到物理DP硬件(例如,具有DP功能处理器和存储器)的代码。因此,程序员不需要考虑DP计算的所有特征来捕捉DP计算的语义。当然,如果程序员熟悉可以在其上运行程序的硬件,则该程序员仍然具有指定或声明如何执行特定操作和如何处理其他资源的能力。
另外,程序员可以使用熟悉的数据集大小的观念来推断资源和成本。超出认知的熟悉性,对于软件开发者,这种新方法允许在非DP主机110和DP计算引擎120之间的类型和操作语义的公共规范。这种新方法简化了产品开发并使得DP编程和功能更平易近人。
借助于这种新方法,介绍这些编程概念:
●字段:预先定义的维度和元素数据类型的数据的多维聚集。
●索引:被用来索引数据的聚集(例如,字段)多维向量。
●网格:索引实例的聚集。具体地,网格指定多维矩形,多维矩形表示在该矩形中的所有索引实例。
●计算域(例如,网格):描述可以请求数据并行计算的所有可能的并行活动的索引实例的聚集。
●DP调用点函数:为四个DP调用点函数定义语法和语义;即,forall、reduce、scan和sortforall。
字段
在为传统的非DP硬件编程时,软件开发者常常定义包含应用程序数据的用户数据结构,例如列表和字典。为了使得从数据并行硬件和功能可能获得的好处最大化,新的数据容器给DP程序提供容纳的方式,且是指程序的数据的聚集。DP计算操作被称为“字段的这些新的数据容器。
字段是DP代码操纵和变换的通用数据数组类型。它可以被看作是指定的数据类型(例如,整数和浮点数)的元素的多维数组。例如,浮点数的一维字段可以被用来表示稠密浮点数向量。颜色的二维字段可以被用来表示图像。
更多具体地,令float4是表示在计算机监视器上的像素的红、绿、蓝和图形保真值的4个32位浮点数的向量。假定监视器具有分辨率1200x1600,则:
field<2,float4>screen(grid<2>(1200,1600))是用于屏幕的好模型。
字段不需要是定义的矩形网格。尽管通常在是仿射的索引空间上定义它,在它是多边形和多面体(polyhedral)或多面体(polytope)的意义上——即是说,它被形成为以下形式的有限数量空间的交集:
f(x1,x2,...,xn)>=c
其中x1,x2,...,xn是N维空间中的坐标且‘f’是这些坐标的线性函数。
字段被分配在具体的硬件设备上。在编译时定义它们的基本类型和维数,同时在运行时定义它们的范围。在一些实现中,字段的指定的数据类型可以是整个字段的统一类型。字段可以以此方式表示:field<N,T>,其中N是数据的聚集的维数且T是基本数据类型。具体地,字段可以由类的这一通用家族来描述:
伪代码1
字段被分配在具体的硬件设备基础(例如,计算设备102)上。在编译时定义字段的基本类型和维数,同时在运行时定义它们的范围。通常,字段充当数据并行计算的输入和/或输出。而且,通常,这样的计算中的每一并行活动负责计算输出字段中的单个元素。
索引
字段中的维数也被称为字段的秩。例如,图像具有为2的秩。字段中的每一维具有下界和范围。这些属性定义允许作为在给定的维度处的索引的数字的范围。通常,在C/C++数组中是这样的情况,下界默认为0。为了获取或设定字段中的特定元素,使用索引。索引是N元组,其中其组建中的每一个落在由对应的下界和范围值所建立的界限内。索引可以如下表示:索引<N>,其中索引是大小为N的向量,它可以被用来索引秩为N的字段。有效的索引可以以此方式定义:
valid index={<i0,...,iN-1>|where ik>=
lower_boundk and ik<lower_boundk+extentk}
伪代码2
计算域
计算域是描述数据并行设备在执行内核的同时必须实例化的所有可能的并行线程的索引实例的聚集。计算域的几何形状与正处理的数据(即字段)强相关,这是由于每一数据并行线程做出关于它负责处理字段的什么部分的假设。通常,DP内核将具有单个输出字段且该字段的底层网格将被用作计算域。但是在每一线程负责计算16个输出值时它也可以是网格的一部分(例如1/16)。
抽象地,计算域是对象索引值的集合的描述。由于计算域描述数据的聚集(即,字段)的形状,它也描述用于对数据的聚集迭代的隐含循环结构。字段是其中每一变量与某一域中的索引值的一一对应的变量的集合。字段被定义在域上,且逻辑上具有用于每一索引值的标量变量。在此,计算域可以简单地被称为“域”。由于计算域指定字段的每一维度的长度或范围,它也可以被称为“网格”。
在典型的场景中,索引值的集合简单地对应于多维数组索引。通过将索引值的规范分解为分离的概念(被称为计算域),可以跨多个字段使用该规范,且可以附加附加的信息。
网格可以被这样表示:grid<N>。网格描述字段或循环嵌套的形状。例如,可以用二维网格描述在外部循环从0运行到N且然后在内部循环从0运行到M的双重嵌套循环,且第一维度的范围从0(包括在内)跨到N(不包括在内),且第二维度的范围为在0和M之间。网格也被用来指定字段的范围。网格不持有数据。它们仅描述它的形状。
基本域的示例是整数运算序列的叉积。运算序列被存储在这一类中:
伪代码3
这表示值的集合{lb+i*stride|0≤i<extent}。这些集的叉积被称为网格,其中集的数量被称为网格的秩。网格可以由以它们的秩区分的类型家族来表示。
伪代码4
说到这里,各种构造器已经被省略,且各种构造器是专业特异的。域的秩或维数是该类型的一部分,因此可以在编译时获得它。
资源视图
resource_view表示在给定的计算设备上数据并行处理引擎。compute_device是物理数据并行设备的抽象。在单个compute_device可以存在多个resource_view。事实上,resource_view可以被看作是执行的数据并行线程。
如果不显式地指定resource_view,则可以创建默认的resource_view。在创建默认值之后,在其上隐含地需要资源视图的所有将来的操作系统(OS)线程将获取先前所创建的默认值。可以从不同的OS线程使用resource_view。
同样借助于这种新方法,资源视图允许在计算引擎120的上下文内指定和强加诸如优先级、最后期限调度和资源限制等的概念。域构造器可以可选地由资源视图参数化。这标识要用来持有数据的聚集的一组计算资源并执行计算。这样的资源可以拥有私有存储器(例如,节点存储器138)以及与非DP主机110的主存储器114非常不同的特性。作为逻辑构建,计算机引擎是指这一资源集。在此简单地将其看作是不透明类型:
typedef...resource_view;
伪代码5
DP调用点函数
借助于这种新方法,DP调用点函数调用可以被应用到与支持DP的硬件(例如,计算引擎120)相关联的数据的聚集以便描述DP计算。所应用的函数被注释为允许在DP上下文中使用。函数可以本质上是标量,这是因为期望它们使用和产生标量值,尽管它们可以访问数据的聚集。在并行调用中各函数被基本地应用到至少一个数据的聚集。在某种意义上,函数指定循环的主体,其中从数据的结构推断循环结构。到该函数一些参数只是被应用到数据的元素(即,流化),尽管对于索引访问(即,非流化)来说数据的聚集也可以像数组一样被传送。
DP调用点函数将被称为内核的可执行代码片段应用到由计算域表示的每一虚拟的数据并行线程。此代码片段被称为“内核”,且是计算节点的每一处理元素(例如,140-146)执行的内容。
在此描述的是表示四个不同的DP原语的四个不同的具体DP调用点函数的实现:forall、reduce、scan和sort。所描述的DP调用点函数中的第一个是“forall”函数。使用forall函数,程序员可以用单次函数调用生成DP嵌套循环。嵌套循环是其中一个循环位于另一循环体内的逻辑结构。以下是嵌套循环的示例伪代码:
for(int i=0;i<N;i++)
for(int j=0;j<=i;j++)
x(i,j)=foo(y(i,j),z(i,j));
…
伪代码6
在上面的嵌套循环的传统的串行执行中,外部循环(即i循环)的第一迭代引起执行内部循环(即j循环)。因此,对于i循环的每一迭代,在内部j循环中的示例嵌套函数“foo(y(i,j),z(i,j))”连续地执行j次。代替串行执行以传统的方式编写的嵌套循环代码,该新方法提供被称为“forall”的新的DP调用点函数,在“forall”被编译和被执行时,逻辑上并行执行嵌套函数的每一迭代(例如,“foo(y(i,j),z(i,j))”)(这被称为“内核”)。
完美的循环嵌套是使得存在单个外部循环语句且每一循环体准确地是一个循环或是非循环语句的序列的循环的集合。仿射循环嵌套是使得存在单个外部循环语句和每一循环体是可能的循环语句的序列的循环的集合。在循环归纳变量中,仿射循环中的每一循环的界限是线性的。
DP调用点函数forall的至少一个实现被设计为将仿射循环嵌套映射到数据并行代码。通常,以外部循环开始且只要接下来的循环是完美的就继续的仿射循环嵌套的一部分被映射到数据并行计算域,且然后,仿射嵌套的剩余部分被放置到内核中。
在这里示出forall函数的伪代码格式:
伪代码7
对于由域“d”指定的每一索引,此函数调用的基本语义将来自对应于的字段的元素的自变量评估函数“foo”,就像在原始循环中一样。
这是forall函数的伪代码的替换格式:
伪代码8
在上面的示例伪代码中,forall函数被示出为由λ操作符“[=]”指示的λ表达式。λ表达式是可以构建表达式和语句的匿名函数且可以被用来创建委托或表达式树类型的匿名函数。
另外,使用传值来修改双精度“y”和“z”的效果具有好处。在程序员以此方式标记自变量时,它将变量映射到只读存储器空间。因此,程序可以更快和更高效地执行,这是由于被写到该存储器区域的值维持它们的完整性,尤其在被分布到多个存储器系统时。因此,使用此“const”标签或另一等效标签,程序员可以在不存在对写回到该存储器区域中的需要时提高效率。
在此描述另一具体的DP调用点函数是“reduce”函数。使用reduce函数,程序员可以计算非常大的值的数组的总和。在这里示出reduce函数的伪代码格式的两个示例:
伪代码9
在这些示例中,“f”映射到“result_type”的值。函数“r”组合此类型的两个实例并返回新的实例。它被假设为是关联的和可交换的。在第一种情况中,此函数被穷举地应用到对被存储在“result”中的单个结果值的归约。这一第二形式限于“网格”域,其中(由“dim”)选择一个维度,且通过归约来消除该维度,如上所述。同样地,经由函数“r”将“result_field”输入值与所生成的值组合。例如,此模式匹配矩阵乘累加:A=A+B*C,其中计算网格对应于基本元组的3维空间。
在此描述的又一个具体的DP调用点函数是“scan”函数。scan函数也被称为数据并行计算的“并行前缀”原语。给定值的数组,程序员可以使用scan函数来计算其中每一元素是输入数组中在它之前的所有元素的总和的新数组。在这里示出scan函数的示例伪代码格式:
伪代码10
在归约情况中,“DIM”自变量选择通过该数据的“线束”。“线束”是数据集的较低的维度投影。例如,考虑10X10的范围的二维矩阵。则,线束将是第五列。或考虑数据的三维立方体,则,线束将是在Y=Y0处的XZ平面。在归约情况中,该线束被减少为标量值,但是在这里该线束定义使用操作符“R”对其执行并行前缀计算的值的序列,操作符“R”在这里被假设为是关联的。这产生值的序列,然后值的序列被存储在“RESULT”的对应元素中。
在此描述的四个具体的DP调用点函数中的最后的函数是“sort”函数。这如此函数的名称所暗示的那样,程序员可以使用一个或多个已知的数据并行排序算法来排序大的数据集。sort函数由比较函数、要排序的字段和可以由比较引用的附加字段。在这里示出sort函数的示例伪代码格式:
伪代码11
如上所述,这一排序操作被应用到“DIM”维度中的线束并在其位置更新“SORT_FIELD”。
其他编程概念
基于DP调用点的自变量,DP调用点函数可以操作两种不同类型的输入参数:元素参数和非元素参数。因此,基于DP调用点生成的计算节点(例如,122-136)操作那两种不同类型的参数中的一种。
对于元素输入,计算节点操作单个值或标量值。对于非元素输入,计算节点操作数据的聚集或值的向量。也就是说,计算节点具有在数据的聚集中任意索引的能力。对DP调用点函数调用将具有是元素输入或非元素输入的自变量。这些DP调用点调用将生成逻辑计算节点(例如,122-136)基于值与相关联的函数的自变量。
一般地,元素计算节点的计算可以重叠,但是非元素计算机节点通常不这样。在非元素的情况中,将需要在任何节点访问数据的聚集中的任何特定元素之前在计算引擎存储器(例如,节点存储器138)中完全实现数据的聚集。因为基于非元素参数的数据的聚集可以递增地产生和使用,相比于使用元素输入参数,需要较少的存储器。
对于DP调用点函数,内核形式参数类型不必匹配传递进来的自变量的实际类型。假设实际类型是秩Ra的字段且计算域具有秩Rc。
1.如果形式的的类型不是字段,而是与实际的字段的基本类型相同的类型(模数常量和引用),则,当:
Ra=Rc
时存在有效的转换。
2.如果形式类型是秩Rf的字段(模数常量和引用),则,当:
Ra=Rf+Rc
时存在有效的转换。
3.为了完整起见,存在身份转换,其中形式类型和实际类型匹配:
Ra=Rf
作为示出转换1的示例,考虑借助于内核的向量加法:
_declspec(kernel)
void vector_add(double&c,double a,double b)
c=a+b;
}
DP调用点函数的实际参数是:
grid domain(1024,1024);
field<2,double>A(domain),B(domain),C(domain);
然后,调用点采取以下形式:
forall(C.get_grid( ),vector_add,C,A,B);
下列转换:
C->double&c
A->double a
B->double b
通过将整个字段聚集与内核vector_add的完全相同地对待而工作。换言之,对于域中两个索引中的每一个:
index<2>idx1,idx2
C[idx1]和C[idx2](分别是A[idx1]和A[idx2]、B[idx1]和B[idx2])在内核vector_add中被同等地对待。
这些转换被称为元素投影。如果内核不具有是字段的参数类型,内核被称为是元素的。元素的内核的优点中的一个包括可能竞争条件、死锁或活锁的完全缺失,这是因为在实际字段的任何元素的处理之间不做区分。
作为示出转换2的示例,考虑借助于内核的向量加:
伪代码12
DP调用点函数的实际参数是:
grid domain(1024,1024),compute_domain(1024);
field<2,double>A(domain),C(comput_domain);
然后,调用点采取以下形式:
forall(C.get_grid( ),sum_rows,C,A);
下列转换中:
C->double&c
A->const field<1,double>&a,
第一个是覆盖在转换1上的元素投影。对于第二个,内核sum_rows作用于A的元素的左边的索引,同时计算域填充正确的索引。换言之,对于compute_domain中给定的‘索引<1>idx’,sum_rows的主体采取以下形式:
这被称为部分投影,且优点之一包括在由计算域提供的索引汇中不存在共同并发缺陷的可能性。部分投影的一般形式使得内核作用于A的元素的索引的最右边的‘Rf’数字,且剩余的索引由计算域填充,因此要求:
Ra=Rf+Rc。
作为转换的稍微更复杂的示例,考虑:
伪代码13
借助于实际参数:
const int N,Rank_f;
int extents1[N],extents2[N+Rank_f];
grid domain(extents2),compute_domain(extents1);
field<2,double>A(domain),C(comput_domain);
然后,调用点采取以下形式:
forall(C.get_grid( ),sum_dimensions,C,A);
对于以下转换:
A->const field<rank_f,double>&a,
内核的体的一个解释包括:
伪代码14
稍微更复杂的示例是使用通信操作符转置和展形的矩阵乘法。
假定‘field<N,T>A,transpose<i,j>(A)是用维度j对换维度i的结果。例如,在N=2时transpose<0,1>(A)是正规矩阵转置:transpose<0,1>(A)(i,j)->A(j,i)。
另一方面,spread<i>(A)是在索引I处添加空维的结果,这将所有随后的索引向右平移一。例如,在N=2时,spread<1>(A)的结果是其中旧存储槽0保持相同但旧存储槽1被移动到存储槽2且存储槽1是空的三维字段:spread<1>(A)(i,j,k)=A(i,k)。
使用以下内核:
伪代码15
借助于实际参数:
grid domain(1024,1024);
field<2,double>C(domain),A(domain),B(domain);
然后,矩阵乘法是以下DP调用点函数:
伪代码16
inner_product内核在最左边的存储槽(即k)处作用于A和B,且计算域正确地填充两个存储槽。实质上,展形只是被用来保持索引操纵的清洁和连贯。
局部投影的最后的示例使用DP调用点函数‘reduce’来计算矩阵乘法。
例如,采取以下:
伪代码17
由于reduce作用于最左边的索引,转置和展形的使用与先前不同。解释是reduce<1>减少了计算域最左边的维度。
两个函数(即λ)被类似地用于map-reduce:
伪代码18
作为示出转换3的示例,令N=K+M,且考虑:
伪代码19
const int K,M,N;//N=K+M
int extents1[K],extents2[N];
grid domain(extents2),compute_domain(extents1);
field<2,double>A(domain),C(compute_domain);
伪代码20
然后,调用点采取以下形式:
forall(C.get_grid( ),sum_dimensions,C,A);
且所有转换都是身份转换。
在设备上创建存储器时,它原始地开始,且然后可以具有只读或读写的的视图。只读的优点之一包括在多个设备之间分解问题时(有时被称为核外(OUT-OF-CORE)算法)不需要检查只读存储器以便了解它是否需要更新。例如,如果设备1正操纵存储器块字段1,且设备2正使用字段1,则,不存在设备1检查是否字段1已经被设备2改变的需要。相似的图片适用于将存储器块用作字段的主机和设备。如果存储块是读写,则,在设备1和设备2上的动作之间将需要存在同步协议。
在第一次创建字段时,它只是原始存储器且并没有为访问做好准备;也就是说它还不具有‘视图’。在字段被传送到DP调用点函数处的内核时,参数类型的签名确定它是否将具有只读视图或读写视图(可以存在相同的存储器的两个视图)。
如果参数类型是传值或传址常量,则将创建只读视图,即是说,对于某种类型的‘element_type’
element_type x
field<N,element_type>y
const field<N,element_type>&z
read_only_field<field<2,element_type>>w
伪代码21
如果该参数类型是非常量引用类型,则将创建读写视图:
element_type&x
field<N,element_type>&y.
通过使用通信操作符,字段可以显式地被限制为只具有只读视图,其中它不具有读写视图,通信操作符为:
read_only
READ_ONLY操作符通过仅定义常量存取器和索引操作符以及下标操作符来工作,且因此:
read_only(A)
以引起写的方式被使用。尤其,如果被传送到内核中(通过DP调用点函数),则可以发生编译器错误。
例如,在一种实施方式中,以下之间将存在差别:
element_type x
field<N,element_type>y
const field<N,element_type>&z
以及
element_type&x
field<N,element_type>&y.
伪代码22
同时在另一实施方式中,以下之间将存在差别:
element_type x
read_only_field<field<2,element_type>>w
以及
element_type&x
field<N,element_type>y.
第一实施方式使用传值而非传址以及常量而不是非常量以便区分只读和读写。第二实施方式仅对元素形式参数使用传值而非传址,另外对字段形式参数,它使用READ_ONLY_field而非字段,以便以便区分只读和读写。第二实施方式的理由在于,在设备和主机具有不同的存储器系统时,引用实际上是引用谎言。
关于DP Forall函数的更多内容
forall函数是高度通用的DP原语。可以使用forall函数来起动DP活动的主机。编译器116将函数的调用扩展到准备数据结构的代码序列,且最终起动并行活动。编译器166也生成将起动点粘合到计算(即,forall函数的内核参数)的存根(例如,调用存根118),将物理线程索引映射到计算域中的当前并行活动逻辑索引,且如果内核函数请求就将这些专用的逻辑索引传递给内核函数,实现投影语义,并且最终调用内核函数。编译器116执行至少两个函数:
●编译器116将DP函数的调用(例如forall)扩展到准备必要的数据结构的非DP可执行的代码的序列(其将在非DP主机110上执行),且最终起动并行活动。
●编译器116也生成存根(即设备代码,例如HLSL)将起动点粘合到单元计算(DP函数的内核参数),实现投影语义和DP函数的特殊索引令牌以及目标设备的所有其他安装。
编译器116使得程序员免受这样的负担,并使得他们聚焦于编程程序本身的功能。另外,将此工作留给编译器开发出数据并行程序开发一次就在多个目标上运行的机会。也就是说,编译器可以为不同的目标生成不同的调用存根,且取决于运行时请求,使得运行时选择适当的存根。
以下是DP原语forall的伪代码的另一示例,且在这一示例中,用三个参数调用内核:
伪代码23
第一参数(“const grid<_Compute_rank>&_Compute_grid”)是计算域,它描述如何部署并行活动。也就是说,如何可以并行完成工作以及部署如何映射回到数据,等等。第二参数(“const_Callable_type&_Kernel”)内核,该内核是单元计算,且在并行中将被所有并行活动调用。其余的参数(Actual1,Actual2,Actual3)是对应于内核的参数的自变量。所描述的技术的至少一种实现在此聚焦于在这些forall自变量和内核的参数之间进行映射。
在此使用这些术语:
●参数秩。(即,类型的DP秩)这是第一模板自变量。例如,field<2,int>的秩是2。对于不同于字段的类型,其秩是0。
●实际参数秩(Ra)。被传送给DP函数的实际自变量的秩,例如forall(上面示例伪代码13中的Actual_type1~Actual_type3)。
●形式参数秩(Rf)。内核的形式参数类型的秩。
●计算秩(Rc)。在网格的实例被用作forall的第一参数时。例如,如果第一自变量的类型是grid<2>,则计算秩是2。
类型的DP秩引入被称为“可索引的类型”的概念,该概念是字段的泛化。可索引的类型是像字段那样具有秩(被命名为秩的编译时已知的静态常量成员)的类型,和实现操作符[]that采取an实例of索引<秩>as输入,和返回an元素值或引用。可选地,它可以实现完全的或局部投影函数。这样的类型的参数秩是给定的可索引的类型的秩。不可索引的类型的参数秩是0。
实际参数秩(Ra)并不必定与形式参数秩(Rf)相同。以下是只是添加两个值并将其和指派给第一参数的内核的简单示例:
_declspec(vector)void add(int&c,int a,int b)
{
c=a+b;
}
伪代码24
可以以这一方式中调用这一内核:
伪代码25
伪代码15的这一示例起动N个并行活动,每一并行活动添加分别来自两个向量(fA和fB)的一个元素,且将结果存储回到结果向量(fC)的对应存储槽。在这一示例中,Rc是1,Ra是(1,1,1)且Rf是(0,0,0),且编译器116生成将Ra桥接到Rf的粘合代码。编译器116标识当前并行活动在整个计算中位置,从fA和fB载入对应的元素,调用内核函数,并将结果存储fC的正确元素。
注意,对于不同的数据可以调用相同的内核。例如,程序员可以编写下列代码来调用对而非向量的加法计算:
伪代码26
不需要编译器116关心调用存根,程序员需要编写用于数据输入的每一可能的种类的核计算算法(在这里是add函数)的包装器或多次复制带有轻微不同的结构的相同算法。使得程序员免受此负担显著地改善了核内核代码的可重用性,且使得整个程序整洁得多和简洁得多。
当然,对于一些算法,每一内核需要看到整个输入数据以便执行所要求的计算,在这种情况中,Rf是与Ra相同的。在这一实例中,调用存根的任务只是标识当前并行活动的位置且然后,用所传递的参数调用内核。
有时,并行活动在整个并行部署中的位置是编程内核所需要的。在这一情况中,内核可以经由定义具有计算秩的相同秩的索引类型参数且在forall的对应参数位置处使用专用的令牌(例如,_index)来获取这一位置信息。另一备选方案涉及允许内核函数具有被提供给forall调用的自变量多一个的参数,且内核函数的第一参数必须是index<computerank>。在这一情况中,编译器将在存根中生成将逻辑索引(并行活动在整个并行部署中的位置)传递给内核函数的代码。
以下内核示例计算矩阵乘法的一个元素:
伪代码27
给定以上内核,程序可以调用类似于此来它(例如):
伪代码28
编译器116在表示当前并行活动的位置的调用存根中生成创建index<2>的正确实例的代码,并将它作为其第一自变量传递给mxm_kernel_naive。
可以使用的两个其他特殊索引令牌包括:“_tile_index”和“_local_index”。它们表示在平铺式计算域上调用内核时当前并行活动的位置。_tile_index给予当前并行活动所属于的平铺的索引,且_local_index提供当前并行活动在该tile内的位置。可以以与_index相似的方式使用这两个令牌,且如果在forall调用点请求它们中的任何之一,则编译器116在调用存根中生成代码以便适当地设置它们并将它们传递给内核。
或者,代替专用的令牌,可以使用新的类型index_group来封装所有可能的特殊索引、全局变量、本地变量或组。各令牌可以是隐含的forall自变量,且如果目标内核请求则各令牌将被编译器插入。
forall调用的实际的自变量是将被传递给目标计算引擎的数据。它们与内核的参数一一对应,但每一自变量的类型并不必定与其对应的参数类型相同。对forall,允许三个自变量种类:
●实例field<N,T>,其指示设备存储器上的存储器区域。这将被映射到设备资源,例如缓冲器。
●非字段类型数据结构,其将被传值复制到设备。在一些平台上,经由专用的常量编组机制而传送这样的数据。
●特殊索引令牌。这些令牌对应于当前并行活动在计算域中的位置。提供它们以使得程序员可以编写无需显式地被暴露给目标计算引擎的线程部署模型非元素内核。为使用_index,程序员将内核参数定义为是index<N>,其中N是计算域的秩,且在FORALL调用点的对应的自变量位置处使用所期望的令牌。_tile_index和_local_index被用于并行活动的tiled部署。
参数投影是DP函数(例如,forall)的实际的自变量的秩,且并不必定与其对应的内核参数的秩相同。如果Rf+Rc=Ra,则编译器生成使用给定的并行活动的位置信息来将给定的字段自变量投影到内核期望的适当的秩的代码。如果Rf+Rc>Ra,则进行自动平铺也是可能的。
线程部署策略和索引映射
在一些场景(例如,微软的DirectComputeTM平台)中,线程可以在三维度空间中分派,其中使用三个值来指定一组线程的形状,且使用三个附加的维度来指定通常被称为线程组的被调度在一起的线程的块的形状。
在生成调用存根时,编译器(例如,编译器116)选择线程部署策略,且它生成基于目标相关计算单元身份(在运行时计算单元身份是可用的,对编译器来说是不可访问的)标识(例如,映射)当前并行活动在计算域中的位置的对应的索引映射代码。作为这一活动的一部分,编译器拾取物理域来覆盖逻辑域并这样分派它。编译器也生成代码,该代码将由每一线程执行,将三维分块物理线程域中给定的点映射回到逻辑计算域中的点。
指导索引映射的选择一些考虑包括(作为示例而非限制):
●在映射应易于定义新的逻辑域和这些逻辑域到多样的物理域的映射的意义上,映射可以是容易地可扩展的。
●存在用于线程组的范围的推荐大小。例如,它们不应太小的(存在许多其他这样的大小考虑,且不是这一背景描述的话题。)。
●从物理到逻辑的逆映射应易于计算和优选地指导以使得:
a.在内核中的线程的实际计算的这一前奏中不耗费太多的时间。
b.在物理域和逻辑域之间的映射对编译器来说是可见的,以使得编译器可以允许优化,这取决于物理索引的用法。例如,如果使用整数变量i访问数组,则编译器知道i如何与物理域中的线程标识符相关是有益的。
●所调度的冗余线程的量被消除或为0。
●“覆盖”逻辑域所需要的平台API调用的次数是低的(或者,在理想情况是1比1)。
逻辑计算域是0基稠密(单元跨距)立方体形状的域,以范围E=<E0,..,EN-1>的N维非负向量为特征,以使得当且仅当对i的每一分量ij来说保持0<=ij<Ej时index i=<i0,...iN-1>是在该域中。例如,在二维的情况中,立方体简单地是带有锚固在<0,0>原点的角的矩形,且对于某种非负E0和E1,对角是在<E0,E1>处。在此,为简洁起见,立方体形状的域将被称为网格。
为帮助描述,我们使用在这一文档中使用以下记法:
·(Gz,Gy,Gx)——线程组的范围(Gx是最不重要的维度)
·(Tz,Ty,Tx)——每一线程组的范围(Tx是最不重要的维度)
·gid——SV_GroupID,(gid[0],gid[1],gid[2])是(Gz,Gy,Gx)中的点
·gtid——SV_GroupdThreadID,(gtid[0],gtid[1],gtid[2])是(Tz,Ty,Tx)中的点
·dtid——SV_DispatchThreadID,(dtid[0],dtid[1],dtid[2])是(Gz*Tz,Gy*Ty,Gx*Tx)中的点
存在用于在逻辑域和物理域之间映射的多种方法,下面提供这些方法。假定compute_grid的实例,即g。
方法1:网格的映射
线程分派:主机可以确定物理网格的维度以便因而分派(作为示例):
1.(Tz,Ty,Tx)=(1,1,256),可以基于场景而调谐可这一预定义的数字;
2.(Gz,Gy,Gx)=(1,1,div_ceil(g.total_elements(),256));如果Gx>MAX_GROUPS,则报告错误。伪代码可以类似于此(例如):
伪代码29
“div_ceil”采用两个整数a和b,且在C++整数math中执行(a+b-1)/b。换言之,它将各数字作为有理数字来除,并将结果上舍入到下一个整数。
索引映射代码生成:给定gid/gtid/dtid,将其展平到线性偏移,且然后,基于g的范围将它提高到N维逻辑域中的索引。伪代码可以类似于此(例如):
伪代码30
例如,如果计算网格是289X2050,则物理线程域可以被排列为:
(Tz,Ty,Tx)=(1,1,256)
(Gz,Gy,Gx)=(1,289,9)
SV_DispatchThreadID的维度将是(1,289,2304),它与带有一些额外点的逻辑计算网格几乎相同。现在给定在空间(1,289,2304)中的dtid(该变量名称通常是指DirectCompute三维线程ID),可以检测它是否在边界(289,2050)内(忽略dtid[DimZ],这是由于在这一情况中它是0)。如果它确实在边界内,则dtid可以被直接地用作逻辑域中的索引而无需任何索引展平和提高(在处理逻辑域和物理域之间的维度排序的差异之后)。除了节省一些数学操作的成本之外,该二维物理ID也可以较好捕捉在二维线程网格和程序访问的二维数据结构之间的关系。这对向量机中的代码生成和编译时边界检查来说是相关的。
方法2:为秩1、2和3优化
线程分派:主机可以确定物理网格的维度以便因而分派(作为示例):
1.(TZ,TY,TX)=(1,1,256),可以基于场景调谐这一预定义数字。在这里假设这些范围是通过恒定向量THREAD_GROUP_EXTENTS传送的。
2.如果秩是1、2和3,则试图将物理域中的相同维数用作逻辑域。分派决定(GZ,GY,GX)经由PHYSICAL_GROUP_GRID被传送出去。伪代码可以类似于此(例如):
伪代码31
注意如果N<=3get_dispatch_extents2如何试图将每一逻辑维度映射到对应的物理维度。如果这是不可能的,方法跨三个物理维度“展形”整个所要求的组的集(由变量“total”捕捉)。Gz,Gy,Gx的值(它们是被存储在输出数组physical_group_grid中的值)被选择为接近必要的各组的总数的立方根。Gz、Gy和Gx的积可以实际上大于所要求的组的数量。通过使用首先舍入(在Gz进行)来进一步除以剩余的组的数量以便调度的结果,可以对“浪费”组的数量进行归约。这可以得到用于Gy且随后用于Gx的稍低的剩余值。
这只是以下一般任务中的优化的一种形式:
查找G的值以使得
每一Gi<MAX_GROUPS
Gz*Gy*Gx>=所要求的组的总数
Gz*Gy*Gx是最小值
使得Gz*Gy*Gz等于(准确地)“总数”是的完全匹配是最优的结果,但是这样的因素并不总是存在(例如如果“总数”是质数)。一般地,总数的值越大,运行时就越乐意视图优化Gz,Gy,Gx的选择。然而,借助于MAX_GROUPS等于64K且基于来自上述方法的基于立方根的解,浪费组的量是零点几个百分比。因此,立方根方法可用于实践目的。
给定用于确定调度网格的维度的上述的代码,这是存根如何从物理索引恢复逻辑索引。给定gid/gtid/dtid,基于秩N,且给定上面选择哪种调度策略(直接映射还是非直接映射),生成不同的索引计算代码。
情况1:N==1,直接地映射:
伪代码32
情况2:N==2,直接地映射:
伪代码33
情况3:N==3,直接地映射:
伪代码34
情况4:间接地映射,对于任何N:
伪代码35
方法“flatten”是提高的互逆,它从给定的网格中的点平移到整数范围[0,总的元素)中的线性偏移。在这里是其定义:
伪代码36
方法3:在max(Gx,Gy,Gz)>=64K时多次内核调用
在方法#2中,物理维度匹配逻辑维度以使得对于秩=1、2和3索引映射是直接的,除非一个或多个维度需要展形。直接映射一般地更为有效,且较好地较好允许编译器优化。在展形必要时或在逻辑秩大于3时的情况中,计算必要的组的总数,且通过在所需要的组的总数的立方根周围绕轴旋转,这一数量跨三维度而相当平面地展形。因而,在它可以处理可能地可映射到单次计算调用中的硬件中的几乎所有输入意义上,先前的方法是相当通用的。给定MAX_GROUPS^3是2^48,来自先前的部分的方法#2所覆盖的范围将不满足任何计算是不太可能。
方法#2仍然涉及非直接映射,非直接映射可以以存根中的分离的代码路径结束,且可以导致大的二进制大小,这是由于对于秩=1、2和3,两个存根的版本通常保持分别处理直接映射和非直接映射,这取决于对于给定的逻辑域中的动态范围直接映射是否可行。
这一部分呈现缓和前述问题的替换方法#3。基本上,对于N<=3,如果逻辑域天然地落在向量G内,则,使用多次调用,每次“覆盖”来自逻辑网格的不同的部分。
例如,假设逻辑网格=(258,258),但是对于每一维度的物理限制是256(即,MAX_GROUPS是256)。同样出于阐述的简单起见,假设线程组的范围是(1,1,1)。因此这意味着逻辑上使用(1,258,258)线程网格,但是,当然,此网格不能被调度,这是因为X维度和Y维度超出了MAX_GROUPS。相反,API平台可以被调用四次以便覆盖类似于此定义的逻辑空间(4次分派):
●Gz,Gy,Gx)=(1,256,256),原点[0,0,0]
●(Gz,Gy,Gx)=(1,256,2),原点[0,0,256]
●(Gz,Gy,Gx)=(1,2,256),原点[0,256,0]
●(Gz,Gy,Gx)=(1,2,2),原点[0,256,256]
其他排列也是可能的,且系统将也有时具有并行执行这些分派中的某一些或在设备或计算机之间分布它们的机会。
此原点信息可以被传送给存根,且在计算逻辑索引时被使用。现在,用于索引计算的伪代码可以类似于此(例如):
情况1:N==1(总是直接地映射,带原点)
伪代码37
直接映射方法类似地适宜于N=2和N=3。因此,在情况N<=3的情况中,映射是直接加原点向量,这不同于先前的方法(#2),方法(#2)在一些情况中即使在N<=3时(且总是在N>3时)采用非直接映射。
现在对于其中N>3情况,存在两个选项。第一,可以使用方法#2中的非直接映射,但是更多地符合当前算法的精神,可以通过在N-3高次维度来“覆盖”N维度空间,且然后,N-3维度空间中的每一固定点,将3维索引映射算法映射到其余的剩余3个维度。伪代码可以类似于此(例如):
伪代码38
方法4:无需多次调用的更积极的线程利用
在方法#3中,在秩是1、2或3时的情况,为了优化索引展平和提高计算,在逻辑域时不能很好地适应物理域时,一个逻辑分派被分成若干个。在此部分中,方法4提供另一选项:试图直接地将逻辑映射到物理,但是在不可能时,它“负载平衡”可用的物理域并将逻辑范围展形到它们上。
因而,这种方法允许在一次分派中映射许多更多线程。毫无疑问,如果系统试图提供原子性的外观或分派的串行化,则,在将单次逻辑分派分成多次分派时需要小心维持此不变式。多次调用也具有它们的开销,尤其是在考虑它们被分派到其中的远程硬件时。
另一方面,映射多次调用方法(#3)中的逻辑的逆线程ID捕捉在物理ID和逻辑ID之间的非常直接的关系,且因而将允许更多编译器优化。它也可以节省重构中所涉及的存根侧上的一些计算(尽管这将通常不太显著)。
简而言之,使用哪种方法取决于系统的性能特性和底层编译器基础设施。正如所述的,在这一方法种,如果可能就优化直接映射,否则就以更为通用和非直接的索引映射代码的额外成本来利用全线程域。由于每一种分派方案可以产生调用存根中的不同索引映射代码,且在运行时基于是否越界来拾取分派方案,所以可以在存根中生成索引映射代码的所有版本,且在运行时传递标志以便选择。
由于在这一情况中通用一映射可以模糊关系在被用来访问数据结构的重构的逻辑线程ID和物理线程ID之间的关系,明智的是,复制内核函数调用以使得它在直接映射的情况中出现一次且在非直接映射情况中出现一次。这将得到较大的二进制,但是另一方面将在直接映射情况中允许更多向量化优化,直接映射情况通常更加常见。
考虑它的另一方式是创建两个存根:一个用于直接映射情况,且另一个用于非直接情况,且在运行时选择正确的一个来调用。
借助于这一方法,拾取thread_group_extents=(Tz,Ty,Tx)=(1,1,256)。可以基于场景和硬件特性调谐这一预定义的向量。该方法不取决于组件向量的数值(在它将用于可以选择的任何其他thread_group_extents值的意义上)。另外,可能生成假设这一值的不同值的多个存根,然后,在运行时为运行时选择准则选择特定的版本。
对于其中N是1、2或3的情况,在每一维度中计算必要的组的数量,在直接映射中:
1.如果在每一维度中要求少于MAX_GROUPS,则在物理组和逻辑组之间直接地映射,除非将得到过度的线程损耗量(见下)。
A.在每一维度中应用直接映射时,可能网格中的某一些维度将具有接近于或小于该维度中的线程组范围的值。例如,假定该网格指定X=1但是X维度中的线程组范围是256。因此X维度中至少一个组被用来覆盖网格,但是每一组将仅在其中具有使得X=0乘以逻辑网格内的有效点的那些值(例如,对于任何Vz或Vy,(Vz,Vy,13)将不被有效映射到逻辑网格)。这将得到实际上有助于网格的有用“覆盖”的线程中的仅1/256。为了防止这一情况,计算损耗量比率,损耗量比率被定义为我们将调度的线程的总数和网格实际上需要的线程的总数之间的比率。如果损耗量超出某个阀值(可由系统配置,例如它可以是5%),则非直接映射比直接映射优选。
B.因而,如果损耗量太大,我们去往步骤5——网格的完全“负载平衡”的间接。
2.否则,检查组的总数是否超过(MAX_GROUPS-1)^3。如果是,则分派是不可能的(当然,在这一不太可能的情况中可以借助多次调用)。
3.否则,存在要求少于MAX_GROUPS个组的至少一个维度。存在所指定的维度是E1、E2和E3的假设,且不失一般性假设E1<=E2<=E3。无疑E3>=MAX_GROUPS(否则情况#1将适用),且E1<MAX_GROUPS(否则情况#2将适用)。
4.现在,如果E2*E3<MAX_GROUPS^2或如果E2<MAX_GROUPS且E1*E3<MAX_GROUPS^2,则,在这两个维度中必要的组跨两个维度而展形,且在逻辑域和物理域之间直接地映射第三个维度。
A.注意,在这一子句下,跨两个物理维度而展形两个逻辑维度的组,但是维持每一组内的结构。这得到下式(假定DimX是对应于E1的维度,且E2和E3对应于DimZ和DimY,且E2*E3<MAX_GROUPS^2):
i.logical_idx[DimX]=gid[DimX]*Tx+gtid[DimX]
ii.logical_idx[DimZ..DimY]=remap(gid[DimZ..DimY])*(Tz,Ty)+gtid[DimZ..DimY]
B.在组水平进行再映射,以便确保X维度上的逆映射易于计算。
然而,这引入了增加的损耗量的可能性,如步骤(1.A)中所解释,因此,类似地,检查与这一映射一起产生的损耗量的水平,且如果它超过阀值,则接着是下面的选项#5。
5.否则,如果上面没有应用直接映射或半直接映射条件,则采用通用映射是。
下面阐述用于分派的示例伪代码和存根(作为示例而非限制):
伪代码39
索引代码生成:给定physical_thread_info(这只是gid/gtid/dtid信息的另一再现),基于在运行时传递的dispatcn_mode,生成不同的索引计算代码。
伪代码40
为进一步改善性能(避免存根中的if/else的成本),可以生成存根函数的多个版本,每一dispatch_mode一个版本,且在运行时拾取对应于由分派算法拾取的dispatch_mode的版本。也可能生成存根的一个通用版本以及几个更具体的版本(即两个选项的混合)。
再次,如果想要适应逻辑计算域中的点的总数大于或等于(MAX_GROUPS-1)^3的情况,我们可以将多次内核调用用于该情况。
方法5:将网格用作用于一般化计算域的中间嵌入域
借助于这一方法,要求所有计算域类型定义这两个成员:
1.extents<K>get_intermediate_grid()。这通过K的值同时地声明计算域类型将希望使用的中间嵌入网格的秩,对于线性嵌入来说,K的值可以是1,且它给运行时提供关于中间嵌入网格的范围信息。
2.bool map_intermediate_to_logical(index<K>intermediate_idx,index<N>&idx)。这一函数将来自中间嵌入网格中的任何点的逆映射提供回给逻辑ID,且带有可选的过滤。即,如果没有向嵌入网格中的点返回保留地映射逻辑索引,则该函数返回假。
对于给定的K,可以与在逻辑网格和物理网格之间映射的任一种先前的算法结合使用嵌入网格的秩、秩K的相应的嵌入网格。相反,为进行分派,我们将首先询问布置其中间嵌入网格的类型,然后使用如在先前的算法中描述的所供应的网格来分派。然后,在存根处,将使用任一种先前的方法来重建中间嵌入网格索引,且将使用该类型所提供的函数map_intermediate_to_logical来从中间索引映射到逻辑索引。如果不过滤该点,则然后用给定的逻辑索引值来调用用户所提供的内核函数。
方法6:调度线程分组的计算域
这种方法涉及线程分组的计算域的物理调度。这是带有以下改变的方法#5的改编:
1.组可以不是“部分的”,组中的所有线程都执行内核,或什么都不做。如先前所解释,这种类型的分散是的线程分组的目的受挫。
2.所指定的中间计算网格的范围可被所指定的分组的线程的范围除尽。如果它们不是,则报告错误。
3.由于上面的#2,用于边界条件和除法的舍入的一些测试变得不必要。
在下面的代码中,术语“逻辑”是指中间网格,从调度程度的观点来看,中间网格是逻辑网格的替身。这只是通过重新使用较早地介绍的术语的愿望来提示的语法约定,但应理解,到此阶段的输入是中间网格。
分派代码:
伪代码41
下面是存根代码。在下面的代码中,一些数据被示出为被当作参数而被传递,而实际上,那些参数将被分解为将允许更有效的代码生成的常数。尤其,THREAD_GROUP_EXTENTS和DISPATCH_MODE在大多数情况将被“焦化(SCORCHED)”为二进制代码。
伪代码42
示例过程
图2-5是示出实现在此描述的技术的示例过程200、300、400和500的流程图。这些过程的讨论将包括参考图1的计算机组件。这些过程中的每一个被示出为逻辑流程图中的框的集合,其表示可以在硬件、软件、固件或其组合中实现的操作的序列。在软件的上下文中,框表示被存储在由这样的计算机的一个或多个处理器执行时执行所叙述的操作的一个或多个计算机可读存储介质上的计算机指令。注意,所描述的过程的次序不旨在被解释成限制,且可以以任何次序组合任何数量的所描述的过程框以实现过程或替换过程。另外,可以在不偏离在此描述的本主题的精神和范围的前提下从过程删除单个框。
图2示出促进产生能够在支持DP的硬件上执行的程序的示例过程200。该产生可以例如通过C++编程语言编译器来执行。过程200至少部分地由包括例如图1的计算设备102的计算设备或系统来执行。计算设备或系统被配置为促进一个或多个DP可执行程序的产生。计算设备或系统可以是不支持DP的或支持DP的。如此配置的计算设备或系统取得特定的机器或装置的资格。
如在这里所示出,过程200以操作202开始,其中计算设备获得程序的源代码。此源代码是以一些人类可读的计算机编程语言(例如,C++)编写的文本的语句或声明的集合。可以从被存储在诸如存储系统106等的辅助存储系统中的一个或多个文件获得源代码。
对于此示例过程200,所获得的源代码包括对DP调用点的调用的文本表示。文本表示包括与对DP调用点的调用相关联的自变量的指示符。来自上面的伪代码列表8-11的函数调用是在这里所期望的文本表示的类型的示例。尤其,那些列表的forall、scan、reduce和sort函数调用以及它们的自变量是示例文本表示。当然,也期望函数调用和自变量的文本表示的其他格式。
在操作204,计算设备预处理源代码。在被编译时,预处理可以包括源代码的词汇分析和语法分析。在编译器的编程语言的上下文内,预处理检验各种字、数字和符号的含义以及它们与编程规则或结构的一致性。而且,源代码可以被转换为中间格式,其中文本的内容以对象或令牌方式来表示。此中间格式可以将内容重新排列为树结构。对于此示例过程200,代替使用对于DP调用点函数(带有其自变量)的调用的文本表示,可以以中间格式来表示DP调用点函数调用(带有其自变量)。
在操作206,计算设备处理源代码。在被编译时,源代码处理将源代码(或源代码的中间格式)转换为可执行指令。
在操作208,当计算设备处理源代码(以其本机格式或中间格式)时,计算设备解释函数调用(带有其自变量)的每一个表示。
在操作210,计算设备确定函数调用的经解析的表示是否需要DP计算。如果函数调用的经解析的需要DP计算,示例过程200移动到操作212。否则示例过程200移动到操作214。在操作212或214处生成适当的可执行指令之后,示例过程返回到操作208,直到所有的源代码已经被处理。
在操作212,计算设备在支持DP的硬件(例如,DP计算引擎120)上生成用于DP计算的可执行指令。所生成的DP可执行指令包括基于对带有其所关联的自变量的DP调用点函数的调用的那些指令。创建那些DP调用点函数指令,以便在具体目标支持DP的硬件(例如,DP计算引擎120)上执行。另外,在那些DP函数指令被执行时,基于自变量来定义数据集,且该数据集被存储在是支持DP的硬件的一部分的存储器(例如,节点存储器138)中。此外,在那些DP函数指令被执行时,一旦该数据集被存储在支持DP的存储器中,就执行DP调用点函数。
在操作214,计算设备在不支持DP的硬件(例如,非DP主机110)上生成用于非DP计算的可执行指令。
在处理之后,或作为处理的一部分,计算设备链接所生成的代码并将它与其他已编译的模块和/或运行时程序库组合以产生最终的可执行文件或镜像。
图3示出促进在支持DP的硬件中执行DP可执行程序的示例过程300。过程300至少部分地由包括例如图1的计算设备102的计算设备或系统来执行。计算设备或系统被配置为在不支持DP的硬件(例如,非DP主机110)和支持DP的硬件(例如,DP计算引擎120)两者上执行指令。实际上,用执行操作和/或是操作的对象的适当的硬件(例如,非DP主机110和/或计算引擎120)来示出操作。如此配置的计算设备或系统取得特定的机器或装置的资格。
如在这里所示出,过程300以操作302开始,其中计算设备选择将被用于DP计算的数据集。更具体地,计算设备的不支持DP的硬件(例如,非DP主机110)选择被存储在存储器(例如,主存储器114)中的数据集,所述存储器(例如,主存储器114)不是计算设备(例如,计算设备102)中的一个或多个的支持DP的硬件的一部分。
在操作304,计算设备将所选择的数据集的数据从非DP存储器(例如,主存储器114)传递到DP存储器(例如,节点存储器128)。在一些实施方式中,主机110和DP计算引擎120可以共享普通存储器系统。在那些实施方式中,将对数据的权限或控制从主机传递到计算机引擎。或者,计算引擎获得存储器中的数据的共享控制。对于这样的实施方式,在此所传递的数据的讨论意指,DP计算引擎拥有对数据的控制而不是数据已经被从一个存储器移动到另一个存储器。
在操作306,计算设备的支持DP的硬件将数据集的所传递的数据定义为字段。当数据集被存储在支持DP的存储器(例如,节点存储器138)上时,字段定义数据集的逻辑排列。DP调用点函数调用的自变量定义字段的参数。那些参数可以包括数据集的秩(即,维数)和数据集中的每一个元素的数据类型。索引和计算域是影响字段的定义的其他参数。这些参数可以帮助定义字段的处理的形状。在存在准确的类型匹配时,则它只是普通的自变量传递,但可以存在投影或局部投影。
在操作308,计算设备的支持DP的硬件准备将由多个数据并行线程执行的DP内核。DP内核是在数据集的一部分上执行的基本迭代DP活动。DP内核的每一个实例是相同的DP任务。特定的DP任务可以由程序员在编程DP内核时指定。多个处理元素(例如,元素140-146)表示每一个DP内核实例。
在操作310,作为计算设备的支持DP的硬件的一部分运行的DP内核的每一个实例将来自字段的数据的一部分接收为输入。DP内核的每一个实例在数据集的不同部分(如由字段所定义)上操作,这是数据并行性的本质。因此,每一个实例将其自己的数据集的一部分接收为输入。
在操作312,计算设备的支持DP的硬件并行调用支持DP的硬件中的DP内核的多个实例。对于由先前的操作适当地设置的所有动作,在操作312执行实际的数据并行计算。
在操作314,计算设备的支持DP的硬件获得从DP内核的所调用的多个实例得到的输出,所得到的输出被存储在支持DP的存储器。至少初始地,将来自DP内核实例的执行的输出收集和存储在本地的支持DP的存储器(例如,节点存储器128)。
在操作316,计算设备将所得到的输出从支持DP的存储器传递到不支持DP的存储器。当然,如果存储器被主机和计算引擎共享,则仅需要传递控制或授权而不是数据本身。一旦收集和存储来自DP内核实例的所有输出,就从DP计算引擎120将所收集的输出移动回到非DP主机110。
操作318表示执行一个或多个非DP计算并同时地与DP内核的多个实例的并行调用(操作312)这样做的计算设备的不支持DP的硬件。也可以同时地与诸如操作306、308、310和314的DP计算等的其他DP计算一起执行这些非DP计算。此外,可以同时地与诸如操作304和316的数据传输等的在非DP存储器和DP存储器之间的其他数据传输一起执行这些非DP计算。
被示出为操作316的一部分的输出的返回传输与调用程序异步。也就是说,发起DP调用点函数的程序(例如,程序118)不需要等待DP调用点的结果。相反,程序可以继续执行其他非DP活动。输出的实际的返回传输是同步点。
在操作320,计算设备继续正常执行一个或多个非DP计算。
图4示出促进至少一个DP函数的DP调用存根的产生的示例过程400。可以例如通过诸如编译器116等的C++编程语言编译器来执行存根产生。过程400至少部分地由包括例如图1的计算设备102的计算设备或系统来执行。计算设备或系统被配置为促进一个或多个DP调用存根的产生。计算设备或系统可以是不支持DP的或支持DP的。如此配置的计算设备或系统取得特定的机器或装置的资格。
对于过程400的此描述,出于示出的目的,引用以下示例源代码伪代码:
伪代码43
如在这里示出,过程400以操作402开始,其中计算设备标识当前并行活动在计算域中的位置。这基于目标相关计算单元身份(例如,GPU六维线程部署模型中的线程索引)来进行。换言之,计算设备标识目标支持DP的硬件(例如,计算引擎120)中的物理位置,其中对于所指派的计算域进行数据并行活动。
而且,在操作402,计算设备选择线程部署策略,并在调用存根中基于目标相关计算单元身份(这在运行时是可用的,对编译器来说不可访问)生成标识(例如,映射)当前并行活动在计算域中的位置的相应索引映射代码。在这里,计算设备也生成入口函数头部的声明,这是因为在头部中所声明的内容取决于线程部署决定。
此操作可以包括检查诸如forall等的DP函数的自变量;生成入口函数头部的声明和调用存根中的目标相关资源的声明;以及将DP硬件线程位置映射到逻辑并行活动在计算域中的位置。
为了进一步详细描述,作为操作402的一部分,计算设备检查诸如forall等的DP函数的自变量。计算设备确定所需要的目标缓冲器的数量和类型,且然后在调用存根中声明它们。基于上面的伪代码14中给出的示例,在forall调用中存在三个字段类型自变量,且因而需要三个设备缓冲器绑定。
每一字段实例对应于目标缓冲器绑定变量。然而,字段可以被包含在另一数据结构中。因此,执行每一个DP函数自变量的深遍历(deep traversal)以便标识所有的字段实例。计算设备及物地(transitively)确定由自变量列表包含的每一字段实例的可写性,以便定义用于调用存根的中间代码中的目标缓冲器绑定的具体类型。一旦收集所有信息,为存根声明缓冲器绑定的列表。
也确定要使用的缓冲器绑定变量的种类。如果存根是以例如HLSL,则HLSL具有许多种类的缓冲器绑定类型(例如,ByteAddrressBuffer、StructuredBuffer等等)。StructuredBuffer<T>可以被用来表示field<N,T>的设备缓冲器绑定。
在一些实现中,类似于在HLSL中的实现,将缓冲器绑定类型分成两个类别:只读或可写。StructuredBuffer<T>是只读,且RWStructuredBuffer<T>是可写。至少一个实现使用内核参数类型的“constness”来确定给定的函数的自变量是否是可写的。另一实现使用专用类型read_only<T>来断言只读用法,以使得编译器可以将其映射到只读缓冲器绑定。
基于来自上面的伪代码19的示例,这是至今所创建的调用存根的一部分:
伪代码43
而且,声明常量缓冲器。常量缓冲器被用来将所有必要的数据从非DP主机110传递到不是字段的数据集的一部分的DP计算引擎120。换言之,经由常量缓冲器将DP函数的自变量列表中的所有其他非字段数据传递给目标。常量缓冲器可以包含(作为示例而非限制):
●字段自变量的形状信息(例如,范围、乘法器、偏移);
●包括计算域参数在内的任何非字段函数自变量(例如,标量自变量);以及
●着色器分派形状信息(例如,组维度乘法器)。
基于来自上面的伪代码19的示例,常量缓冲器声明可以类似于此:
伪代码44
在这里,_grid_2是grid<2>的HLSL类,且_field_2_base是对应于field<2,T>的共享信息的HLSL类。注意,特殊索引参数不能被传递且不经由常量缓冲器而被传递。相反,在调用存根中生成它们。
另一实现可以包括生成原始的非类型化数据,且使用适当的偏移来从最初类型化的数据访问数据。在该情况中,常量缓冲器类似于:
在这一情况中,将不生成HLSL类。
操作402也可以包括入口函数头部的声明。这实际上是调用存根的声明。这涉及声明“numthread”属性和声明系统变量,对调用存根来说可能是有用的。
“numthread”属性指定框内的线程的形状。numthread指示如何以多个维度部署在线程组中的线程。对于至少一个实现,对于非tiled情况,计算设备生成作为普通的线程部署的“numthreads[256,1,1]”。对于tiled情况,如果tile的秩小于或等于三,则如果可能的话计算设备使用“numthreads”属性中的tile的形状。否则,计算设备尽可能高效地将tile的维度分布到3维物理线程组,或如果tile不能适合物理线程组,则报告错误。
操作402也可以包括将DP硬件的线程位置映射到逻辑并行活动在计算域中的位置。
计算域的概念有助于描述数据并行函数的并行性。这允许程序员在部署并行活动时以逻辑级而不是计算设备级(即,硬件级)思考。例如,对于向量加法,计算域是向量的形状,也就是说,每一元素可以通过并行活动独立地计算。然而,在使用在此描述的一种或多种实现时,这些逻辑并行活动应如何被映射到底层DP硬件不需要是程序员的关心的部分。
然而,每一种类的DP硬件具有其自己的部署并行计算的方式。在一些DP硬件中,以六维模型分派GPU线程。对于那些GPU线程,使用三个维度来描述线程框(或组)的部署,并使用三个维度来描述在框(组)内的线程的形状。从过程400得到的调用存根可以将DP硬件的线程位置(例如,六维域中的点)映射到逻辑并行活动在计算域中的位置。
完成此映射的一个方式包括在相同的分派中的所有线程当中获得线性的线程标识(“ltid”)(这在此被称为“变换索引展平”或简单地称为“展平”)且然后,将线性线程标识映射回到计算域中的索引(这在此被称为“索引提高”或简单地称为“提高”)。对于tiled部署,使用相似的展平和提高算法可以将三维线程组域和三维组内域分别独立地映射到tile索引和本地索引。
例如,存在带有范围E0、E1、E2(最显著的到最不显著的)的三维域。对于在此域中的给定的点(I0、I1、I2),
ltid=I0*E1*E2+I1*E2+I2
注意,并行活动的总数小于由“numthreads”预定义的组内的线程维数(例如,对于非tiled情况是256)是可能的。在该情况中,将存在不应执行内核的一些线程,这是由于它们不是计算域的一部分。为防止这些线程进行不被支持进行的工作,在计算线性线程标识的代码之后,编译器将调用存根的剩余部分封装在条件中,以确保映射到计算域的线程将执行内核,但其他线程不执行内核。
下一个步骤是将ltid提高到计算域的索引。以下的函数在grid<2>计算域中进行提高:
伪代码45
例如,对于非平铺情况,进行展平和提高调用存根的代码可以类似于此:
伪代码46
注意,此展平和然后提高方法是不取决于线程组形状或计算域形状的形式的最通用的算法。但是涉及此两步映射的计算可以是一些应用程序所关心的。一种优化可以是如果可能的话使线程组形状匹配计算域形状。
此展平-提高方法处理在目标线程模型和计算域之间的所有种类的映射。为改善性能,对于某些专用的情况,可以部署较好的执行计划以使目标线程模型与计算域部分地或完全地匹配,使得目标线程索引可以直接地被用作计算域的索引。对于这些情况,编译器将稍微不同地生成代码以利用这样的专门化。
在操作404,计算设备用目标相关资源设置DP函数的字段对象。
在操作406,计算设备准备内核期望的适当的参数。此操作在图5的稍后讨论中详细说明。
在操作408,计算设备产生将调用具有所准备的参数的内核的代码。
在操作410,计算设备将结果存储回到正确的位置。在投影被执行时,这一操作将结果恢复回到其中发生到标量的投影的缓冲器。对于发生到标量的投影的那些可写的参数,计算结果被写回到原始的缓冲器的适当的存储槽。
在操作412,计算设备输出诸如存根118的那些等的调用存根。调用存根可以被存储到例如存储器114和/或存储子系统106。
此外,计算设备可以生成附加代码以设置适当的环境以开始DP计算。例如,HLSL中的调用存根可以包括以下(作为示例而非限制):
·定义将要使用的所有种类的缓冲器,例如,结构化缓冲器(可写或不可写)、纹理、常量缓冲器等等;
·声明适当的入口点函数头部,入口点函数头部包括numthreads属性和SV变量(SV变量是DP计算设备提供的专用的物理线程索引,包括SV_GroupIndex、SV_DispathThreadId、SV_GroupThreadID、SV_GroupID)。
图5示出准备内核期望的适当的参数的示例过程500。过程500至少部分地通过包括例如图1的计算设备102的计算设备或系统来执行。计算设备或系统被配置为在不支持DP的硬件(例如,非DP主机110)和支持DP的硬件(例如,DP计算引擎120)两者上执行指令。实际上,借助于执行操作和/或是操作的对象的适当的硬件(例如,非DP主机110和/或计算引擎120)来示出各操作。如此配置的计算设备或系统取得特定的机器或装置的资格。
过程500是来自图4的操作406的扩展。如在这里所示出,过程500在操作404之后拾取。在操作502,计算设备确定内核函数的参数是否对应于特殊索引,即,它标识计算域中的并行活动。如果是,则过程继续到操作504。如果不是,则过程进行到操作506。
在操作504,在专用的令牌(例如,(_index,_tile_index,_local_index))被用作DP函数自变量的一部分时,计算设备创建适当的索引实例。如果使用了专用的令牌,则程序员指定对非元素的内核的映射。在这之后,过程500完成,且过程400在操作408拾取。另外,此过程可以对内核函数参数一个一个地迭代。
如果没有使用特殊索引令牌,则过程500沿着经由操作506的路径向下进行。作为这一操作的一部分,计算设备确定形式参数是否匹配实际参数。如果是,则过程继续到操作508。如果不是,则该过程进行到操作510。
在操作508,计算设备将DP函数的自变量直接地广播给内核。如果参数是广播标量(Ra=Rf=0),则来自常量缓冲器的值被内核利用。如果参数是广播字段(Ra=Rf>0),则适当的字段类型的实例被创建并用经由常量缓冲器和被定义为过程400的一部分的缓冲器所传送的字段的形状信息来初始化。在操作508之后,过程500是完整的,且过程400在操作408加速。
如果形式参数不匹配实际参数,则该过程沿着经由操作510的路径向下进行。这意味着该参数涉及投影(Ra=Rf+Rc)。作为这一操作的一部分,使用作为过程400的一部分计算的计算索引,秩Ra处的字段被投影到秩Rf处的字段。如果Rf为零,则将元素从投影的字段加载到标量本地的变量。在操作508之后,过程500完成,且过程400在操作408拾取。
替代过程500,可以允许内核函数访问计算域中的并行活动的身份。代替用特殊令牌,可以隐含地允许它们的功能。以这一方式,例如,如果内核函数具有一个比由forall调用提供的更多参数,且第一参数是在具有与计算秩相同的秩的类型index_group,则编译器可以准备特殊索引并将其作为其第一参数而传递给内核函数。在这里,做出以下判决:是否应从特殊索引或来自forall调用的用户提供的数据映射给定的内核函数参数,且对于后面的情况,是否应使用投影或广播。
实现细节
在一种或多种实现中,编译器116独立地从调用存根的代码生成执行内核的生成。调用存根不是内核的定制。相反,编译器116将内核看作是调用函数且仅要求内核的签名。这允许更灵活的编译模型和内核的所生成的代码的重用,但是如果内核体是可用的,则不排除优化机会。
尤其,将在此描述的本发明概念实现到C++编程语言,可以涉及使用模板语法来表达大多数概念和避免核语言的扩展。模板语法可以包括可变参数模板,它是采取可变数量的自变量的模板。模板是允许函数和类与泛型类型一起操作的C++编程语言的特征。也就是说,函数或类无需必须针对每一数据类型重写就可以作用于许多不同的数据类型。泛型类型允许将数据提高到类型系统中。这允许定制在编译时通过标准兼容的C++编译器来检查的域专用的语义。适当的编译器(例如,编译器116)可以具有准确的错误消息并强加某种类型的限制。
类index的实例表示任何N维索引或N维范围。N是编译时常量,它是索引模板类的参数。或者,索引可以从范围分开。而且,作为替换方式的一部分,为避免绑定到模板,可以在编译时将所有秩指定为该类型的静态的常量成员。在二维整数空间中,例如,此空间中的点通常被标记为“<x,y>坐标”。对于在此描述的一种或多种实现,这样的坐标可以用二维空间来表示为类index<2>的实例。对于类型index<2>的给定的实例idx,使用idx[0]和idx[1]来获得“x”和“y”。程序员拥有是否使得“x”与idx[0]相等且“y”与idx[1]相等的选择,或用相反的方式。这一决定时常由用于索引对象且用来索引到其中的数据的物理布局来指示。
索引可以从数组初始化或直接地通过将索引值传送到构造器来初始化。这是可以达成的伪代码的示例:
size_t extents[3]={3,7,0};
index<3>idx1(extents);
index<3>idx2(3,7,0);
伪代码47
上面的伪代码将初始化三维索引,其中idx1[0]等于3,idx1[1]等于7,且idx1[2]等于0。换言之,将索引的元素列出为从较低的索引维度到较高的索引维度。
索引支持许多有用的操作。可以复制和比较它们。乘法、加法和减法操作符可以以逐点的方式被应用到两个索引对象(具有相同的维度)。可以计算两个索引的点乘(像向量那样处理它们)。索引对象是轻量级的,且通常传值来传递,且被分配在堆栈上。
DP调用点函数调用的自变量被用来定义DP调用点函数将在其上操作的字段的参数。换言之,自变量帮助定义字段所定义的数据集的逻辑排列。
除了关于解释字段的自变量的规则除外,还有在一种或多种实现中可以被应用到DP调用点函数的其他规则:将相同的标量值传递给调用,且避免定义评估次序。
如果实际参数是标量值,则相应形式参数可以被限制为具有非引用类型或被限制为具有“const”属性。对于这一限制,标量被同等地传递给所有内核调用。这是基于在调用点从主机环境复制的标量参数化计算节点的机制。
在DP内核调用内,字段可以被限制为与至多一个非常量引用或聚集形式相关联。在该情况中,如果字段与非常量引用或聚集形式相关联,则不可以以不同于非常量引用或聚集形式的任何方式来引用字段。这一限制避免了必须定义评估次序。它也防止危险的混叠且可以作为冒险检测的副作用而被强加。此外,通过将指派的目标同等地看作是元素指派函数的实际的、非常量的、非元素参数,这一限制强加写前读取(read-before-write)语义。
对于至少一种实现,可以使用“_declspec”关键字来将内核定义为对C++编程语言的扩展,其中给定的类型的实例应被存储带有域专用的存储类属性。更具体地,“_declspec(vector)”被用来定义对C++语言的内核扩展。
“map_index”在范围为0至网格的大小减一的偏移和N维度索引之间映射。在偏移和N维度索引之间的映射假设idx[0]是最重要的且最后的索引维度是最不重要的。
在将N维数据存储在一维存储器中时,改变最不重要的索引维度得到对邻近的存储器位置的引用,同时改变最重要的索引维度得到远离的存储器引用。下表示出如何将二维网格放置在一维存储器中。元组是<idx[0],idx[1]>的形式。
这是3乘4的二维网格的逻辑视图:
<0,0> | <0,1> | <0,2> | <0,3> |
<1,0> | <1,1> | <1,2> | <1,3> |
<2,0> | <2,1> | <2,2> | <2,3> |
且这是网格将如何被转换成平面索引地址:
用法示例:
grid<2>cubic_domain(rv,3,4);
index<2>idx=cubic_domain.map_index(7);//idx=
<1,3>
可以从用户提供的输入数据(forall调用的自变量)直接地映射内核函数所期望的参数中的某一些(经由投影或广播),一些参数(例如索引、tile索引、局部索引)取决于线程分派决定,线程分派决定不具有在用户提供的输入数据中的相应副本。在此描述的实现给用户提供在内核函数中引用这样的专用的项的途径。
特殊索引令牌是用于该目的的一种方法。它用作forall自变量列表中的标记(marker),forall自变量列表让编译器知道,内核函数中的相应的参数应被映射到从线程分派决定而不是任何用户提供的输入数据获得的特殊索引。或者,代替特殊索引令牌,在程序员想要引用在他们的内核函数中的这样的特殊索引的情况中,允许用户在内核参数列表中具有比在forall调用点所提供的多一个的参数,且第一参数可以是他们期望的特殊索引的类型。这是令编译器知道内核函数的第一参数应被映射到特殊索引的另一途径。
结论
如在本申请中所使用的,术语“组件”、“模块”、“系统”、“接口”等一般旨在表示计算机相关的实体,其可以是硬件、硬件和软件的组合、软件、或者执行中的软件。例如,组件可以是,但不限于是,在处理器上运行的进程、处理器、对象、可执行码、执行的线程、程序和/或计算机。作为示例,运行在控制器上的应用程序和控制器都可以是组件。一个或多个组件可以驻留在进程和/或执行线程中,并且组件可以位于一个计算机内和/或分布在两个或更多的计算机之间。
此外,所要求保护的主题可以使用产生控制计算机以实现所公开的主题的软件、固件、硬件或其任意组合的标准编程和/或工程技术而被实现为方法、装置或制品。
所要求保护的主题的实现可以存储在某种形式的计算机可读介质上或通过某种形式的计算机可读介质传输。计算机可读介质可以是可由计算机访问的任何可用介质。作为示例,计算机可读介质可包括但不限于“计算机可读存储介质”和“通信介质”。
“计算机可读存储介质”包括以用于存储诸如计算机可读指令、计算机可执行指令、数据结构、程序模块或其他数据等信息的任何方法或技术实现的易失性和非易失性、可移动和不可移动介质。计算机可读存储介质包括但不限于,RAM、ROM、EEPROM、闪存或其他存储器技术、CD-ROM、数字多功能盘(DVD)或其他光盘存储、盒式磁带、磁带、磁盘存储或其他磁存储设备,或者任何其他可用于存储所需信息并可由计算机访问的介质。
“通信介质”通常用诸如载波或其他传输机制等已调制数据信号来体现计算机可读指令、计算机可执行指令、数据结构、程序模块或其他数据。通信介质也包括任意的信息传递介质。
如本申请中所使用的,术语“或”意指包括性“或”而非互斥性“或”。即,除非另有指定或从上下文可以清楚,否则“X使用A或B”意指任何自然的包括性排列。即,如果X使用A,X使用B,或X使用A和B两者,则在任何以上情况下,都满足“X使用A或B”。另外,本申请中和所附权利要求书中所使用的冠词“一”和“一个”一般应被解释为是指“一个或多个”,除非另有指定或从上下文可以清楚指的是单数形式。
尽管已经用结构特征和/或方法动作专用的语言描述了本主题,但要理解,所附权利要求书中定义的主题不必限于所描述的具体特征或动作。相反,这些具体特征和动作是作为实现权利要求的示例形式来公开的。
Claims (22)
1.一种促进数据并行(DP)可执行程序的产生的方法,所述方法包括:
获得(202)对DP函数的调用的表示,其中所述表示包括与对所述DP函数的所述调用相关联的自变量的指示符;
至少部分地基于所述DP函数表示及其关联的自变量生成(400)调用存根,所述调用存根包括通过基于物理线程索引和逻辑计算域计算每一DP活动的逻辑索引来将所述DP函数的DP计算的逻辑排列桥接到要在一个或多个计算设备的DP硬件上执行的DP计算的物理排列的计算机可执行指令。
2.如权利要求1所述的方法,其特征在于,所述生成包括确定所述DP硬件中将对所述DP计算的逻辑排列进行所述DP计算的物理位置。
3.如权利要求1所述的方法,其特征在于,所述生成包括用目标相关资源设置用于所述DP函数的字段,其中所述字段是要由所述DP函数的DP计算操作的数据集。
4.如权利要求1所述的方法,其特征在于,所述生成包括用目标相关资源设置用于所述DP函数的字段,其中所述字段包括要由所述DP函数的DP计算操作的数据集,并且其中所述设置包括检查与所述DP函数相关联的自变量以及基于所述检查配置所述数据集。
5.如权利要求1所述的方法,其特征在于,所述生成包括用目标相关资源设置用于所述DP函数的字段,其中所述字段包括由所述DP函数的DP计算操作的数据集,并且其中所述设置包括声明应将线程组中的多少个线程部署在多个维度中。
6.如权利要求1所述的方法,其特征在于,所述生成包括用目标相关资源设置用于所述DP函数的字段,其中所述字段包括由所述DP函数的DP计算操作的数据集,并且其中所述设置包括将所述DP硬件的线程位置映射到所述DP计算的逻辑排列中的逻辑DP活动位置。
7.如权利要求1所述的方法,其特征在于,所述生成包括用目标相关资源设置用于所述DP函数的字段,其中所述字段包括由所述DP函数的DP计算操作的数据集,并且其中所述设置包括将所述DP硬件的线程位置映射到所述DP计算的所述逻辑排列中的逻辑DP活动位置,所述映射包括变换索引展平和索引提高。
8.如权利要求1所述的方法,其特征在于,所述生成包括基于内核期望的内容来准备所述内核的参数,所述内核是所述DP函数的单元DP计算。
9.如权利要求1所述的方法,其特征在于,所述生成包括基于内核期望的内容来准备所述内核的参数,所述内核是所述DP函数的单元DP计算,其中所述准备包括:
确定所关联的自变量是否包括一个或多个特殊索引;
响应于所述确定,基于一个或多个特殊索引的类型创建索引实例。
10.如权利要求1所述的方法,其特征在于,所述生成包括基于内核期望的内容来准备所述内核的参数,所述内核是所述DP函数的单元DP计算,其中所述准备包括:
确定所关联的自变量是否匹配所述内核的实际参数;
响应于所述确定,广播一值以供所述内核使用。
11.如权利要求1所述的方法,其特征在于,所述生成包括基于内核期望的内容来准备所述内核的参数,所述内核是所述DP函数的单元DP计算,其中所述准备包括:
确定所关联的自变量是否匹配实际参数;
响应于所述确定,投影字段,其中所述字段是由所述DP函数的DP计算操作的数据集。
12.如权利要求1所述的方法,其特征在于,还包括将所述调用存根输出到存储器中。
13.如权利要求1所述的方法,其特征在于,所述DP硬件能够执行DP计算,并且所述DP计算的逻辑排列至少部分地由具有其所关联的自变量的所述对DP函数的调用的表示来定义。
14.一种方法,包括:
获得(202)对DP函数的调用的表示,其中所述表示包括与对所述DP函数的调用相关联的自变量的指示符;
至少部分地基于所述DP函数表示及其关联的自变量生成(400)调用存根,所述调用存根包括将所述DP函数的DP计算的逻辑排列桥接到要在一个或多个计算设备的DP硬件上执行的DP计算的物理排列的计算机可执行指令,所述DP硬件能够执行DP计算且所述DP计算的逻辑排列至少部分地由具有其所关联的自变量的所述对DP函数的调用的表示来定义,
所述生成包括:
确定所述DP硬件中将对所述DP计算的逻辑排列进行所述DP计算的物理位置;
选择适当的线程部署策略;
用目标相关资源设置用于所述DP函数的字段,其中所述字段包括由所述DP函数的DP计算操作的数据集,所述设置包括:
检查与所述DP函数相关联的自变量并基于所述检查配置所述数据集;
声明应将线程组中的多少个线程部署在多个维度中;
基于内核期望的内容来准备所述内核的参数,所述内核是所述DP函数的单元DP计算,所述准备包括:
确定所关联的自变量是否包括一个或多个特殊索引;
响应于关于特殊索引的所述确定,基于所述一个或多个特殊索引类型创建索引实例;
确定所关联的自变量是否匹配实际参数;
响应于关于自变量匹配参数的所述确定,广播一值以供所述内核使用或投影字段,其中所述字段是由所述DP函数的DP计算操作的数据集。
15.一种方法,包括:
获得(202)对DP函数的调用的表示,其中所述表示包括与对所述DP函数的所述调用相关联的自变量的指示符;
至少部分地基于所述DP函数表示及其关联的自变量生成(400)调用存根,所述调用存根包括将所述DP函数的DP计算的逻辑排列桥接到要在一个或多个计算设备的DP硬件上执行的DP计算的物理排列的计算机可执行指令,所述DP硬件能够执行DP计算且所述DP计算的逻辑排列由具有其所关联的自变量的所述对DP函数的调用的表示来定义;
所述生成包括:
用目标相关资源设置用于所述DP函数的字段,其中所述字段包括由所述DP函数的DP计算操作的数据集;
基于内核期望的内容来准备所述内核的参数,所述内核是所述DP函数的单元DP计算;
将所述调用存根输出到存储器中。
16.如权利要求15所述的方法,其特征在于,所述设置包括:
检查与所述DP函数相关联的自变量并基于所述检查配置所述数据集;
声明应将线程组中的多少个线程部署在多个维度中;以及
将所述DP硬件的线程位置映射到所述DP计算的逻辑排列中的逻辑DP活动位置。
17.如权利要求15所述的方法,其特征在于,所述设置包括将所述DP硬件的线程位置映射到所述DP计算的逻辑排列中的逻辑DP活动位置,所述映射包括变换索引展平和索引提高。
18.如权利要求15所述的方法,其特征在于,所述准备包括:
确定所关联的自变量是否包括一个或多个令牌;
响应于关于令牌的所述确定,基于所述一个或多个令牌创建索引实例。
19.如权利要求15所述的方法,其特征在于,所述准备包括:
确定所关联的自变量是否匹配实际参数;
响应于关于自变量匹配参数的所述确定,广播一值以供所述内核使用或投影字段,其中所述字段包括由所述DP函数的DP计算操作的数据集。
20.如权利要求15所述的方法,其特征在于,所述准备包括:
确定所关联的自变量是否包括一个或多个令牌;
响应于关于令牌的所述确定,基于所述一个或多个令牌创建索引实例;
确定所关联的自变量是否匹配实际参数;
响应于关于匹配参数的自变量所述确定,广播一值以供所述内核使用或投影字段,其中所述字段包括由所述DP函数的DP计算操作的数据集。
21.一种系统,包括:
用于获得(202)对DP函数的调用的表示的装置,其中所述表示包括与对所述DP函数的调用相关联的自变量的指示符;
用于至少部分地基于所述DP函数表示及其关联的自变量生成(400)调用存根的装置,所述调用存根包括将所述DP函数的DP计算的逻辑排列桥接到要在一个或多个计算设备的DP硬件上执行的DP计算的物理排列的计算机可执行指令,所述DP硬件能够执行DP计算且所述DP计算的逻辑排列至少部分地由具有其所关联的自变量的所述对DP函数的调用的表示来定义,
所述生成包括:
确定所述DP硬件中将对所述DP计算的逻辑排列进行所述DP计算的物理位置;
选择适当的线程部署策略;
用目标相关资源设置用于所述DP函数的字段,其中所述字段包括由所述DP函数的DP计算操作的数据集,所述设置包括:
检查与所述DP函数相关联的自变量并基于所述检查配置所述数据集;
声明应将线程组中的多少个线程部署在多个维度中;
基于内核期望的内容来准备所述内核的参数,所述内核是所述DP函数的单元DP计算,所述准备包括:
确定所关联的自变量是否包括一个或多个特殊索引;
响应于关于特殊索引的所述确定,基于所述一个或多个特殊索引类型创建索引实例;
确定所关联的自变量是否匹配实际参数;
响应于关于自变量匹配参数的所述确定,广播一值以供所述内核使用或投影字段,其中所述字段是由所述DP函数的DP计算操作的数据集。
22.一种系统,包括:
用于获得(202)对DP函数的调用的表示的装置,其中所述表示包括与对所述DP函数的所述调用相关联的自变量的指示符;
用于至少部分地基于所述DP函数表示及其关联的自变量生成(400)调用存根的装置,所述调用存根包括将所述DP函数的DP计算的逻辑排列桥接到要在一个或多个计算设备的DP硬件上执行的DP计算的物理排列的计算机可执行指令,所述DP硬件能够执行DP计算且所述DP计算的逻辑排列由具有其所关联的自变量的所述对DP函数的调用的表示来定义;
所述生成包括:
用目标相关资源设置用于所述DP函数的字段,其中所述字段包括由所述DP函数的DP计算操作的数据集;
基于内核期望的内容来准备所述内核的参数,所述内核是所述DP函数的单元DP计算;
用于将所述调用存根输出到存储器中的装置。
Applications Claiming Priority (2)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
US12/819,108 | 2010-06-18 | ||
US12/819,108 US8589867B2 (en) | 2010-06-18 | 2010-06-18 | Compiler-generated invocation stubs for data parallel programming model |
Publications (2)
Publication Number | Publication Date |
---|---|
CN102314342A CN102314342A (zh) | 2012-01-11 |
CN102314342B true CN102314342B (zh) | 2016-08-17 |
Family
ID=45329826
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201110177689.1A Active CN102314342B (zh) | 2010-06-18 | 2011-06-17 | 用于数据并行编程模型的编译器生成的调用存根 |
Country Status (2)
Country | Link |
---|---|
US (1) | US8589867B2 (zh) |
CN (1) | CN102314342B (zh) |
Families Citing this family (44)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US8533697B2 (en) * | 2007-02-14 | 2013-09-10 | The Mathworks, Inc. | Graphical processing unit (GPU) arrays providing high computational capabilities in a computing environment |
US8621447B1 (en) * | 2009-08-25 | 2013-12-31 | Adobe Systems Incorporated | Systems and methods for dynamic struct variable creation including inline declaration with dynamic keys |
US8756590B2 (en) * | 2010-06-22 | 2014-06-17 | Microsoft Corporation | Binding data parallel device source code |
US9489183B2 (en) | 2010-10-12 | 2016-11-08 | Microsoft Technology Licensing, Llc | Tile communication operator |
US9430204B2 (en) | 2010-11-19 | 2016-08-30 | Microsoft Technology Licensing, Llc | Read-only communication operator |
US9507568B2 (en) | 2010-12-09 | 2016-11-29 | Microsoft Technology Licensing, Llc | Nested communication operator |
US9395957B2 (en) | 2010-12-22 | 2016-07-19 | Microsoft Technology Licensing, Llc | Agile communication operator |
US9841958B2 (en) * | 2010-12-23 | 2017-12-12 | Microsoft Technology Licensing, Llc. | Extensible data parallel semantics |
US9483235B2 (en) | 2012-05-09 | 2016-11-01 | Nvidia Corporation | Method and system for separate compilation of device code embedded in host code |
US10025643B2 (en) * | 2012-05-10 | 2018-07-17 | Nvidia Corporation | System and method for compiler support for kernel launches in device code |
US9165035B2 (en) | 2012-05-10 | 2015-10-20 | Microsoft Technology Licensing, Llc | Differential dataflow |
US9274772B2 (en) * | 2012-08-13 | 2016-03-01 | Microsoft Technology Licensing, Llc. | Compact type layouts |
US8959495B2 (en) * | 2012-09-14 | 2015-02-17 | Oracle International Corporation | Unifying static and dynamic compiler optimizations in source-code bases |
US9832068B2 (en) | 2012-12-17 | 2017-11-28 | Microsoft Technology Licensing, Llc | Reachability-based coordination for cyclic dataflow |
US11003459B2 (en) | 2013-03-15 | 2021-05-11 | Intel Corporation | Method for implementing a line speed interconnect structure |
US9817666B2 (en) | 2013-03-15 | 2017-11-14 | Intel Corporation | Method for a delayed branch implementation by using a front end track table |
CN105190579B (zh) * | 2013-03-15 | 2018-04-06 | 英特尔公司 | 一种用于实现线路速度互连结构的方法 |
US9753691B2 (en) | 2013-03-15 | 2017-09-05 | Intel Corporation | Method for a stage optimized high speed adder |
US9229698B2 (en) | 2013-11-25 | 2016-01-05 | Nvidia Corporation | Method and apparatus for compiler processing for a function marked with multiple execution spaces |
US9710245B2 (en) * | 2014-04-04 | 2017-07-18 | Qualcomm Incorporated | Memory reference metadata for compiler optimization |
US10346941B2 (en) | 2014-05-30 | 2019-07-09 | Apple Inc. | System and method for unified application programming interface and model |
US9740464B2 (en) * | 2014-05-30 | 2017-08-22 | Apple Inc. | Unified intermediate representation |
US10430169B2 (en) * | 2014-05-30 | 2019-10-01 | Apple Inc. | Language, function library, and compiler for graphical and non-graphical computation on a graphical processor unit |
US10585892B2 (en) * | 2014-07-10 | 2020-03-10 | Oracle International Corporation | Hierarchical dimension analysis in multi-dimensional pivot grids |
US9690709B2 (en) * | 2014-07-14 | 2017-06-27 | Oracle International Corporation | Variable handles |
US9400683B2 (en) * | 2014-10-16 | 2016-07-26 | Sap Se | Optimizing execution of processes |
CN104375806B (zh) * | 2014-11-19 | 2015-12-09 | 北京应用物理与计算数学研究所 | 一种并行计算构件、方法及相应并行软件开发方法与系统 |
US10241761B2 (en) * | 2014-12-29 | 2019-03-26 | Nvidia Corporation | System and method for compiler support for compile time customization of code |
CN104536937B (zh) * | 2014-12-30 | 2017-10-31 | 深圳先进技术研究院 | 基于cpu‑gpu异构集群的大数据一体机实现方法 |
CN105183451B (zh) * | 2015-07-30 | 2018-11-02 | 浪潮金融信息技术有限公司 | 一种确定调用关系的方法和多维程序管理装置 |
CN107250982B (zh) | 2015-11-25 | 2020-11-06 | 华为技术有限公司 | 用于加速器的程序生成方法和系统 |
US9798569B2 (en) * | 2016-02-15 | 2017-10-24 | Nvidia Corporation | System and method for retrieving values of captured local variables for lambda functions in Java |
US20180046940A1 (en) * | 2016-08-15 | 2018-02-15 | Google Inc. | Optimized machine learning system |
US10726605B2 (en) * | 2017-09-15 | 2020-07-28 | Intel Corporation | Method and apparatus for efficient processing of derived uniform values in a graphics processor |
CN107766052B (zh) * | 2017-09-18 | 2020-09-25 | 网宿科技股份有限公司 | 一种构建容器镜像的方法和装置 |
US10467724B1 (en) * | 2018-02-14 | 2019-11-05 | Apple Inc. | Fast determination of workgroup batches from multi-dimensional kernels |
CN109144492A (zh) * | 2018-06-23 | 2019-01-04 | 上海泽阳智能科技有限公司 | 一种面向对象的软件开发系统 |
CN108984166A (zh) * | 2018-06-23 | 2018-12-11 | 上海泽阳智能科技有限公司 | 一种用于人机交互软件的快速开发工具系统 |
CN109395380A (zh) * | 2018-09-14 | 2019-03-01 | 北京智明星通科技股份有限公司 | 游戏数据处理方法及系统、服务器和计算机可读存储介质 |
CN110069243B (zh) * | 2018-10-31 | 2023-03-03 | 上海奥陶网络科技有限公司 | 一种java程序线程优化方法 |
US10761821B1 (en) * | 2019-03-27 | 2020-09-01 | Sap Se | Object oriented programming model for graphics processing units (GPUS) |
US11249651B2 (en) * | 2019-10-29 | 2022-02-15 | Samsung Electronics Co., Ltd. | System and method for hierarchical sort acceleration near storage |
CN111158805B (zh) * | 2019-11-19 | 2022-06-17 | 厦门天锐科技股份有限公司 | Delphi软件源语言翻译系统、方法、设备及介质 |
CN116841622B (zh) * | 2023-09-01 | 2023-11-24 | 上海燧原智能科技有限公司 | 一种地址自增访存指令的生成方法、装置、设备及介质 |
Citations (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN1499362A (zh) * | 2002-10-24 | 2004-05-26 | 国际商业机器公司 | 在异构体系结构的集成可执行程序中用多个代码访问全局变量的系统和装置 |
Family Cites Families (65)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US4205371A (en) | 1975-11-03 | 1980-05-27 | Honeywell Information Systems Inc. | Data base conversion system |
US4340857A (en) | 1980-04-11 | 1982-07-20 | Siemens Corporation | Device for testing digital circuits using built-in logic block observers (BILBO's) |
US4516203A (en) | 1981-09-11 | 1985-05-07 | Data General Corporation | Improved apparatus for encaching data whose value does not change during execution of an instruction sequence |
US4503492A (en) | 1981-09-11 | 1985-03-05 | Data General Corp. | Apparatus and methods for deriving addresses of data using painters whose values remain unchanged during an execution of a procedure |
DE3265546D1 (en) | 1982-04-03 | 1985-09-26 | Itt Ind Gmbh Deutsche | Circuit for a serially operating digital filter |
US4530051A (en) | 1982-09-10 | 1985-07-16 | At&T Bell Laboratories | Program process execution in a distributed multiprocessor system |
US4652995A (en) | 1982-09-27 | 1987-03-24 | Data General Corporation | Encachement apparatus using multiple caches for providing multiple component values to form data items |
US4847755A (en) | 1985-10-31 | 1989-07-11 | Mcc Development, Ltd. | Parallel processing method and apparatus for increasing processing throughout by parallel processing low level instructions having natural concurrencies |
US5021945A (en) | 1985-10-31 | 1991-06-04 | Mcc Development, Ltd. | Parallel processor system for processing natural concurrencies and method therefor |
US4847613A (en) | 1986-07-15 | 1989-07-11 | Matsushita Electric Industrial Co., Ltd. | Data transfer apparatus |
DE3782160T2 (de) | 1986-09-11 | 1993-02-11 | Hughes Aircraft Co | Digitales simulationssystem zur erzeugung von realistischen szenen. |
US4811214A (en) | 1986-11-14 | 1989-03-07 | Princeton University | Multinode reconfigurable pipeline computer |
AU583203B2 (en) | 1987-03-06 | 1989-04-20 | Fujitsu Limited | Electronic circuit device able to diagnose status-holding circuits by scanning |
US4868776A (en) | 1987-09-14 | 1989-09-19 | Trw Inc. | Fast fourier transform architecture using hybrid n-bit-serial arithmetic |
US4888714A (en) | 1987-09-25 | 1989-12-19 | Laser Precision Corporation | Spectrometer system having interconnected computers at multiple optical heads |
JPH0731726B2 (ja) | 1989-06-29 | 1995-04-10 | インターナショナル・ビジネス・マシーンズ・コーポレーシヨン | イメージ処理システム |
US5404519A (en) | 1989-10-11 | 1995-04-04 | Texas Instruments Incorporated | System for extending software calls to functions on another processor by means of a communications buffer |
US5261095A (en) | 1989-10-11 | 1993-11-09 | Texas Instruments Incorporated | Partitioning software in a multiprocessor system |
JPH03223957A (ja) | 1989-12-26 | 1991-10-02 | Hitachi Ltd | 計算機 |
US5361363A (en) | 1990-10-03 | 1994-11-01 | Thinking Machines Corporation | Input/output system for parallel computer for performing parallel file transfers between selected number of input/output devices and another selected number of processing nodes |
US5377191A (en) | 1990-10-26 | 1994-12-27 | Data General Corporation | Network communication system |
US5625793A (en) | 1991-04-15 | 1997-04-29 | International Business Machines Corporation | Automatic cache bypass for instructions exhibiting poor cache hit ratio |
JPH04337843A (ja) | 1991-05-15 | 1992-11-25 | Hitachi Ltd | プログラム動作表示方法 |
US5355492A (en) | 1991-11-05 | 1994-10-11 | Thinking Machines Corporation | System for compiling parallel communications instructions including their embedded data transfer information |
US5355494A (en) | 1991-12-12 | 1994-10-11 | Thinking Machines Corporation | Compiler for performing incremental live variable analysis for data-parallel programs |
US5561801A (en) | 1991-12-13 | 1996-10-01 | Thinking Machines Corporation | System and method for multilevel promotion |
US5278986A (en) | 1991-12-13 | 1994-01-11 | Thinking Machines Corporation | System and method for compiling a source code supporting data parallel variables |
US5659778A (en) | 1992-02-03 | 1997-08-19 | Tm Patents, L.P. | System and method of mapping an array to processing elements |
JP3489123B2 (ja) | 1992-04-15 | 2004-01-19 | 株式会社日立製作所 | アプリケーション結合方法 |
US5377228A (en) | 1992-04-20 | 1994-12-27 | Yamaha Corporation | Data repeating apparatus |
US5339430A (en) | 1992-07-01 | 1994-08-16 | Telefonaktiebolaget L M Ericsson | System for dynamic run-time binding of software modules in a computer system |
WO1994003860A1 (en) | 1992-08-07 | 1994-02-17 | Thinking Machines Corporation | Massively parallel computer including auxiliary vector processor |
US5566341A (en) | 1992-10-05 | 1996-10-15 | The Regents Of The University Of California | Image matrix processor for fast multi-dimensional computations |
DE69330399T2 (de) | 1992-12-18 | 2002-05-02 | Advanced Micro Devices Inc | HDLC-Empfänger |
US5566302A (en) | 1992-12-21 | 1996-10-15 | Sun Microsystems, Inc. | Method for executing operation call from client application using shared memory region and establishing shared memory region when the shared memory region does not exist |
US5524192A (en) | 1993-02-09 | 1996-06-04 | International Business Machines Corporation | Simplifying maintaining and displaying of program comments |
US5544091A (en) | 1993-03-05 | 1996-08-06 | Casio Computer Co., Ltd. | Circuit scale reduction for bit-serial digital signal processing |
US5712996A (en) | 1993-03-15 | 1998-01-27 | Siemens Aktiengesellschaft | Process for dividing instructions of a computer program into instruction groups for parallel processing |
US5475842A (en) | 1993-08-11 | 1995-12-12 | Xerox Corporation | Method of compilation optimization using an N-dimensional template for relocated and replicated alignment of arrays in data-parallel programs for reduced data communication during execution |
US5426694A (en) | 1993-10-08 | 1995-06-20 | Excel, Inc. | Telecommunication switch having programmable network protocols and communications services |
US5613139A (en) | 1994-05-11 | 1997-03-18 | International Business Machines Corporation | Hardware implemented locking mechanism for handling both single and plural lock requests in a lock message |
US5696991A (en) | 1994-11-29 | 1997-12-09 | Winbond Electronics Corporation | Method and device for parallel accessing data with optimal reading start |
US5680597A (en) | 1995-01-26 | 1997-10-21 | International Business Machines Corporation | System with flexible local control for modifying same instruction partially in different processor of a SIMD computer system to execute dissimilar sequences of instructions |
US5729748A (en) | 1995-04-03 | 1998-03-17 | Microsoft Corporation | Call template builder and method |
US5671419A (en) | 1995-06-15 | 1997-09-23 | International Business Machines Corporation | Interprocedural data-flow analysis that supports recursion while only performing one flow-sensitive analysis of each procedure |
US5737607A (en) | 1995-09-28 | 1998-04-07 | Sun Microsystems, Inc. | Method and apparatus for allowing generic stubs to marshal and unmarshal data in object reference specific data formats |
US5887172A (en) | 1996-01-10 | 1999-03-23 | Sun Microsystems, Inc. | Remote procedure call system and method for RPC mechanism independent client and server interfaces interoperable with any of a plurality of remote procedure call backends |
US5841976A (en) | 1996-03-29 | 1998-11-24 | Intel Corporation | Method and apparatus for supporting multipoint communications in a protocol-independent manner |
US6032199A (en) | 1996-06-26 | 2000-02-29 | Sun Microsystems, Inc. | Transport independent invocation and servant interfaces that permit both typecode interpreted and compiled marshaling |
US5896517A (en) | 1997-08-18 | 1999-04-20 | Bull Hn Information Systems Inc. | High performance processor employing background memory move mechanism |
CA2236188C (en) | 1998-04-28 | 2002-10-01 | Thomas Alexander | Firmware controlled transmit datapath for high-speed packet switches |
US6106575A (en) | 1998-05-13 | 2000-08-22 | Microsoft Corporation | Nested parallel language preprocessor for converting parallel language programs into sequential code |
JP4130713B2 (ja) | 1998-10-21 | 2008-08-06 | 松下電器産業株式会社 | プログラム変換装置 |
US7243333B2 (en) * | 2002-10-24 | 2007-07-10 | International Business Machines Corporation | Method and apparatus for creating and executing integrated executables in a heterogeneous architecture |
US7493606B2 (en) | 2004-08-03 | 2009-02-17 | Université du Québec à Chicoutimi (UQAC) | Method for compiling and executing a parallel program |
US7512738B2 (en) | 2004-09-30 | 2009-03-31 | Intel Corporation | Allocating call stack frame entries at different memory levels to functions in a program |
US8046777B2 (en) | 2005-06-02 | 2011-10-25 | The Mathworks, Inc. | Calling of late bound functions from an external program environment |
US8010953B2 (en) | 2006-04-04 | 2011-08-30 | International Business Machines Corporation | Method for compiling scalar code for a single instruction multiple data (SIMD) execution engine |
US8201159B2 (en) | 2006-08-04 | 2012-06-12 | International Business Machines Corporation | Method and apparatus for generating data parallel select operations in a pervasively data parallel system |
US8196127B2 (en) | 2006-08-04 | 2012-06-05 | International Business Machines Corporation | Pervasively data parallel information handling system and methodology for generating data parallel select operations |
US8739022B2 (en) * | 2007-09-27 | 2014-05-27 | The Research Foundation For The State University Of New York | Parallel approach to XML parsing |
US8261234B1 (en) * | 2008-02-15 | 2012-09-04 | Nvidia Corporation | System, method, and computer program product for compiling code adapted to execute utilizing a first processor, for executing the code utilizing a second processor |
US8863104B2 (en) | 2008-06-10 | 2014-10-14 | Board Of Regents, The University Of Texas System | Programming model and software system for exploiting parallelism in irregular programs |
US8627042B2 (en) | 2009-12-30 | 2014-01-07 | International Business Machines Corporation | Data parallel function call for determining if called routine is data parallel |
US20110314256A1 (en) | 2010-06-18 | 2011-12-22 | Microsoft Corporation | Data Parallel Programming Model |
-
2010
- 2010-06-18 US US12/819,108 patent/US8589867B2/en active Active
-
2011
- 2011-06-17 CN CN201110177689.1A patent/CN102314342B/zh active Active
Patent Citations (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN1499362A (zh) * | 2002-10-24 | 2004-05-26 | 国际商业机器公司 | 在异构体系结构的集成可执行程序中用多个代码访问全局变量的系统和装置 |
Non-Patent Citations (1)
Title |
---|
Re-scheduling invocations of services for RPC grids;Gautier et al.;《COMPUTER LANGUAGES,SYSTERMS & STRUCTURES》;20060724;第33卷;第168至178页 * |
Also Published As
Publication number | Publication date |
---|---|
US8589867B2 (en) | 2013-11-19 |
US20110314444A1 (en) | 2011-12-22 |
CN102314342A (zh) | 2012-01-11 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN102314342B (zh) | 用于数据并行编程模型的编译器生成的调用存根 | |
González‐Vélez et al. | A survey of algorithmic skeleton frameworks: high‐level structured parallel programming enablers | |
Nugteren et al. | Introducing'Bones' a parallelizing source-to-source compiler based on algorithmic skeletons | |
US20120317059A1 (en) | System and method for space and resource optimization | |
US20110314256A1 (en) | Data Parallel Programming Model | |
CN110149802A (zh) | 用于在虚拟图像处理器指令集架构(isa)与具有二维移位阵列结构的目标硬件之间进行转译的编译器 | |
CN107145344A (zh) | 在基于图的程序中指定组件 | |
Yu et al. | S2FA: An accelerator automation framework for heterogeneous computing in datacenters | |
Tejedor et al. | A high‐productivity task‐based programming model for clusters | |
Lepley et al. | A novel compilation approach for image processing graphs on a many-core platform with explicitly managed memory | |
Bosilca et al. | The Template Task Graph (TTG)-an emerging practical dataflow programming paradigm for scientific simulation at extreme scale | |
Rasch et al. | dOCAL: high-level distributed programming with OpenCL and CUDA | |
Ma et al. | Generic parallel programming for massive remote sensing data processing | |
de Jong et al. | An environmental modelling framework based on asynchronous many-tasks: Scalability and usability | |
Aumage et al. | Combining both a component model and a task-based model for hpc applications: a feasibility study on gysela | |
Moreton-Fernandez et al. | Exploiting distributed and shared memory hierarchies with Hitmap | |
Ernstsson | Pattern-based Programming Abstractions for Heterogeneous Parallel Computing | |
Dekate | Extreme scale parallel nbody algorithm with event driven constraint based execution model | |
Khammassi | High-level structured programming models for explicit and automatic parallelization on multicore architectures | |
Saied | Automatic code generation and optimization of multi-dimensional stencil computations on distributed-memory architectures | |
Dünnweber et al. | Higher-Order Components for Grid Programming: Making Grids More Usable | |
Papadopoulos | STAPL-RTS: A Runtime System for Massive Parallelism | |
Majidi et al. | Nested parallelism with algorithmic skeletons | |
Falcou | Software Abstractions for Parallel Architectures | |
West | Combining control and data parallelism: Data parallel extensions to the Mentat programming language |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
C06 | Publication | ||
PB01 | Publication | ||
C10 | Entry into substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
ASS | Succession or assignment of patent right |
Owner name: MICROSOFT TECHNOLOGY LICENSING LLC Free format text: FORMER OWNER: MICROSOFT CORP. Effective date: 20150717 |
|
C41 | Transfer of patent application or patent right or utility model | ||
TA01 | Transfer of patent application right |
Effective date of registration: 20150717 Address after: Washington State Applicant after: Micro soft technique license Co., Ltd Address before: Washington State Applicant before: Microsoft Corp. |
|
C14 | Grant of patent or utility model | ||
GR01 | Patent grant |