11、内存内和近内存处理架构的编程模型

内存内和近内存处理架构的编程模型

在当今的计算领域,内存内和近内存处理架构正逐渐成为提升计算性能的关键技术。这些架构通过将计算靠近内存进行,减少了数据在内存和处理器之间的传输开销,从而显著提高了计算效率。本文将深入探讨这些架构的编程模型,包括近期特定领域的模型、数据并行编程模型等方面。

近期特定领域模型

为了便于采用,许多内存内和近内存处理架构的方法将加速器集成到现有的高级特定领域编程框架中。这些框架降低了程序员的入门门槛,使他们能够专注于特定应用的优化,而无需担心应用到硬件的映射、数据管理和调度复杂性等问题。

例如,机器学习和图处理都是基于框架的。内存内和近内存机器学习加速器可以使用流行的高级框架进行编程,如TensorFlow、Microsoft CNTK、PyTorch和Caffe2。用这些特定领域语言编写的程序首先被编译成中间计算图,然后根据底层硬件进行优化。ONNX(开放神经网络交换格式)是一种流行的表示这些计算图的格式,支持多种编程框架和多种硬件。因此,许多内存内和近内存机器学习方法扩展了ONNX的前端和后端接口,以支持在自己的加速器上执行,而无需向程序员暴露这些特定于加速器的接口。

类似地,对图处理框架如GraphLab、GraphX、IBM System G和GraphMat的轻量级扩展也被提出,以支持图处理的内存内或近内存加速器。

在设计内存内和近内存处理架构的编程模型时,需要考虑以下几个关键设计决策:
1. 卸载粒度 :先前的内存内和近内存加速方法提出将单操作、批量操作、应用程序内的函数或整个应用程序卸载到智能内存架构中。对于图处理,指令级卸载已观察到显著的好处。在一些具有固定功能单元的近内存计算架构中,为每个卸载操作提出了ISA扩展。在GraphPIM中,每个对图顶点的原子指令(分配在指定的不可缓存区域)作为单独的指令卸载。Seshadri等人和Aga等人分别提出将批量按位操作卸载到支持计算的DRAM和SRAM中,并展示了对几个数据分析内核的显著好处。其他方法使用编译器指令或库调用来指定要卸载到内存的函数。虽然有一些系统将完整的应用程序卸载到内存中,但由于涉及的复杂性,卸载整个应用程序的情况很少见。
2. 编程复杂性 :许多受益于近内存处理的应用程序是基于框架的。许多数据分析工作负载在多个服务器中并行分片和处理数据,并使用分布式计算框架如Spark、Hadoop和MPI编写。为了减轻程序员的负担,许多近内存处理架构也采用类似的方法,扩展这些高级编程框架并为自己的架构进行定制。NDA、NDC、Tesseract和Active Memory Cube是基于MapReduce/MPI编程模型的内存内和近内存计算架构的例子。为了提供更大的灵活性并支持多个高级框架,其他内存内和近内存处理方法基于低级编程模型如OpenCL,广泛用于异构计算。然而,OpenCL增加了程序员的负担。另一方面,为了提供最大的灵活性和细粒度控制,许多人也提出了具有低级API和ISA扩展的自定义编程模型。这些更适合对程序行为和内存架构有详细了解的领域专家。此外,也有努力自动化识别高级程序中的卸载候选者。
3. 地址转换和缓存一致性 :支持虚拟到物理地址转换是涉及基于指针的数据结构(如树和链表)的计算内核的另一个重要要求,这些是内存内和近内存处理架构常见的加速候选者。虽然一些方法在智能内存中嵌入地址转换单元,但这些会增加系统复杂性。最近的内存内和近内存加速器倾向于通过限制加速器操作的物理内存区域来采用更简单的基于主机的转换机制。除了虚拟地址转换,为程序员提供硬件支持的一致共享内存抽象(统一主机和近数据加速器内存)可以大大简化编程。然而,细粒度的一致性协议如MESI会大大增加主机 - 内存网络流量。最近的工作CoNDA观察到,虽然一些近数据加速内核在主机和加速器之间表现出显著的数据共享,但与主机的缓存行冲突很少。CoNDA乐观地执行内核,假设所有权限都被授予,并跟踪修改的缓存行。这些修改的缓存行地址被压缩并传输到主机进行冲突检测。如果检测到冲突,内核将重新执行。

