news 2026/5/9 14:13:30

CANN FlashAttention反向梯度计算V4

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CANN FlashAttention反向梯度计算V4

aclnnFlashAttentionScoreGradV4

【免费下载链接】ops-transformer本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-transformer

产品支持情况

产品是否支持
Ascend 950PR/Ascend 950DT
Atlas A3 训练系列产品/Atlas A3 推理系列产品x
Atlas A2 训练系列产品/Atlas A2 推理系列产品x
Atlas 200I/500 A2 推理产品×
Atlas 推理系列产品×
Atlas 训练系列产品×

功能说明

  • 接口功能:训练场景下计算注意力的反向输出,即FlashAttentionScoreV4的反向计算。该接口query、key、value参数支持多个长度相等或者长度不相等的sequence

    • 该接口合并了FlashAttentionScoreGradV2接口和FlashAttentionUnpaddingScoreGradV2接口,并调整了Dropout功能
      • Ascend 950PR/Ascend 950DT :keepProb小于1.0时,若没有外部传入的DropoutMask,则使用新增参数生成DropoutMask;若有外部传入的DropoutMask,则使用外部传入的DropoutMask
  • 计算公式:

    • pseType=1时,与FlashAttentionScoreGrad计算公式相同
    • pseType=其他取值时,公式如下:

    $$ Y=Dropout(Softmax(Mask(\frac{QK^T}{\sqrt{d}}+pse),atten_mask),keep_prob)V $$

    为方便表达,以变量$S$和$P$表示计算公式:

    $$ S=Mask(\frac{QK^T}{\sqrt{d}}+pse),atten_mask $$

    $$ P=Dropout(Softmax(S),keep_prob) $$

    $$ Y=PV $$

    则注意力的反向计算公式为:

    $$ dV=P^TdY $$

    $$ dQ=\frac{((dS)*K)}{\sqrt{d}} $$

    $$ dK=\frac{((dS)^T*Q)}{\sqrt{d}} $$

    其中增加sink之后计算逻辑见下,主要修改相关softmax_max和softmax_sum逻辑计算部分

    $$ m = max(sink, max(S)) $$

    $$ Attention = \frac{e^{S - m} @ V}{\sum e^{S-m} + S^{sink - m}} $$

    $$ dSink = reduce(-Softmax(S) * dP * SimpleSoftmax(sink, x_max, x_sum)) $$

    说明:query、keyIn、value数据排布格式支持从多种维度解读,其中T (Total S Length) 表示所有batch对应的S的总长、B(Batch)表示输入样本批量大小、S(Seq-Length)表示输入样本序列长度、H(Head-Size)表示隐藏层的大小、N(Head-Num)表示多头数、d(Head-Dim)表示隐藏层最小的单元尺寸,且满足d=H/N。

函数原型

每个算子分为两段式接口,必须先调用“aclnnFlashAttentionScoreGradV4GetWorkspaceSize”接口获取计算所需workspace大小以及包含了算子计算流程的执行器,再调用“aclnnFlashAttentionScoreGradV4”接口执行计算。

