不久之前的一篇分享里,我介绍了AMD CDNA架构(MI210, MI250, MI300)上的异步拷贝相关指令,在BitBLAS可以找到相关的实现,然而实际过程中发现AMD的异步拷贝指令的要求实际上要比那篇分享所写的更加苛刻,每个warp里的线程必须要求访问连续的数据,或者通过M0寄存器来控制每个线程的偏置。
一般来说,我们习惯这个指令就是明确的要load给定指针的一小块数据就行了,但是这个指令因为上述提到的两个限制就很难做到。经过笔者非常繁琐的Micro bencmark之后,笔者终于调教出了可以让每个线程Load给定数据块的写法,如下:
1 |
|
在这篇文章里,笔者填一下AMD Matrix Core的坑,介绍一下过去一个月里BitBLAS针对AMD的的高性能Matrix Core支持,在这篇文章里笔者将介绍一下MFMA(AMD版的MMA)。如何进行AMD Kernel的性能分析,及Profile一个AMD Kernel,最后我们介绍若干种绞尽了笔者脑汁的优化方法,完全利用好硬件的带宽(全都是128bits的内存访问指令,并且没有Memory bank conflict)。
这篇文章涉及到的算子有矩阵乘法和Flash Attention。本篇文章的实现在BitBLAS里, Codegen以及Swizzle等Layout变换依托于TVM, TVM可以帮助我们显式地操作一个数据的Layout,相比Triton更加灵活和可观。虽然AMD提供的文档十分有限,但是在这一个月里笔者参考了很多AMD开发人员提供的实现,例如Composable Kernel和Triton for ROCm,笔者从这些项目中收获良多。
本文假设读者对Nvidia GPU的编程有一定的了解,熟悉最基本的Tile优化程序的方法,以及Tensor Core的基本概念。