数据并行编程模型

随着内存内计算设备支持的操作符的通用性增加,人们努力将这些设备的好处扩展到更广泛的应用场景。尽管内存内计算可以提供强大的计算能力,但应用程序并不总是能轻松利用它。由于性能提升的一个来源是减少数据移动,因此正确处理输入数据成为执行流程设计的重要方面。编程模型需要考虑内存内设备的约束,同时提供程序员友好的接口和数据流的透明度。编译器则需要探索数据映射和操作调度,以充分暴露输入操作序列和硬件中的并行性。

内存内计算的机会和挑战如下:
1. 机会 :尽管内存内计算设备有显著的性能提升,但大多数加速器工作依赖于将计算内核手动映射到内存阵列或通过专门为一类工作负载设计的特定领域语言(DSL),这使得为不同应用程序配置变得困难。一种解决方法是设计一种可编程的内存内处理器架构,与通用的编程框架一起工作。据报道,通用内存内处理器有潜力将数据并行应用程序内核的性能提高一个数量级或更多。内存内处理器的效率来自两个方面。一是大规模数据并行性,例如NVM由数千个数组组成,每个数组可以转换为单指令多数据(SIMD)处理单元,能够并发计算。二是减少数据移动,避免数据在内存和处理器核心之间的洗牌。然而,NVM的读写延迟相对较大,导致算术运算的执行延迟较长。一个表达性强的内存内计算编程模型可以向应用程序和程序员暴露可计算内存设备的独特特性和机会,而无需大量重写程序。
2. 挑战 :通用内存内计算的一个挑战是拥有丰富的计算原语,以满足广泛的数据密集型应用程序。虽然许多工作支持逻辑和定点算术运算,但许多数据并行工作负载需要复杂的算术运算,如超越函数和高精度算术,如浮点数。在内存内向量架构中基于指数操作尾数是一个不小的挑战。另一个挑战是设计CPU核心和计算内存之间的接口、执行模型和内存寻址。内存内操作的操作数需要在位线ALU上对齐,这限制了它们在内存中的特定位置。编程模型对可编程性和架构设计有直接而显著的影响。简单的模型(如宽SIMD)简化了硬件,但以有限的灵活性为代价。另一方面,保证过多的自由可能会导致为了处理所有计算和通信模式而过度配置硬件资源。从程序员的角度来看,希望遵循或与广泛使用的编程模型兼容,以减少重写程序的工作量并提供跨平台兼容性。现有的GPU和机器学习编程模型已经为数据并行程序提供了很好的表达能力,这些程序是内存内计算的主要目标。

下面介绍两种具体的编程模型:
1. SIMD编程 :IMP将基于ReRAM的内存内计算设备视为一个大型SIMD处理器,并提出通过合并数据流和SIMD向量处理的概念来利用硬件中的底层并行性。数据流明确暴露程序中的指令级并行性(ILP),而向量处理暴露数据级并行性(DLP)。他们使用Google的TensorFlow,因为观察到TensorFlow的编程语义是数据流和向量处理的良好结合,可以应用于更通用的应用程序。

TensorFlow为数据并行内存内计算提供了合适的编程范式:
- 节点可以操作多维矩阵,嵌入了SIMD编程模型,便于向编译器暴露数据级并行性。
- 不规则内存访问受到限制,不允许下标表示法,这对程序员和编译器都有益。
- 数据流图自然暴露指令级并行性,可由编译器用于超长指令字(VLIW)风格的调度,以进一步利用硬件中的底层并行性。
- 支持在数据流图节点中的持久内存上下文,在数据可以在不同内核调用中重用的情况下很有用。

