存内计算 | UPMEM PIM 概述

1,186 阅读7分钟

引言

随着摩尔定律的逐渐失效,大数据和人工智能等数据密集型应用正挑战当前架构在内存带宽上的限制。此外,数据移动所带来的能耗成为计算节点内的主要能源成本,导致系统能耗高且操作频繁受阻。存内计算作为新的绕过内存墙的解决方案,面临着难以商业化的困难,如Intel的3D堆叠内存方案受到能耗与散热的阻碍难以实现。UPMEM是首家在DRAM存储芯片上集成处理器(DPU)与DDR4 DRAM内存的公司,也是首家实现通用化存内计算和商业化的公司。通过在数据所在位置进行计算,以微小的能源增加和硬件占用率,只需在CPU与DRAM之间传输程序指令和结果,而非数据本身,UPMEM PIM有潜力成为数据密集型应用的下一代计算架构。

本文基于 UPMEM PIM 白皮书和SDK用户手册整理。

UPMEM PIM 硬件架构

DPU

DPU 是执行计算的最基本单位。DPU 是一种RISC处理器,具有接近传统的指令集架构(ISA),包含100条48位指令。指令通过 DDR 总线读取和写入。DPU既没有指令缓存也没有数据缓存,但有一个称为指令RAM(IRAM)的指令内存和一个称为工作RAM(WRAM)的暂存器内存。

每个 DPU 与主 CPU 共享对一个称为主内存 RAM(MRAM)的 DRAM bank 的访问权,用于复制输入数据(从主内存到MRAM)和检索结果(从MRAM到主内存)。操作模式使得 DRAM bank 轮流属于CPU和DPU。

将DPU及其DRAM、DDR和PIM接口结合起来统称为一个PIM单元作为PIM芯片的组成部分。

image.png

PIM 芯片

在每个内存芯片内,有8个DPU共存。DPU之间的内存是独立的,并且是异步的,DPU之间没有直接的通信渠道。因此,所有DPU之间的通信都通过主CPU来完成,通过从DPU检索结果到CPU以及从CPU复制数据到DPU来实现。

PIM 模块

UPMEM模块在每侧分别嵌入了8个PIM芯片,共16个,每个DIMM模块内有128个DPU。它采用标准DDR4-2400 DIMM的形态,可以轻松地插入标准服务器。标准的DIMM和UPMEM的DIMM可以共存,支持常规处理和PIM处理。与普通DRAM相比,制造PIM-DRAM芯片的额外成本非常小。

image.png

PIM 服务器

PIM服务器是一种标准的应用服务器,其中大多数标准的DRAM DIMM插槽都安装了PIM DIMM。服务器固件被配置为识别这种特定的配置。一个常规的配置总共有2560个DPU,以及160GB的PIM DRAM,分布在20个PIM模块上。

image.png

UPMEM PIM SDK

开发DPU程序需要分别编写DPU端的实际运算程序和主机端的程序用于配置、分配和调度DPU。UPMEM提供了一个SDK以及一套工具包和调试器用于DPU和主机编程,包括DPU运行时库、主机端通信库、LLVM编译器、LLDB调试器和功能模拟器。主机端的程序可以使用C语言编写,也可以利用SDK提供的使用C++、Java和Python包装后的API,DPU端的程序只能使用C语言编写。

DPU运行时库

运行时服务库包括C标准库的一个子集,符合ISO C11规范,但排除了不适合UPMEM DPU环境的函数,如IO文件操作。

该库提供了线程(称为tasklet)的抽象。tasklet 是一个软件抽象,为底层相关的硬件线程提供了一些系统能力(如栈)。基于 tasklet 的能力,运行时库提供了各种同步原语:互斥锁、信号量、屏障和握手。

运行时库为以下功能定义了原语:

  • WRAM管理:动态管理WRAM。
  • MRAM访问:管理MRAM与WRAM之间和MRAM与IRAM之间的事务。

tasklet 有可能获取工作内存中的缓冲区供自用,或访问一些预先保留的共享内存进行协作工作。MRAM管理例程定义了一系列简化MRAM与WRAM之间事务的函数,考虑到UPMEM DPU定义的对齐和大小约束。还定义了一些函数用于简化了涉及此类事务的编程模型。

主机端通信库

主机端通信库提供了函数用于在主机内存与任何DPU内存(IRAM、WRAM或MRAM)之间传输数据。可以将一个缓冲区传输到单个DPU,广播到一组DPU,或者在一次传输中将不同的缓冲区推送到一组DPU。

LLVM编译器和LLDB调试器

DPU 的编译器基于 LLVM 编译器基础架构,使用 clang 10.0.0。提供了一些 LLVM 编译工具链的实用工具,如 llvm-objdump、llvm-objcopy 或 llvm-readelf。生成的二进制文件是标准的 ELF 文件,适用于 DPU架构。

UPMEM 开发了一个基于 lldb 10.0.0 的调试工具,可以同时作用于 CPU 和 DPU,能够精确指定组或单个 DPU。此外,还提供了指令级调试和性能分析选项。面向性能的低级性能分析可以用于了解程序在等待特定 DPU 时的情况。

功能模拟器

工具包中同时提供了功能模拟器用于缺乏 UPMEM 硬件时进行预备工作。模拟器包括指令追踪和DPU grind,但是不具有周期精确性。这种模拟器可用于进行预备开发工作,但不允许进行性能评估。要进行真实的性能评估,可以使用 UPMEM 云服务器。对于周期级的精确性,也可以使用KAIST开源的 uPIMulator

DPU 编程模型

并发编程

DPU 通过 tasklet 实现并发编程,tasklet 一对一对应硬件线程,硬件线程实现任务级并行。tasklet 通过以下限制减少了线程的执行范围:

  • 启动:每个 tasklet 在启动时都会执行主函数。
  • 同步:不能被停止,但可以通过同步原语(如互斥)暂停其执行。
  • 内存:在 WRAM 中拥有一个特定的空间来存储其执行栈。

tasklet 共享相同的内存空间,在源代码中声明的任何全局变量都可以被任何tasklet访问,无论其作用域是什么(静态或非静态)。

每个 tasklet 都有一个系统名称,可以通过在defs.h中定义的函数me()获取,返回一个唯一的系统名称(sysname_t)。

内存管理

DPU 运行时库定义了各存储器的具体用法

  • WRAM:是程序的执行存储器,是放置堆、栈、全局变量等的位置。在 WRAM 中,运行时配置定义了特定的内存区域来实现堆和共享内存。
  • MRAM:被视为外部存储设备,通过运行时库简化其访问操作。

在 DPU 编程时,需要显式地在主内存和MRAM之间移动数据,并确保 CPU 和 DPU 之间的数据一致性。MRAM 和 WRAM 之间的数据移动也需要显式管理。

UPMEM PIM 应用场景

鉴于 PIM 架构和由此引发的编程范式转变,可以使用 PIM 加速运行的应用包括:

  • 能够利用高度并行操作和细粒度划分的应用,
  • 数据量达数十或数百GB且计算/数据比率密集的应用,
  • 涉及处理大量数据集、隐含大量数据移动、在这些应用上执行重要操作的应用。

技术白皮书中提供了一些已经移植或具有高潜力的应用

image.png

引用

UPMEM, “UPMEM DPU ABI,” 2021.
UPMEM, “UPMEM Processing-In-Memory (PIM) Acceleration for Data-Intensive Applications (White Paper),” 2022.