General Matrix-Vector Multiplication
Overview
General Matrix-Vector Multiplication, or GEMV, refers to a scenario in which matrix multiplication is performed on the left matrix A with shape (1, K) and a right matrix B with shape (K, N) in Matmul computation when M is 1. Matmul allows you to enable the GEMV mode by setting the data format of matrix A to VECTOR in the tiling process and on the kernel. In this way, the computation scenario where M is 1 can be efficiently processed. If the GEMV mode is disabled when M is 1, the M direction is processed as a non-alignment scenario during Matmul computation. Compared with the non-alignment processing mode, the GEMV mode moves less data and provides better performance.
The following uses Matmul with M = 1, K = 256, N = 32, and the data type of both the left and right matrices being half, as an example to illustrate the internal processing process of the Matmul API in GEMV mode.
- GEMV
When matrix A is moved from A1 to A2, the 1 x 256 vector is processed as a 16 x 16 matrix. The LoadData API is called to move the 16 x 16 fractal matrix at once. The movement and matrix multiplication of matrix B are the same as those in basic scenarios, as shown in the following figure.
Figure 1 Matrix multiplication in GEMV mode (M = 1)
- Non-GEMV
When matrix A is moved from A1 to A2, the 1 x 256 vector is processed as non-aligned matrix data. The M direction needs to be 32-byte aligned before the movement. The LoadData API is called to move a 16 x 16 fractal matrix each time, for a total of 16 times (K/16). As a result, the amount of moved data increases, and the performance is poorer than that in GEMV mode, as illustrated in the following figure.
Figure 2 Matrix multiplication in non-GEMV mode (M = 1)
Application Scenarios
Matrix multiplication is performed on matrix A (M = 1, K > 1) with the shape of (1, K). In other words, the input matrix A consists of vector data.
Restrictions
- In Matmul computation, the precondition for enabling GEMV is that M, the original input shape of matrix A, must be 1.
- In the GEMV scenario, the left matrix A cannot be transposed.
- In the GEMV scenario, the left matrix data in the global memory must be 16-byte aligned.
Example
For a complete operator example, see matmul_gemv operator sample.
- Tiling implementation
Call the SetAType API to set the data format of matrix A to CubeFormat::VECTOR. Other tiling implementation details are the same as those in basic scenarios.
1 2 3 4 5 6 7 8 9 10
auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); matmul_tiling::MatmulApiTiling tiling(ascendcPlatform); // Call the API to set the format of matrix A to CubeFormat::VECTOR. tiling.SetAType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::VECTOR, matmul_tiling::DataType::DT_FLOAT16); tiling.SetBType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT16); tiling.SetCType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT); tiling.SetBiasType(AscendC::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT); ... // Other implementation details. optiling::TCubeTiling tilingData; int ret = tiling.GetTiling(tilingData);
- Kernel implementation
In the GEMV scenario, when a Matmul object is created, the data format of the template parameter A_TYPE is set to CubeFormat::VECTOR. This is different from basic scenarios.
1 2 3 4 5 6 7
#include "lib/matmul_intf.h" using A_TYPE = AscendC::MatmulType<AscendC::TPosition::GM, CubeFormat::VECTOR, half>; using B_TYPE = AscendC::MatmulType<AscendC::TPosition::GM, CubeFormat::ND, half>; using C_TYPE = AscendC::MatmulType<AscendC::TPosition::GM, CubeFormat::ND, float>; using BIAS_TYPE = AscendC::MatmulType<AscendC::TPosition::GM, CubeFormat::ND, float>; AscendC::Matmul<A_TYPE, B_TYPE, C_TYPE, BIAS_TYPE> mm;