TensorFlow通过选择指令支持简单的控制流。编译和执行SIMD程序时,TensorFlow程序本质上是数据流图,编译器将输入的数据流图转换为具有相同机器代码的数据并行模块集合。在运行时,代码模块多次实例化并处理独立的数据元素。编译器还执行一些数据流图优化,如展开高维张量、合并数据流图节点以利用n元ReRAM操作、流水线计算和写回、使用VLIW风格调度最大化模块内的ILP以及最小化数组之间的通信。在运行时,模块的不同实例以同步方式对输入向量的不同元素执行相同的指令。
2. SRAM上的SIMT编程 :TensorFlow为并行内存内计算提供了合适的编程范式,但并非所有程序都可向量化,一些具有不规则内存访问的应用程序可能在这些框架中面临困难。此外,主内存中的内存内计算对数据流和数据结构有相对严格的限制,因为内部互连带宽不是为任意通信模式设计的,这也会影响不可向量化的程序。

Duality Cache(DC)采用CUDA/OpenACC作为编程模型,并提出了一个编译器,可以将任意CUDA/OpenACC程序转换为DC的ISA,用于SRAM上的缓存内计算。DC架构扩展了Compute Caches和Neural Cache的计算能力,用于通用计算。编译器分配资源、调度VLIW指令,并进行一些优化,以利用缓存内架构中的独特机会。

CUDA将内核描述为多线程程序,并将线程分组为线程束。在线程束中,线程以同步方式执行。线程间同步和共享允许在称为线程块或协作线程数组(CTA)的线程组内进行。不同的CTA是独立的,可以按任何顺序调度和执行。缓存内计算从这个编程模型中受益于两个方面。首先,CUDA是一个流行且广泛使用的框架,跨越从科学计算到机器学习的不同领域。将其用于缓存内计算架构,通过直接翻译或进行微小的源代码更改,可以实现可移植性并利用现有软件。其次,独立的CTA需要最少的网络资源来进行在线程块内本地发生的线程间通信。

DC也支持OpenACC。OpenACC为程序员提供类似OpenMP的编译指示,使将现有串行程序转换为并行程序变得更容易。目前,商用OpenACC编译器支持多线程、多核CPU和NVIDIA GPU。OpenACC的特点是能够使用编译指示描述主机上的串行计算和要在加速器(如GPU)上执行的并行内核的细粒度交织。虽然GPU对于那些具有频繁主机 - 设备通信的OpenACC程序往往面临通信瓶颈,但DC由于缓存与主机共享相同的内存层次结构,实现了主机代码和内核代码之间的无缝执行。

执行和编译SIMT程序时,DC的SIMT执行模型比GPU更简单和粗粒度。DC允许缓存以两种模式运行:加速器模式和缓存模式。在加速器模式下,缓存数组中的位线成为SIMT处理器的一个线程通道。在缓存内计算模式下,寄存器和计算单元相同。DC将线程中的寄存器分配到位线并就地执行计算。操作数在映射到位线的寄存器内垂直对齐。在缓存模式下,缓存数组是处理器传统多级内存层次结构的一部分。

DC将整个包含四个SRAM数组的存储体分配给一个线程块(TB),以提供每个线程足够数量的寄存器并防止频繁的寄存器溢出。一个SRAM数组沿位线有256位单元,因此只能提供八个32位位串行寄存器。通过将256个线程分配给一个包含四个SRAM数组的存储体,DC可以为每个线程提供32个32位位串行寄存器。因此,TB中的每个线程实际上映射到存储体中的多个数组,每个成员数组有一部分寄存器。线程间通信仅允许在线程块内进行。这种设计选择是为了平衡可编程性和硬件复杂性。一个256×256的本地交叉开关在C - Box中用于洗牌/广播CTA本地数据。

将TB映射到四个数组的存储体使每个数组能够在同一周期执行不同的操作。DC执行类似VLIW的指令调度。VLIW允许DC以低硬件复杂性利用程序中的ILP,因为编译器处理复杂的ILP感知调度。DC以位串行方式执行计算。每个位线作为一个计算单元,数组中的所有位线像SIMD处理器一样执行相同的操作。

DC编译器将CUDA代码转换为VLIW SIMD ISA。与传统的VLIW架构不同,DC架构必须考虑操作数的局部性;所有操作数需要驻留在执行操作的数组中,否则操作数必须显式复制。

