昇腾社区首页
EN
注册

矩阵向量乘

功能介绍

矩阵向量乘(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接口一次完成16*16分形大小的矩阵搬运。B矩阵的搬运以及矩阵乘计算跟基础场景相同,如下图所示。
    图1 GEMV模式M=1的矩阵乘计算示意图
  • 非GEMV模式
    将A矩阵从A1搬运到A2时,1*256的向量被当作非对齐矩阵数据进行处理,将M方向对齐到32字节后进行搬运。调用LoadData接口每次搬运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不支持转置。

调用示例

  • Tiling实现
    调用SetAType接口,设置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;