MemRef Dialect:内存引用与多维数组抽象 📅 2026/7/9 1:16:52 MemRef Dialect内存引用与多维数组抽象在控制流有了SCF支撑之后数据在内存中的存储与访问便成为了下一个需要解决的核心问题。在底层编译中直接操作扁平的一维指针如float*会丢失大量的高维空间信息。为了在底层依然能够高效地进行内存优化MLIR 引入了MemRef DialectMemory Reference内存引用方言。MemRef填补了高层「张量Tensor」与底层「裸指针Raw Pointer」之间的物理鸿沟。它代表了一个驻留在内存中的多维数组不仅包含了数据的首地址还打包了维度Shape、步长Strides以及布局Layout等关键元数据。核心操作OperationsMemRef Dialect 专注于内存的分配、读写和视图重塑其核心 Op 包括memref.alloc在堆上动态分配一块内存。memref.alloca在栈上分配一块局部内存通常随作用域结束自动释放。memref.load从多维坐标指定的内存位置读取一个标量值。memref.store将一个标量值写入到多维坐标指定的内存位置。memref.dealloc显式释放之前分配的内存避免内存泄漏。语法示例二维矩阵的分配与读写以下是一个标准的memref操作序列// 1. 分配一个 16x32 的单精度浮点数二维数组 %buffer memref.alloc() : memref16x32xf32 // 2. 定义坐标索引在 MLIR 中控制坐标的类型通常是 index %c0 arith.constant 0 : index %c1 arith.constant 1 : index // 3. 从坐标 (0, 1) 处加载数据 %val memref.load %buffer[%c0, %c1] : memref16x32xf32 // 4. 对数据进行处理假设加了某个值得到 %new_val // ... // 5. 将新数据写回坐标 (0, 1) memref.store %val, %buffer[%c0, %c1] : memref16x32xf32 // 6. 显式释放内存 memref.dealloc %buffer : memref16x32xf32为什么 MemRef 至关重要保留多维几何信息如果直接降级到硬件底层的扁平指针原本形如matrix[i][j]的访问会被立即拍平为matrix[i * 32 j]。这种乘加组合一旦形成后端的硬件流水线优化器如数据预取、缓存局部性优化就很难反向推导其本来的访问规律。MemRef显式保留了多维索引让编译器能清晰地看到内存访问模式。零成本的视图切片SubViewMemRef支持创建memref.subview操作。比如从一个100x100的大矩阵中切出一个10x10的子块。这个操作不需要发生任何实际的数据拷贝它仅仅是创建了一个包含新步长Strides和偏移量Offset的新MemRef描述符。这对于矩阵乘法中的分块Tiling优化至关重要。明确的数据边界显式的alloc和dealloc使得生存期分析Liveness Analysis变得非常直接方便编译器在后续阶段将其平滑地映射到 GPU 的共享内存Shared Memory或者专用的硬件缓冲区SRAM中。