寄存器压力和高效的VLIW指令调度是不可分割的问题。在DC中,指令调度与资源分配紧密耦合。虽然许多VLIW架构的编译器在寄存器分配之前先调度指令以利用许多执行单元共享的丰富寄存器资源来最大化并行性,但DC的私有寄存器数量有限,这可能导致频繁的寄存器溢出。另一方面,先进行资源分配的方法通常会引入许多虚假依赖关系,以换取最小化的寄存器使用,这可能会减少可用的并行性。DC通过同时执行资源分配和指令调度来解决这个问题。DC使用Bottom - Up Greedy作为基线调度算法,线性扫描寄存器分配作为基线资源分配算法。通过在执行指令调度时考虑寄存器压力,编译器可以选择更好的策略来平衡并行性和寄存器溢出。

需要注意的是,内存内计算不能轻易集成到现有的软件/硬件堆栈中,原因如下:
- 内存内计算通常需要特殊的数据映射和寻址。例如,DRAM和NVM的内存内向量计算通常要求操作数在同一列中对齐,而位串行计算进一步要求操作数位进行转置。
- 为了允许内存内计算使用一部分内存,系统必须支持灵活分配该区域,用于类似暂存储存器的用途。例如,一些工作将SRAM缓存重新用于本地暂存储存器,这些工作通常需要对操作系统和硬件进行小的更改。DRAM通常使用基于XOR的地址映射来利用存储体和通道并行性,通过在物理地址空间中将连续的缓存块分布在DRAM存储体和通道中。为了将页面对齐到同一子数组,操作系统必须分配具有特定地址的物理页面,并且数据应根据CPU微架构的XOR地址映射写入特定的缓存块。
- 此外,高效的按需数据转换(如转置)可能需要专门的硬件。例如,Neural Cache使用转置内存单元(TMU),它使用8 - T转置位单元来转置位。内存控制器可能需要管理内存内计算的操作数寻址和数据加载/存储,以避免与主机CPU的昂贵通信。
- 内存内计算可能需要支持启用ECC的高可靠性并解决潜在的安全问题。

综上所述,内存内和近内存处理架构的编程模型为提高计算性能提供了新的途径,但也面临着许多挑战。在设计和应用这些编程模型时,需要综合考虑卸载粒度、编程复杂性、地址转换和缓存一致性等因素,以充分发挥这些架构的优势。同时,要注意内存内计算集成到现有软件/硬件堆栈中的困难,并采取相应的措施来解决这些问题。

内存内和近内存处理架构的编程模型(续)

编程模型的综合分析与对比

为了更清晰地了解不同编程模型的特点和适用场景,我们对上述提到的几种编程模型进行综合分析与对比。以下是一个简单的对比表格:
| 编程模型 | 适用架构 | 优点 | 缺点 | 适用场景 |
| — | — | — | — | — |
| 基于高级特定领域框架(如TensorFlow用于机器学习) | 内存内和近内存机器学习加速器 | 降低程序员入门门槛,可专注应用优化;支持多种硬件和框架;便于扩展 | 可能存在一定的领域局限性 | 机器学习、图处理等特定领域应用 |
| OpenCL | 内存内和近内存处理架构 | 提供一定灵活性,支持异构计算 | 增加程序员负担 | 需要一定灵活性且程序员对底层有一定了解的场景 |
| 自定义编程模型(低级API和ISA扩展) | 内存内和近内存处理架构 | 提供最大灵活性和细粒度控制 | 适合领域专家,对程序员要求高 | 对程序行为和内存架构有深入了解的专业场景 |
| SIMD编程(IMP基于ReRAM和TensorFlow) | 基于ReRAM的内存内计算设备 | 利用硬件底层并行性,结合数据流和向量处理;编程语义适合数据并行计算 | 可能不适用于非向量化程序 | 数据并行应用,可向量化的程序 |
| SIMT编程(DC基于CUDA/OpenACC) | SRAM上的缓存内计算架构 | 支持多线程,实现主机代码和内核代码无缝执行;可移植性好 | 对内存结构和通信有一定限制 | 通用计算,多线程程序 |

