---
title: 矩阵向量乘
description: "矩阵向量乘（General Matrix-Vector multiplication），即GEMV，是指Matmul计算中M=1，形状为(1, K)的左矩阵A与形状为(K, N)的右矩阵B进行矩阵乘运算的场景。Matmul支持在Tiling侧与Kernel侧通过配置A矩阵的数据格式为VECTOR来开启GEMV模式，从而高效处理M=1的计算场景。若在M=1时未开启GEMV模式，Matmul计算则将M方向作为非对齐场景进行处理。GEMV模式相较于非对齐处理方式，搬运数据量更少，性能更好。"
url: https://www.hiascend.com/document/detail/zh/canncommercial/latest/programug/Ascendcopdevg/atlas_ascendc_10_10019.html
sourcePath: /source/zh/canncommercial/900/programug/Ascendcopdevg/atlas_ascendc_10_10019.html
indexId: 7871aac5edf0d28625b28598e6ece565b603f0c76f8f4bf581db3e69fcdbd0aa81
---
# 矩阵向量乘

#### 功能介绍

矩阵向量乘（General Matrix-Vector multiplication），即GEMV，是指Matmul计算中M=1，形状为(1, K)的左矩阵A与形状为(K, N)的右矩阵B进行矩阵乘运算的场景。Matmul支持在Tiling侧与Kernel侧通过配置A矩阵的数据格式为VECTOR来开启GEMV模式，从而高效处理M=1的计算场景。若在M=1时未开启GEMV模式，Matmul计算则将M方向作为非对齐场景进行处理。GEMV模式相较于非对齐处理方式，搬运数据量更少，性能更好。

以M=1，K=256，N=32，左右矩阵数据类型为half的Matmul为具体示例，说明GEMV模式的Matmul API内部处理过程。

- GEMV模式
  将A矩阵从A1搬运到A2时，1*256的向量被当作16*16的矩阵进行处理，调用LoadData(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc_api_07_0238.html)接口一次完成16*16分形大小的矩阵搬运。B矩阵的搬运以及矩阵乘计算跟基础场景相同，如下图所示。

  图1 GEMV模式M=1的矩阵乘计算示意图

- 非GEMV模式
  将A矩阵从A1搬运到A2时，1*256的向量被当作非对齐矩阵数据进行处理，将M方向对齐到32字节后进行搬运。调用LoadData(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc_api_07_0238.html)接口每次搬运16*16分形大小的矩阵，一共搬运K/16=16次，导致搬运数据量增加，性能相较于GEMV模式差，如下图所示。

  图2 非GEMV模式M=1的矩阵乘计算示意图


#### 使用场景

形状为(1, K)的A矩阵（M=1，K>1）做矩阵乘计算，即输入A矩阵的数据是向量数据。


#### 约束说明

- 在Matmul计算中，若要开启GEMV模式，A矩阵的原始输入形状M必须等于1。

- GEMV场景下，左矩阵A不支持转置。
- GEMV场景下，Global Memory上的左矩阵数据需要保证16字节对齐。
-   MxMatmul场景
计算矩阵向量乘时，左矩阵A和左量化系数矩阵scaleA仅支持内存逻辑位置为TPosition::GM。


#### 调用示例

完整的算子样例请参考matmul_gemv算子样例(https://gitcode.com/cann/asc-devkit/tree/9.0.0/examples/01_simd_cpp_api/03_libraries/00_matrix/matmul_gemv)。

- Tiling实现
  调用SetAType(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc_api_07_0674.html)接口，设置A矩阵的数据格式为CubeFormat::VECTOR，其它Tiling实现与基础场景相同。 1 2 3 4 5 6 7 8 9 10 auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); matmul_tiling::MatmulApiTiling tiling(ascendcPlatform); // 调用设置A矩阵的格式为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); ... // 其他实现内容 optiling::TCubeTiling tilingData; int ret = tiling.GetTiling(tilingData);

- Kernel实现
  相较于基础场景，GEMV场景在创建Matmul对象时，设置模板参数A_TYPE的数据格式为CubeFormat::VECTOR。 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;
