如何在 Cupy 内核中使用 WMMA 函数?
How to use WMMA functions in Cupy kernels?
如何在cupy.RawKernel或cupy.RawModule中使用wmma::load_matrix_sync等WMMA功能?
有人可以提供一个最小的例子吗?
我们可以结合cupy RawKernel
and wmma programming to provide most of the needed material. I don't intend to give a tutorial on wmma programming, there are other resources for that such as this blog and the cutlass template library的信息。
请注意,wmma 函数需要 7.0 或更高的计算能力。您必须 运行 在 Volta、Turing 或 Ampere GPU 上。
我们就拿编程指南中给出的kernel example来说吧。要将其放入 RawKernel
,我们需要将其作为字符串提供。为了支持内核C-style的使用,我把内核代码分解成可以使用C++的__device__
函数,同时导出内核入口点(wmma_ker
)使用C-style linkage .示例代码执行 16x16 矩阵乘法(使用单个 warp)。这是一个有效的例子:
# cat t24.py
import numpy
import cupy as cp
ddim = 16
bdim = 32
gdim = 1
a = cp.ones(ddim*ddim, dtype=cp.float16)
b = cp.ones(ddim*ddim, dtype=cp.float16)
c = cp.zeros(ddim*ddim, dtype=cp.float32)
wmma_ker = cp.RawKernel(r'''
#include <mma.h>
using namespace nvcuda;
__device__ void wmma_ker_dev(half *a, half *b, float *c) {
// Declare the fragments
wmma::fragment<wmma::matrix_a, 16, 16, 16, half, wmma::col_major> a_frag;
wmma::fragment<wmma::matrix_b, 16, 16, 16, half, wmma::row_major> b_frag;
wmma::fragment<wmma::accumulator, 16, 16, 16, float> c_frag;
// Initialize the output to zero
wmma::fill_fragment(c_frag, 0.0f);
// Load the inputs
wmma::load_matrix_sync(a_frag, a, 16);
wmma::load_matrix_sync(b_frag, b, 16);
// Perform the matrix multiplication
wmma::mma_sync(c_frag, a_frag, b_frag, c_frag);
// Store the output
wmma::store_matrix_sync(c, c_frag, 16, wmma::mem_row_major);
}
extern "C" {
__global__ void wmma_ker(half *a, half *b, float *c) {
wmma_ker_dev(a,b,c);
}
}
''', 'wmma_ker', options=("-restrict","-lineinfo"))
wmma_ker((gdim,1), (bdim,1), (a,b,c)) # grid, block and arguments
r_o = cp.asnumpy(c)
print(r_o)
# cuda-memcheck python t24.py
========= CUDA-MEMCHECK
[16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16.]
========= ERROR SUMMARY: 0 errors
#
我使用 pip install cupy-cuda102
为此设置了 cupy,否则 运行 在安装了 CUDA 10.2 和 Tesla V100 GPU 的机器上设置。我提供的 RawKernel
options
对于本演示来说是不必要的,您可以完全省略该参数。
此代码的目的是演示示例方法。我并不是说代码没有缺陷或适用于任何特定目的。需要您自担风险使用它。特别是,我不希望这段代码在任何方面发生变化时都能正常工作。我并不是说它是一个 general/flexible/extensible 矩阵乘法例程。
如何在cupy.RawKernel或cupy.RawModule中使用wmma::load_matrix_sync等WMMA功能? 有人可以提供一个最小的例子吗?
我们可以结合cupy RawKernel
and wmma programming to provide most of the needed material. I don't intend to give a tutorial on wmma programming, there are other resources for that such as this blog and the cutlass template library的信息。
请注意,wmma 函数需要 7.0 或更高的计算能力。您必须 运行 在 Volta、Turing 或 Ampere GPU 上。
我们就拿编程指南中给出的kernel example来说吧。要将其放入 RawKernel
,我们需要将其作为字符串提供。为了支持内核C-style的使用,我把内核代码分解成可以使用C++的__device__
函数,同时导出内核入口点(wmma_ker
)使用C-style linkage .示例代码执行 16x16 矩阵乘法(使用单个 warp)。这是一个有效的例子:
# cat t24.py
import numpy
import cupy as cp
ddim = 16
bdim = 32
gdim = 1
a = cp.ones(ddim*ddim, dtype=cp.float16)
b = cp.ones(ddim*ddim, dtype=cp.float16)
c = cp.zeros(ddim*ddim, dtype=cp.float32)
wmma_ker = cp.RawKernel(r'''
#include <mma.h>
using namespace nvcuda;
__device__ void wmma_ker_dev(half *a, half *b, float *c) {
// Declare the fragments
wmma::fragment<wmma::matrix_a, 16, 16, 16, half, wmma::col_major> a_frag;
wmma::fragment<wmma::matrix_b, 16, 16, 16, half, wmma::row_major> b_frag;
wmma::fragment<wmma::accumulator, 16, 16, 16, float> c_frag;
// Initialize the output to zero
wmma::fill_fragment(c_frag, 0.0f);
// Load the inputs
wmma::load_matrix_sync(a_frag, a, 16);
wmma::load_matrix_sync(b_frag, b, 16);
// Perform the matrix multiplication
wmma::mma_sync(c_frag, a_frag, b_frag, c_frag);
// Store the output
wmma::store_matrix_sync(c, c_frag, 16, wmma::mem_row_major);
}
extern "C" {
__global__ void wmma_ker(half *a, half *b, float *c) {
wmma_ker_dev(a,b,c);
}
}
''', 'wmma_ker', options=("-restrict","-lineinfo"))
wmma_ker((gdim,1), (bdim,1), (a,b,c)) # grid, block and arguments
r_o = cp.asnumpy(c)
print(r_o)
# cuda-memcheck python t24.py
========= CUDA-MEMCHECK
[16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16. 16.
16. 16. 16. 16.]
========= ERROR SUMMARY: 0 errors
#
我使用 pip install cupy-cuda102
为此设置了 cupy,否则 运行 在安装了 CUDA 10.2 和 Tesla V100 GPU 的机器上设置。我提供的 RawKernel
options
对于本演示来说是不必要的,您可以完全省略该参数。
此代码的目的是演示示例方法。我并不是说代码没有缺陷或适用于任何特定目的。需要您自担风险使用它。特别是,我不希望这段代码在任何方面发生变化时都能正常工作。我并不是说它是一个 general/flexible/extensible 矩阵乘法例程。