从这个表格中可以看出,不同的编程模型各有优劣,选择合适的编程模型需要根据具体的应用场景、硬件架构以及程序员的技能水平来决定。

未来发展趋势

随着计算需求的不断增长和硬件技术的不断进步,内存内和近内存处理架构的编程模型也将不断发展。以下是一些可能的未来发展趋势:
1. 更通用的编程模型 :目前的编程模型大多针对特定领域或硬件架构,未来可能会出现更通用的编程模型,能够支持多种类型的内存内和近内存处理架构,以及更广泛的应用场景。这样可以降低程序员的学习成本,提高编程效率。
2. 自动化优化 :如前文提到的,已经有努力自动化识别高级程序中的卸载候选者。未来,这种自动化优化技术可能会更加成熟,能够自动进行数据映射、操作调度和资源分配等优化,进一步提高计算性能。
3. 与新兴技术的融合 :随着人工智能、大数据等新兴技术的发展,内存内和近内存处理架构的编程模型可能会与这些技术进行更深入的融合。例如,结合深度学习框架的自动微分机制,进一步优化内存内机器学习加速器的编程模型。
4. 安全性和可靠性的提升 :内存内计算可能面临一些安全和可靠性问题,未来的编程模型可能会更加注重这些方面的设计,提供更好的安全机制和错误处理能力。

实际应用案例分析

为了更好地理解内存内和近内存处理架构编程模型的实际应用,我们来看一个简单的实际应用案例。假设我们有一个大规模的图处理任务,需要对一个包含数百万个节点和边的图进行分析。

选择编程模型 :考虑到图处理的特点,我们可以选择基于图处理框架的编程模型,如对GraphLab进行轻量级扩展以支持近内存加速器的模型。这种模型可以利用近内存处理的优势,减少数据传输开销。

操作步骤
1. 数据准备 :将图数据加载到内存中,并根据编程模型的要求进行数据映射和寻址。确保数据按照特定的格式存储,以便于后续的计算。
2. 编写程序 :使用扩展后的GraphLab框架编写图处理程序。在程序中,根据卸载粒度的考虑,将一些计算密集型的操作(如节点更新、边遍历等)卸载到近内存加速器中。可以使用编译器指令或库调用来指定卸载的函数。
3. 编译和优化 :使用相应的编译器对程序进行编译,并进行必要的优化。编译器会进行数据映射和操作调度,以充分利用硬件的并行性。例如,可能会进行指令级卸载,将一些原子指令直接发送到近内存加速器执行。
4. 执行程序 :将编译好的程序在近内存处理架构上执行。在执行过程中,注意观察程序的性能指标,如执行时间、内存使用等。如果发现性能不理想,可以根据情况调整卸载粒度、优化数据映射等。
5. 结果分析 :对程序执行的结果进行分析,评估编程模型的效果。可以与传统的图处理方法进行对比,验证近内存处理和编程模型的优势。

通过这个实际应用案例,我们可以看到内存内和近内存处理架构编程模型在实际应用中的具体操作流程和优势。

总结

内存内和近内存处理架构的编程模型为提高计算性能带来了新的机遇,但也面临着诸多挑战。不同的编程模型适用于不同的场景,在选择和应用时需要综合考虑各种因素。未来,随着技术的不断发展,编程模型将不断完善和创新,为计算领域带来更多的突破。

为了更直观地展示整个内存内和近内存处理架构编程模型的流程,我们可以用mermaid绘制一个简单的流程图:

graph LR
    A[选择编程模型] --> B[数据准备]
    B --> C[编写程序]
    C --> D[编译和优化]
    D --> E[执行程序]
    E --> F[结果分析]
    F --> G{是否满足需求}
    G -- 是 --> H[结束]
    G -- 否 --> A

这个流程图展示了从选择编程模型到最终结果分析的整个过程,如果结果不满足需求,还可以重新选择编程模型进行优化。

总之,内存内和近内存处理架构的编程模型是一个充满潜力和挑战的领域,需要我们不断地探索和研究,以推动计算技术的发展。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值