aclnnStatus aclnnFlashAttentionScoreGradV4GetWorkspaceSize( const aclTensor *query, const aclTensor *keyIn, const aclTensor *value, const aclTensor *dy, const aclTensor *pseShiftOptional, const aclTensor *dropMaskOptional, const aclTensor *paddingMaskOptional, const aclTensor *attenMaskOptional, const aclTensor *softmaxMaxOptional, const aclTensor *softmaxSumOptional, const aclTensor *softmaxInOptional, const aclTensor *attentionInOptional, const aclTensor *sinkInOptional, const aclTensor *queryRopeOptional, const aclTensor *keyRopeOptional, const aclTensor *dScaleQOptional, const aclTensor *dScaleKOptional, const aclTensor *dScaleVOptional, const aclTensor *dScaleDyOptional, const aclTensor *dScaleOOptional, const aclIntArray *prefixOptional, const aclIntArray *actualSeqQLenOptional, const aclIntArray *actualSeqKvLenOptional, const aclIntArray *qStartIdxOptional, const aclIntArray *kvStartIdxOptional, double scaleValue, double keepProb, int64_t preTokens, int64_t nextTokens, int64_t headNum, char *inputLayout, char *softmaxInLayout, int64_t innerPrecise, int64_t sparseMode, int64_t pseType, int64_t seed, int64_t offset, int64_t outDtype, aclTensor *dqOut, aclTensor *dkOut, aclTensor *dvOut, aclTensor *dqRopeOut, aclTensor *dkRopeOut, aclTensor *dpseOut, aclTensor *dsinkOut, uint64_t *workspaceSize, aclOpExecutor **executor)`
aclnnStatus aclnnFlashAttentionScoreGradV4( void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, aclrtStream stream)

aclnnFlashAttentionScoreGradV4GetWorkspaceSize

  • 参数说明:

    参数名输入/输出描述使用说明数据类型数据格式维度(shape)非连续Tensor
    query输入公式中的Q。数据类型与keyIn/value一致。FLOAT16、BFLOAT16、FLOAT32ND0、3、4
    keyIn输入公式中的K。数据类型与query/value一致。FLOAT16、BFLOAT16、FLOAT32ND0、3、4
    keyRopeOptional输入公式中的输入K的rope部分。数据类型与keyIn一致。FLOAT16、BFLOAT16ND0、3、4
    value输入公式中的V。数据类型与query/keyIn一致。FLOAT16、BFLOAT16、FLOAT32ND0、3、4
    dy输入公式中的dY。-FLOAT16、BFLOAT16、FLOAT32ND0、3、4
    pseShiftOptional可选输入公式中的pse,表示位置编码。支持[B,N,S,S]、[B,N,1,S]、[1,N,S,S]、[B,N,H,S]、[1,N,H,S]。FLOAT16、BFLOAT16、FLOAT32ND0、4
    dropMaskOptional可选输入公式中的Dropout。支持[B,N,S,S]UINT8ND0、1
    paddingMaskOptional可选输入预留参数暂未使用。-----
    qStartIdxOptional可选输入代表外切场景,当前分块Q的sequence在全局中的起始索引。-INT64ND0、1
    kvStartIdxOptional可选输入代表外切场景,当前分块KV的sequence在全局中的起始索引。-INT64ND0、1
    attenMaskOptional可选输入公式中的atten_mask。
    • 取值1表示该位不参与计算,0表示参与计算。
    • 支持[B,N,S,S]、[B,1,S,S]、[1,1,S,S]、[S,S]。
    BOOL、UINT8ND0、2、4
    softmaxMaxOptional可选输入注意力正向计算的中间输出。shape=[B,N,Sq,8],[N,T,8],[T,N,8]。FLOATND0、4
    softmaxSumOptional可选输入注意力正向计算的中间输出。shape=[B,N,Sq,8],[N,T,8],[T,N,8]。FLOATND0、4
    softmaxInOptional可选输入注意力正向计算的中间输出。预留参数暂未使用。shape=[B,N,Sq,8]。FLOATND0、4
    attentionInOptional可选输入注意力正向的最终输出。数据类型和shape与query一致。FLOAT16、BFLOAT16、FLOAT32ND0、3、4
    sinkInOptional可选输入公式中的sink。长度是headNum。FLOAT32ND[headNum]
    dScaleQOptional可选输入是query输入的反量化参数。支持[B,N2,G,Sq/128,1]FLOAT32ND0、1
    dScaleKOptional可选输入是key输入的反量化参数。支持[B,N2,1,Skv/128,1]FLOAT32ND0、1
    dScaleVOptional可选输入是value输入的反量化参数。支持[B,N2,1,Skv/128,1]FLOAT32ND0、1
    dScaleDyOptional可选输入是dy输入的反量化参数。支持[B,N2,G,Sq/128,1]FLOAT32ND0、1
    dScaleOOptional可选输入是attentionOptional输入的反量化参数。支持[B,N2,G,Sq/128,1]FLOAT32ND0、1
    prefixOptional可选输入prefix稀疏场景每个Batch的N。-INT64ND0、1-
    actualSeqQLenOptional输入表示每个Batch的query序列长度。-INT64ND0、1-
    actualSeqKvLenOptional输入表示每个Batch的kv序列长度。-INT64ND0、1-
    scaleValue输入公式中的scale缩放系数。-DOUBLE---
    keepProb输入dropMask中1的比例。-DOUBLE---
    preTokens输入稀疏计算窗口左边界。-INT64---
    nextTokens输入稀疏计算窗口右边界。-INT64---
    headNum输入单卡head个数,对应query的N轴。-INT64---
    inputLayout输入query/key/value的数据排布格式。支持BSH、SBH、BSND、BNSD、TND。String---
    softmaxInLayout输入控制softmaxMax、softmaxSum的实际数据排布。shape为TND,实际数据排布需要NTD时传"same_as_input",TND时传""String---
    innerPrecise输入预留参数暂未使用。-----
    sparseMode输入稀疏模式。支持配置值0~8。INT64---
    pseType输入Host侧的整型。支持配置值0~3。INT64---
    seed输入keepProbOptional小于1.0时,根据seedOptional和offsetOptional生成DropoutMask。-INT64---
    offset输入Host侧的整型。-INT64---
    outDtype输入值为0表示dqOut等输出是FLOAT16,为1表示是BFLOAT16。-INT64---
    dqOut输出公式中的dQ,query的梯度。-FLOAT16、BFLOAT16、FLOAT32ND0、3、4
    dqRopeOut输出表示queryRope的梯度。-FLOAT16、BFLOAT16ND0、3、4
    dkOut输出公式中的dK,keyIn的梯度。-FLOAT16、BFLOAT16、FLOAT32ND0、3、4
    dkRopeOut输出公式中的dkRope,表示keyInRope的梯度。-FLOAT16、BFLOAT16ND0、3、4
    dvOut输出公式中的dV,value的梯度。-FLOAT16、BFLOAT16、FLOAT32ND0、3、4
    dpseOut输出d(pse)梯度。暂未使用,传入的shape必须和pse_shape保持一致。FLOAT16、BFLOAT16、FLOAT32ND0、4
    dsinkOut输出公式中dSink,d(sinkInOptional)梯度。-FLOAT32ND1
    workspaceSize输出返回Device侧需要申请的workspace大小。-----
    executor输出返回算子执行器,包含计算流程。-----
  • 返回值:

    返回aclnnStatus状态码,具体参见aclnn返回码。

    第一段接口完成入参校验,出现以下场景时报错:

    返回值错误码描述
    ACLNN_ERR_PARAM_NULLPTR161001传入参数是必选输入,输出或者必选属性,且是空指针。
    ACLNN_ERR_PARAM_INVALID161002query、keyIn、value、dy、pseShiftOptional、dropMaskOptional、paddingMaskOptional、attenMaskOptional、softmaxMaxOptional、softmaxSumOptional、softmaxInOptional、attentionInOptional、dqOut、dkOut、dvOut、softmaxInLayout的数据类型不在支持的范围内。

aclnnFlashAttentionScoreGradV4

  • 参数说明:

    参数名输入/输出描述
    workspace输入在Device侧申请的workspace内存地址。
    workspaceSize输入在Device侧申请的workspace大小,由第一段接口aclnnFlashAttentionScoreGradV4GetWorkspaceSize获取。
    executor输入op执行器,包含了算子计算流程。
    stream输入指定执行任务的Stream。
  • 返回值:

    返回aclnnStatus状态码,具体参见aclnn返回码。

约束说明

  • 确定性计算:

    • aclnnFlashAttentionScoreGradV4默认非确定性实现,支持通过aclrtCtxSetSysParamOpt开启确定性。
  • 输入query、key、value、dy的约束如下:

    • B:batchsize必须相等。
    • inputLayout必须一致。
    • D:Head-Dim必须满足query和key的D相等,value和dy的D相等,并且query和key的D大于等于value和dy的D。
  • 支持输入query/dy的N和key/value的N不相等,但必须成比例关系,即Nq/Nkv必须是非0整数,Nq取值范围1~256。

  • 关于数据shape的约束,以inputLayout的TND为例,其中:

    • B:取值范围为1~2K。带prefixOptional的时候B最大支持1K。
    • N:取值范围为1~256。
    • S:取值范围为1~1M。
    • D:取值范围为1~768。
    • KeepProb:取值范围为(0, 1]。
  • 部分场景下,如果计算量过大可能会导致算子执行超时(aicore error类型报错,errorStr为:timeout or trap error),此时建议做轴切分处理,注:这里的计算量会受B、S、N、D等参数的影响,值越大计算量越大。

  • prefixOptional稀疏计算仅支持压缩场景,sparseModeOptional=6,当Sq > Skv时,prefix的N值取值范围[0, Skv],当Sq <= Skv时,prefix的N值取值范围[Skv-Sq, Skv]。当sparseModeOptional=5、prefix的N > Skv或prefixOptional不传时执行全计算,sparseModeOptional=6要求prefixOptional必传。

  • sparseMode=7时,不支持可选输入pseShiftOptional。

  • sparseMode=8时,当每个sequence的q、kv等长时支持可选输入pseShiftOptional,针对全局做pse生成。支持q方向进行外切,需要外切前每个sequence的q、kv等长,外切后传入的actualSeqQLenOptional[0] - actualSeqKvLenOptional[0] + qStartIdxOptional - kvStartIdxOptional == 0(本功能属实验性功能)。

  • actualSeqQLenOptional输入支持某个Batch上的S长度为0,此时不支持可选输入pseShiftOptional。

  • 关于softmaxMax与softmaxSum参数的约束:输入格式固定为[B, N, S, 8],TND的输入格式除外,此时为[N, T, 8],注:T=B*S。

  • headNum的取值必须和传入的Query中的N值保持一致。

  • Ascend 950PR/Ascend 950DT :

    • seedOptional和offsetOptional只在keepProbOptional小于1.0时生效,否则不生效。
    • keepProbOptional小于1.0时,若dropMaskOptional非nullptr,则使用输入的dropMask;否则使用seed和offset生成的dropMask。
  • TND格式下,支持尾部部分Batch不参与计算,此时actual_seq_q_len和actual_seq_kv_len尾部传入对应个数的0即可。假设真实S长度为[2, 3, 4, 5, 6],若希望最后两个Batch不参与计算,则传入的actual_seq_q_len为[2, 3, 4, 0, 0]。此时若需要传入prefixOptional,其尾部也需要传入同等数量的0,例如[1, 1, 1, 0, 0]。

  • sinkInOptional维度为1,长度需要与query的headnum相同。

  • softmaxSum、softmaxMax数据排布为TND时,softmaxInLayout需要为"same_as_input"。

调用示例

调用示例代码如下,仅供参考,具体编译和执行过程请参考编译与运行样例。

#include <iostream> #include <vector> #include <cstdint> #include <cmath> #include <random> #include "acl/acl.h" #include "aclnnop/aclnn_flash_attention_score_grad.h" #define CHECK_RET(cond, return_expr) \ do { \ if (!(cond)) { \ return_expr; \ } \ } while (0) #define LOG_PRINT(message, ...) \ do { \ printf(message, ##__VA_ARGS__); \ } while (0) int64_t GetShapeSize(const std::vector<int64_t>& shape) { int64_t shapeSize = 1; for (auto i : shape) { shapeSize *= i; } return shapeSize; } void PrintOutResult(std::vector<int64_t> &shape, void** deviceAddr) { auto size = GetShapeSize(shape); std::vector<float> resultData(size, 0); auto ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), *deviceAddr, size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return); for (int64_t i = 0; i < size; i++) { LOG_PRINT("mean result[%ld] is: %f\n", i, resultData[i]); } } int Init(int32_t deviceId, aclrtStream* stream) { // 固定写法,AscendCL初始化 auto ret = aclInit(nullptr); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); ret = aclrtSetDevice(deviceId); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); ret = aclrtCreateStream(stream); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); return 0; } template <typename T> int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, aclDataType dataType, aclTensor** tensor) { auto size = GetShapeSize(shape) * sizeof(T); // 调用aclrtMalloc申请device侧内存 auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); // 计算连续tensor的strides std::vector<int64_t> strides(shape.size(), 1); for (int64_t i = shape.size() - 2; i >= 0; i--) { strides[i] = shape[i + 1] * strides[i + 1]; } // 调用aclCreateTensor接口创建aclTensor *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), *deviceAddr); return 0; } int main() { // 1. (固定写法)device/stream初始化,参考AscendCL对外接口列表 // 根据自己的实际device填写deviceId int32_t deviceId = 0; aclrtStream stream; auto ret = Init(deviceId, &stream); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); // 2. 构造输入与输出,需要根据API的接口自定义构造 int64_t B = 1; int64_t N1 = 1; int64_t N2 = 1; int64_t S1 = 128; int64_t S2 = 128; int64_t D = 128; int64_t H1 = N1 * D; int64_t H2 = N2 * D; int64_t q_size = S1 * B * H1; int64_t kv_size = S2 * B * H2; int64_t atten_mask_size = S1 * S2; int64_t softmax_size = B * N1 * S1 * 8; std::vector<int64_t> qShape = {S1, B, H1}; std::vector<int64_t> kShape = {S2, B, H2}; std::vector<int64_t> vShape = {S2, B, H2}; std::vector<int64_t> dxShape = {S1, B, H1}; std::vector<int64_t> attenmaskShape = {S1, S2}; std::vector<int64_t> softmaxMaxShape = {B, N1, S1, 8}; std::vector<int64_t> softmaxSumShape = {B, N1, S1, 8}; std::vector<int64_t> attentionInShape = {S1, B, H1}; std::vector<int64_t> sinkInOptionalShape = {N1}; std::vector<int64_t> dqShape = {S1, B, H1}; std::vector<int64_t> dkShape = {S2, B, H2}; std::vector<int64_t> dvShape = {S2, B, H2}; std::vector<int64_t> dsinkShape = {N1}; void* qDeviceAddr = nullptr; void* kDeviceAddr = nullptr; void* vDeviceAddr = nullptr; void* dxDeviceAddr = nullptr; void* attenmaskDeviceAddr = nullptr; void* softmaxMaxDeviceAddr = nullptr; void* softmaxSumDeviceAddr = nullptr; void* attentionInDeviceAddr = nullptr; void* sinkInOptionalDeviceAddr = nullptr; void* dqDeviceAddr = nullptr; void* dkDeviceAddr = nullptr; void* dvDeviceAddr = nullptr; void* dsinkDeviceAddr = nullptr; aclTensor* q = nullptr; aclTensor* k = nullptr; aclTensor* v = nullptr; aclTensor* dx = nullptr; aclTensor* pse = nullptr; aclTensor* dropMask = nullptr; aclTensor* padding = nullptr; aclTensor* attenmask = nullptr; aclTensor* queryRope = nullptr; aclTensor* keyRope = nullptr; aclTensor* dScaleQ = nullptr; aclTensor* dScaleK = nullptr; aclTensor* dScaleV = nullptr; aclTensor* dScaleDy = nullptr; aclTensor* dScaleO = nullptr; aclTensor* softmaxMax = nullptr; aclTensor* softmaxSum = nullptr; aclTensor* softmaxIn = nullptr; aclTensor* attentionIn = nullptr; aclTensor* sinkInOptional = nullptr; aclTensor* dq = nullptr; aclTensor* dk = nullptr; aclTensor* dv = nullptr; aclTensor* dpse = nullptr; aclTensor* dqRope = nullptr; aclTensor* dkRope = nullptr; aclTensor* dsink = nullptr; std::random_device rd; std::mt19937 gen(rd()); std::normal_distribution<float> dist(0.0f, 1.0f); // 均值为0,标准差为1的正态分布 std::vector<float> qHostData(q_size); for (auto& val : qHostData) { val = dist(gen); } std::vector<float> kHostData(kv_size); for (auto& val : kHostData) { val = dist(gen); } std::vector<float> vHostData(kv_size); for (auto& val : vHostData) { val = dist(gen); } std::vector<float> dxHostData(q_size); for (auto& val : dxHostData) { val = dist(gen); } std::vector<uint8_t> attenmaskHostData(atten_mask_size, 0); std::vector<float> softmaxMaxHostData(softmax_size, 3.0); std::vector<float> softmaxSumHostData(softmax_size, 3.0); std::vector<float> attentionInHostData(q_size, 255.0); std::vector<float> sinkInOptionalHostData(N1, 0); std::vector<float> dqHostData(q_size, 2.0); std::vector<float> dkHostData(kv_size, 2.0); std::vector<float> dvHostData(kv_size, 3.0); std::vector<float> dsinkHostData(N1, 0); ret = CreateAclTensor(qHostData, qShape, &qDeviceAddr, aclDataType::ACL_FLOAT, &q); CHECK_RET(ret == ACL_SUCCESS, return ret); ret = CreateAclTensor(kHostData, kShape, &kDeviceAddr, aclDataType::ACL_FLOAT, &k); CHECK_RET(ret == ACL_SUCCESS, return ret); ret = CreateAclTensor(vHostData, vShape, &vDeviceAddr, aclDataType::ACL_FLOAT, &v); CHECK_RET(ret == ACL_SUCCESS, return ret); ret = CreateAclTensor(dxHostData, dxShape, &dxDeviceAddr, aclDataType::ACL_FLOAT, &dx); CHECK_RET(ret == ACL_SUCCESS, return ret); ret = CreateAclTensor(attenmaskHostData, attenmaskShape, &attenmaskDeviceAddr, aclDataType::ACL_UINT8, &attenmask); CHECK_RET(ret == ACL_SUCCESS, return ret); ret = CreateAclTensor(softmaxMaxHostData, softmaxMaxShape, &softmaxMaxDeviceAddr, aclDataType::ACL_FLOAT, &softmaxMax); CHECK_RET(ret == ACL_SUCCESS, return ret); ret = CreateAclTensor(softmaxSumHostData, softmaxSumShape, &softmaxSumDeviceAddr, aclDataType::ACL_FLOAT, &softmaxSum); CHECK_RET(ret == ACL_SUCCESS, return ret); ret = CreateAclTensor(attentionInHostData, attentionInShape, &attentionInDeviceAddr, aclDataType::ACL_FLOAT, &attentionIn); ret = CreateAclTensor(sinkInOptionalHostData, sinkInOptionalShape, &sinkInOptionalDeviceAddr, aclDataType::ACL_FLOAT, &sinkInOptional); CHECK_RET(ret == ACL_SUCCESS, return ret); ret = CreateAclTensor(dqHostData, dqShape, &dqDeviceAddr, aclDataType::ACL_FLOAT, &dq); CHECK_RET(ret == ACL_SUCCESS, return ret); ret = CreateAclTensor(dkHostData, dkShape, &dkDeviceAddr, aclDataType::ACL_FLOAT, &dk); CHECK_RET(ret == ACL_SUCCESS, return ret); ret = CreateAclTensor(dvHostData, dvShape, &dvDeviceAddr, aclDataType::ACL_FLOAT, &dv); CHECK_RET(ret == ACL_SUCCESS, return ret); ret = CreateAclTensor(dsinkHostData, dsinkShape, &dsinkDeviceAddr, aclDataType::ACL_FLOAT, &dsink); CHECK_RET(ret == ACL_SUCCESS, return ret); double scaleValue = 1.0/sqrt(128); double keepProb = 1.0; int64_t preTokens = 65536; int64_t nextTokens = 65536; int64_t headNum = 1; int64_t innerPrecise = 0; int64_t sparseMode = 0; int64_t pseType = 1; int64_t outDtype = 1; int64_t seed = 0; int64_t offset = 0; char inputLayOut[5] = {'S', 'B', 'H', 0}; char softmaxInLayoutArr[] = ""; // 3. 调用CANN算子库API,需要修改为具体的Api名称 uint64_t workspaceSize = 0; aclOpExecutor* executor; // 调用aclnnFlashAttentionScoreGradV4第一段接口 ret = aclnnFlashAttentionScoreGradV4GetWorkspaceSize(q, k, v, dx, pse, dropMask, padding, attenmask, softmaxMax, softmaxSum, softmaxIn, attentionIn, nullptr, queryRope, keyRope, dScaleQ, dScaleK, dScaleV, dScaleDy, dScaleO, nullptr, nullptr, nullptr, nullptr, nullptr, scaleValue, keepProb, preTokens, nextTokens, headNum, inputLayOut, softmaxInLayoutArr, innerPrecise, sparseMode,outDtype, pseType, seed, offset, dq,dk,dv,dqRope,dkRope,dpse, nullptr, &workspaceSize, &executor); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnFlashAttentionScoreGradV4GetWorkspaceSize failed. ERROR: %d\n", ret); return ret); // 根据第一段接口计算出的workspaceSize申请device内存 void* workspaceAddr = nullptr; if (workspaceSize > 0) { ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); } // 调用aclnnFlashAttentionScoreGradV4第二段接口 ret = aclnnFlashAttentionScoreGradV4(workspaceAddr, workspaceSize, executor, stream); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnFlashAttentionScoreGradV4 failed. ERROR: %d\n", ret); return ret); // 4. (固定写法)同步等待任务执行结束 ret = aclrtSynchronizeStream(stream); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 PrintOutResult(dqShape, &dqDeviceAddr); PrintOutResult(dkShape, &dkDeviceAddr); PrintOutResult(dvShape, &dvDeviceAddr); // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 aclDestroyTensor(q); aclDestroyTensor(k); aclDestroyTensor(v); aclDestroyTensor(dx); aclDestroyTensor(attenmask); aclDestroyTensor(softmaxMax); aclDestroyTensor(softmaxSum); aclDestroyTensor(attentionIn); aclDestroyTensor(sinkInOptional); aclDestroyTensor(dq); aclDestroyTensor(dk); aclDestroyTensor(dv); aclDestroyTensor(dsink); // 7. 释放device资源 aclrtFree(qDeviceAddr); aclrtFree(kDeviceAddr); aclrtFree(vDeviceAddr); aclrtFree(dxDeviceAddr); aclrtFree(attenmaskDeviceAddr); aclrtFree(softmaxMaxDeviceAddr); aclrtFree(softmaxSumDeviceAddr); aclrtFree(attentionInDeviceAddr); aclrtFree(sinkInOptionalDeviceAddr); aclrtFree(dqDeviceAddr); aclrtFree(dkDeviceAddr); aclrtFree(dvDeviceAddr); aclrtFree(dsinkDeviceAddr); if (workspaceSize > 0) { aclrtFree(workspaceAddr); } aclrtDestroyStream(stream); aclrtResetDevice(deviceId); aclFinalize(); return 0; }

【免费下载链接】ops-transformer本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-transformer

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/9 14:11:50

FPGA-MPSoC边缘AI加速实战:从模型量化到硬件部署全解析

1. 项目概述&#xff1a;为什么要在边缘用FPGA-MPSoC做AI加速&#xff1f;这几年&#xff0c;但凡跟AI沾边的项目&#xff0c;无论是自动驾驶里识别一个突然窜出来的行人&#xff0c;还是工厂质检摄像头判断一个零件的瑕疵&#xff0c;大家挂在嘴边的都是“实时性”和“低功耗”…

作者头像 李华
网站建设 2026/5/9 14:11:01

股市学习心得-近期感悟和总结

作为一个新手&#xff0c;经过一段时间的学习和交易&#xff0c;我感同深受的认识到了一些东西。现在写出来总结自己也分享给大家&#xff0c;看能不能引起共鸣&#xff0c;同时让大家少踩坑。一、持股总结目前这个阶段&#xff0c;轮动特别快&#xff0c;没有特别确定的主线&a…

作者头像 李华
网站建设 2026/5/9 14:11:00

换背景颜色怎么操作?一个微信小程序就能搞定,免费无限使用

最近有个朋友问我&#xff0c;"换背景颜色怎么操作啊&#xff1f;我有张证件照&#xff0c;想换个蓝底的。"我才意识到&#xff0c;很多人可能还在用PS或者其他复杂的工具来处理这个问题。其实现在换背景颜色已经变得超简单了&#xff0c;今天就给大家分享一下我最常…

作者头像 李华
网站建设 2026/5/9 14:09:06

「AI最强联盟」正在悄悄解体

微软和OpenAI结束独家云合作的那天,没有吵架,没有声明,只有一份平静的公告。 但这可能是2026年最被低估的AI信号—— 不是因为感情破裂,而是因为利益已经大到无法用「独家」锁住。 如果你关注AI新闻,可能会有一种错觉:微软和OpenAI仍然是天作之合。 微软投了130亿美元,…

作者头像 李华
网站建设 2026/5/9 14:08:37

CANN unitflag指令优化

unitflag特性介绍 【免费下载链接】cann-samples 算子领域高性能实战演进样例与体系化调优知识库 项目地址: https://gitcode.com/cann/cann-samples 1. 原理介绍 1.1 背景 在算子性能调优过程中&#xff0c;对于带宽搬运瓶颈引起的计算断流我们要尽力优化&#xff0c;…

作者头像 李华
网站建设 2026/5/9 14:08:37

可解释AutoML在信贷风控中的工程实践:从黑箱模型到可信决策

1. 项目概述&#xff1a;当AutoML遇上信贷审批&#xff0c;我们到底在做什么&#xff1f; 干了这么多年金融科技&#xff0c;我见过太多关于“AI赋能信贷”的讨论&#xff0c;但真正落地时&#xff0c;往往卡在一个尴尬的节点&#xff1a;模型效果不错&#xff0c;但风控和业务…

作者头像 李华