已合并
update FA/FAG #856
huanyongben创建于 1月20日
update FA/FAG #856
已合并
共 96 个文件变更+12506-1049
| @@ -22,13 +22,11 @@ | |||
| 22 | 注意力的正向计算公式如下: | 22 | 注意力的正向计算公式如下: |
| 23 | 23 | ||
| 24 | - pseType=1时,公式如下: | 24 | - pseType=1时,公式如下: |
| 25 | - | ||
| 26 | $$ | 25 | $$ |
| 27 | attention\_out=Dropout(Softmax(Mask(scale*(pse+(query*d\_scale\_q)*(key*d\_scale\_k)^T), atten\_mask)), keep\_prob)*(value*d\_scale\_v) | 26 | attention\_out=Dropout(Softmax(Mask(scale*(pse+(query*d\_scale\_q)*(key*d\_scale\_k)^T), atten\_mask)), keep\_prob)*(value*d\_scale\_v) |
| 28 | $$ | 27 | $$ |
| 29 | 28 | ||
| 30 | - pseType≠1时,公式如下: | 29 | - pseType≠1时,公式如下: |
| 31 | - | ||
| 32 | $$ | 30 | $$ |
| 33 | attention\_out=Dropout(Softmax(Mask(scale*((query*d\_scale\_q)*(key*d\_scale\_k)^T) + pse),atten\_mask),keep\_prob)*(value*d\_scale\_v) | 31 | attention\_out=Dropout(Softmax(Mask(scale*((query*d\_scale\_q)*(key*d\_scale\_k)^T) + pse),atten\_mask),keep\_prob)*(value*d\_scale\_v) |
| 34 | $$ | 32 | $$ |
| @@ -55,21 +53,21 @@ | |||
| 55 | <td>query</td> | 53 | <td>query</td> |
| 56 | <td>输入</td> | 54 | <td>输入</td> |
| 57 | <td>公式中的输入query。</td> | 55 | <td>公式中的输入query。</td> |
| 58 | - <td>BFLOAT16、FLOAT16、FLOAT</td> | 56 | + <td>BFLOAT16、FLOAT16、FLOAT、FLOAT8_E5M2、FLOAT8_E4M3FN、HIFLOAT8</td> |
| 59 | <td>ND</td> | 57 | <td>ND</td> |
| 60 | </tr> | 58 | </tr> |
| 61 | <tr> | 59 | <tr> |
| 62 | <td>key</td> | 60 | <td>key</td> |
| 63 | <td>输入</td> | 61 | <td>输入</td> |
| 64 | <td>公式中的输入key。</td> | 62 | <td>公式中的输入key。</td> |
| 65 | - <td>BFLOAT16、FLOAT16、FLOAT</td> | 63 | + <td>BFLOAT16、FLOAT16、FLOAT、FLOAT8_E5M2、FLOAT8_E4M3FN、HIFLOAT8</td> |
| 66 | <td>ND</td> | 64 | <td>ND</td> |
| 67 | </tr> | 65 | </tr> |
| 68 | <tr> | 66 | <tr> |
| 69 | <td>value</td> | 67 | <td>value</td> |
| 70 | <td>输入</td> | 68 | <td>输入</td> |
| 71 | <td>公式中的输入value。</td> | 69 | <td>公式中的输入value。</td> |
| 72 | - <td>BFLOAT16、FLOAT16、FLOAT</td> | 70 | + <td>BFLOAT16、FLOAT16、FLOAT、FLOAT8_E5M2、FLOAT8_E4M3FN、HIFLOAT8</td> |
| 73 | <td>ND</td> | 71 | <td>ND</td> |
| 74 | </tr> | 72 | </tr> |
| 75 | <tr> | 73 | <tr> |
| @@ -174,6 +172,9 @@ | |||
| 174 | </tbody> | 172 | </tbody> |
| 175 | </table> | 173 | </table> |
| 176 | 174 | ||
| 175 | +- <term>Atlas A2 训练系列产品</term>:不支持FLOAT8_E5M2、FLOAT8_E4M3FN、HIFLOAT8三种数据类型。 | ||
| 176 | +- <term>Atlas A3 训练系列产品</term>:不支持FLOAT8_E5M2、FLOAT8_E4M3FN、HIFLOAT8三种数据类型。 | ||
| 177 | + | ||
| 177 | ## 约束说明 | 178 | ## 约束说明 |
| 178 | 179 | ||
| 179 | - 输入query、key、value、realShiftOptional的数据类型必须一致。 | 180 | - 输入query、key、value、realShiftOptional的数据类型必须一致。 |
| @@ -182,7 +183,8 @@ | |||
| 182 | - B:取值范围为1\~2M。当prefixOptional的时候B最大支持2K。 | 183 | - B:取值范围为1\~2M。当prefixOptional的时候B最大支持2K。 |
| 183 | - N:取值范围为1\~256。 | 184 | - N:取值范围为1\~256。 |
| 184 | - S:取值范围为1\~1M。 | 185 | - S:取值范围为1\~1M。 |
| 185 | - - D:取值范围为1\~512。 | 186 | + - D:取值范围为1\~768。输入query、key、value类型为FLOAT8_E5M2、FLOAT8_E4M3FN、HIFLOAT8时,D取值范围为1\~128。 |
| 187 | +- 输入query、key、value类型为FLOAT8_E5M2、FLOAT8_E4M3FN、HIFLOAT8时, 不支持queryRopeOptional、keyRopeOptional、realShiftOptional、attenMaskOptional、dropMaskOptional、keepProb、pseType等相关可选参数。 | ||
| 186 | - keepProb的取值范围为(0, 1]。 | 188 | - keepProb的取值范围为(0, 1]。 |
| 187 | - 部分场景下,如果计算量过大可能会导致算子执行超时(aicore error类型报错,errorStr为:timeout or trap error),此时建议做轴切分处理,注:这里的计算量会受B、S、N、D等参数的影响,值越大计算量越大。 | 189 | - 部分场景下,如果计算量过大可能会导致算子执行超时(aicore error类型报错,errorStr为:timeout or trap error),此时建议做轴切分处理,注:这里的计算量会受B、S、N、D等参数的影响,值越大计算量越大。 |
| 188 | - pseType为2或3的时候,当前只支持Sq和Skv等长。 | 190 | - pseType为2或3的时候,当前只支持Sq和Skv等长。 |
| @@ -98,6 +98,14 @@ struct FaShapeInfo { | |||
| 98 | bool needPadValue = false; | 98 | bool needPadValue = false; |
| 99 | }; | 99 | }; |
| 100 | 100 | ||
| 101 | +static bool StrideLimited() { | ||
| 102 | + NpuArch npuArch = GetCurrentPlatformInfo().GetCurNpuArch(); | ||
| 103 | + if (npuArch == NpuArch::DAV_2201) { | ||
| 104 | + return true; | ||
| 105 | + } | ||
| 106 | + return false; | ||
| 107 | +} | ||
| 108 | + | ||
| 101 | static void AnalysisAxisForBsh(const Shape &qShape, const Shape &kShape, const Shape &vShape, FaShapeInfo &shapeInfo) | 109 | static void AnalysisAxisForBsh(const Shape &qShape, const Shape &kShape, const Shape &vShape, FaShapeInfo &shapeInfo) |
| 102 | { | 110 | { |
| 103 | shapeInfo.inputLayout = InputLayout::BSH; | 111 | shapeInfo.inputLayout = InputLayout::BSH; |
| @@ -388,18 +396,22 @@ static bool isSupportMLA(const FaShapeInfo &shapeInfo, const aclTensor *query) | |||
| 388 | } | 396 | } |
| 389 | 397 | ||
| 390 | static aclnnStatus InputDtypeCheck(const aclTensor *query, const aclTensor *key, const aclTensor *value, | 398 | static aclnnStatus InputDtypeCheck(const aclTensor *query, const aclTensor *key, const aclTensor *value, |
| 391 | - const aclTensor *realShiftOptional, int64_t pseType, const aclTensor *sinkOptional) | 399 | + const aclTensor *attentionOut, const aclTensor *realShiftOptional, |
| 400 | + int64_t pseType, const aclTensor *sinkOptional) | ||
| 392 | { | 401 | { |
| 393 | auto vDtype = value->GetDataType(); | 402 | auto vDtype = value->GetDataType(); |
| 394 | auto kDtype = key->GetDataType(); | 403 | auto kDtype = key->GetDataType(); |
| 395 | auto qDtype = query->GetDataType(); | 404 | auto qDtype = query->GetDataType(); |
| 405 | + auto outDtype = attentionOut->GetDataType(); | ||
| 396 | if (qDtype != kDtype || kDtype != vDtype) { | 406 | if (qDtype != kDtype || kDtype != vDtype) { |
| 397 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, "The data type of query[%s], key[%s], value[%s] are not equal.", | 407 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, "The data type of query[%s], key[%s], value[%s] are not equal.", |
| 398 | op::ToString(DataType(qDtype)).GetString(), op::ToString(DataType(kDtype)).GetString(), | 408 | op::ToString(DataType(qDtype)).GetString(), op::ToString(DataType(kDtype)).GetString(), |
| 399 | op::ToString(DataType(vDtype)).GetString()); | 409 | op::ToString(DataType(vDtype)).GetString()); |
| 400 | return ACLNN_ERR_PARAM_INVALID; | 410 | return ACLNN_ERR_PARAM_INVALID; |
| 401 | } | 411 | } |
| 402 | - if (!(qDtype == op::DataType::DT_FLOAT || qDtype == op::DataType::DT_FLOAT16 || qDtype == op::DataType::DT_BF16)) { | 412 | + |
| 413 | + if (StrideLimited() && | ||
| 414 | + !(qDtype == op::DataType::DT_FLOAT || qDtype == op::DataType::DT_FLOAT16 || qDtype == op::DataType::DT_BF16)) { | ||
| 403 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, "The data type of query/key/value is [%s], should be fp16, bf16 or fp32.", | 415 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, "The data type of query/key/value is [%s], should be fp16, bf16 or fp32.", |
| 404 | op::ToString(DataType(qDtype)).GetString()); | 416 | op::ToString(DataType(qDtype)).GetString()); |
| 405 | return ACLNN_ERR_PARAM_INVALID; | 417 | return ACLNN_ERR_PARAM_INVALID; |
| @@ -421,10 +433,10 @@ static aclnnStatus InputDtypeCheck(const aclTensor *query, const aclTensor *key, | |||
| 421 | } | 433 | } |
| 422 | if (realShiftOptional != nullptr) { | 434 | if (realShiftOptional != nullptr) { |
| 423 | auto pseDtype = realShiftOptional->GetDataType(); | 435 | auto pseDtype = realShiftOptional->GetDataType(); |
| 424 | - if (pseDtype != qDtype) { | 436 | + if (pseDtype != outDtype) { |
| 425 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, | 437 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, |
| 426 | - "The data type %s of pse is not equal to the data type %s of query, key and value.", | 438 | + "The data type %s of pse is not equal to the data type %s of attentionOut.", |
| 427 | - op::ToString(DataType(pseDtype)).GetString(), op::ToString(DataType(qDtype)).GetString()); | 439 | + op::ToString(DataType(pseDtype)).GetString(), op::ToString(DataType(outDtype)).GetString()); |
| 428 | return ACLNN_ERR_PARAM_INVALID; | 440 | return ACLNN_ERR_PARAM_INVALID; |
| 429 | } | 441 | } |
| 430 | } | 442 | } |
| @@ -454,7 +466,7 @@ static inline bool CheckFormat( | |||
| 454 | if (!formatValid) { | 466 | if (!formatValid) { |
| 455 | OP_LOGE( | 467 | OP_LOGE( |
| 456 | ACLNN_ERR_PARAM_INVALID, | 468 | ACLNN_ERR_PARAM_INVALID, |
| 457 | - "Input and output format only support [ND]. Actual: query:[%s], key:[%s], value:[%s], softmaxMaxOut:[%s], softmaxSumOut:[%s], attentionOutOut:[%s].", | 469 | + "Input and output format do not support [NZ]. Actual: query:[%s], key:[%s], value:[%s], softmaxMaxOut:[%s], softmaxSumOut:[%s], attentionOutOut:[%s].", |
| 458 | op::ToString(query->GetStorageFormat()).GetString(), op::ToString(key->GetStorageFormat()).GetString(), | 470 | op::ToString(query->GetStorageFormat()).GetString(), op::ToString(key->GetStorageFormat()).GetString(), |
| 459 | op::ToString(value->GetStorageFormat()).GetString(), op::ToString(softmaxMaxOut->GetStorageFormat()).GetString(), | 471 | op::ToString(value->GetStorageFormat()).GetString(), op::ToString(softmaxMaxOut->GetStorageFormat()).GetString(), |
| 460 | op::ToString(softmaxSumOut->GetStorageFormat()).GetString(), op::ToString(attentionOutOut->GetStorageFormat()).GetString()); | 472 | op::ToString(softmaxSumOut->GetStorageFormat()).GetString(), op::ToString(attentionOutOut->GetStorageFormat()).GetString()); |
| @@ -482,7 +494,7 @@ static inline bool CheckFormat( | |||
| 482 | formatValid = (formatValid && sinkOptional->GetStorageFormat() != op::Format::FORMAT_FRACTAL_NZ); | 494 | formatValid = (formatValid && sinkOptional->GetStorageFormat() != op::Format::FORMAT_FRACTAL_NZ); |
| 483 | } | 495 | } |
| 484 | if (!formatValid) { | 496 | if (!formatValid) { |
| 485 | - OP_LOGE(ACLNN_ERR_PARAM_INVALID,"Optional input format only support [ND]. Actual: queryRope:[%s], keyRope:[%s], realShiftOptional:[%s], " | 497 | + OP_LOGE(ACLNN_ERR_PARAM_INVALID,"Optional input format do not support [NZ]. Actual: queryRope:[%s], keyRope:[%s], realShiftOptional:[%s], " |
| 486 | "dropMaskOptional:[%s], paddingMaskOptional:[%s], attenMaskOptional:[%s], sinkOptional:[%s].",op::ToString(queryRope->GetStorageFormat()).GetString(), | 498 | "dropMaskOptional:[%s], paddingMaskOptional:[%s], attenMaskOptional:[%s], sinkOptional:[%s].",op::ToString(queryRope->GetStorageFormat()).GetString(), |
| 487 | op::ToString(keyRope->GetStorageFormat()).GetString(),op::ToString(realShiftOptional->GetStorageFormat()).GetString(), | 499 | op::ToString(keyRope->GetStorageFormat()).GetString(),op::ToString(realShiftOptional->GetStorageFormat()).GetString(), |
| 488 | op::ToString(dropMaskOptional->GetStorageFormat()).GetString(),op::ToString(paddingMaskOptional->GetStorageFormat()).GetString(), | 500 | op::ToString(dropMaskOptional->GetStorageFormat()).GetString(),op::ToString(paddingMaskOptional->GetStorageFormat()).GetString(), |
| @@ -525,6 +537,10 @@ static aclnnStatus AnalysisInput(const aclTensor *query, const aclTensor *key, c | |||
| 525 | return ACLNN_SUCCESS; | 537 | return ACLNN_SUCCESS; |
| 526 | } | 538 | } |
| 527 | 539 | ||
| 540 | + if (!StrideLimited()) { | ||
| 541 | + return ACLNN_SUCCESS; | ||
| 542 | + } | ||
| 543 | + | ||
| 528 | int64_t alignDim = (shapeInfo.axes.d < PAD_LOWER_BOUND_196 || shapeInfo.axes.d == PAD_ALIGN_SPL_SHAPE) ? | 544 | int64_t alignDim = (shapeInfo.axes.d < PAD_LOWER_BOUND_196 || shapeInfo.axes.d == PAD_ALIGN_SPL_SHAPE) ? |
| 529 | PAD_BASIC_BLOCK : PAD_ALIGN_128; | 545 | PAD_BASIC_BLOCK : PAD_ALIGN_128; |
| 530 | if (shapeInfo.axes.d % alignDim != 0 || shapeInfo.axes.dv % alignDim != 0) { | 546 | if (shapeInfo.axes.d % alignDim != 0 || shapeInfo.axes.dv % alignDim != 0) { |
| @@ -603,7 +619,8 @@ static aclnnStatus Contiguous(const aclTensor *&query, const aclTensor *&key, co | |||
| 603 | const aclTensor *&realShiftOptional, const aclTensor *&dropMaskOptional, | 619 | const aclTensor *&realShiftOptional, const aclTensor *&dropMaskOptional, |
| 604 | const aclTensor *&paddingMaskOptional, const aclTensor *&attenMaskOptional, | 620 | const aclTensor *&paddingMaskOptional, const aclTensor *&attenMaskOptional, |
| 605 | const aclTensor *&queryRope, const aclTensor *&keyRope, const aclTensor *&sinkOptional, | 621 | const aclTensor *&queryRope, const aclTensor *&keyRope, const aclTensor *&sinkOptional, |
| 606 | - aclOpExecutor *executor) | 622 | + const aclTensor *&dScaleQOptional, const aclTensor *&dScaleKOptional, |
| 623 | + const aclTensor *&dScaleVOptional, aclOpExecutor *executor) | ||
| 607 | { | 624 | { |
| 608 | query = l0op::Contiguous(query, executor); | 625 | query = l0op::Contiguous(query, executor); |
| 609 | CHECK_RET(query != nullptr, ACLNN_ERR_PARAM_NULLPTR); | 626 | CHECK_RET(query != nullptr, ACLNN_ERR_PARAM_NULLPTR); |
| @@ -639,12 +656,27 @@ static aclnnStatus Contiguous(const aclTensor *&query, const aclTensor *&key, co | |||
| 639 | sinkOptional = l0op::Contiguous(sinkOptional, executor); | 656 | sinkOptional = l0op::Contiguous(sinkOptional, executor); |
| 640 | CHECK_RET(sinkOptional != nullptr, ACLNN_ERR_PARAM_NULLPTR); | 657 | CHECK_RET(sinkOptional != nullptr, ACLNN_ERR_PARAM_NULLPTR); |
| 641 | } | 658 | } |
| 659 | + if (dScaleQOptional) { | ||
| 660 | + dScaleQOptional = l0op::Contiguous(dScaleQOptional, executor); | ||
| 661 | + CHECK_RET(dScaleQOptional != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 662 | + } | ||
| 663 | + if (dScaleKOptional) { | ||
| 664 | + dScaleKOptional = l0op::Contiguous(dScaleKOptional, executor); | ||
| 665 | + CHECK_RET(dScaleKOptional != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 666 | + } | ||
| 667 | + if (dScaleVOptional) { | ||
| 668 | + dScaleVOptional = l0op::Contiguous(dScaleVOptional, executor); | ||
| 669 | + CHECK_RET(dScaleVOptional != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 670 | + } | ||
| 642 | return ACLNN_SUCCESS; | 671 | return ACLNN_SUCCESS; |
| 643 | } | 672 | } |
| 644 | 673 | ||
| 645 | static aclnnStatus PreprocessQKV(const aclTensor *&query, const aclTensor *&key, const aclTensor *&value, | 674 | static aclnnStatus PreprocessQKV(const aclTensor *&query, const aclTensor *&key, const aclTensor *&value, |
| 646 | const struct FaShapeInfo &shapeInfo, aclOpExecutor *executor) | 675 | const struct FaShapeInfo &shapeInfo, aclOpExecutor *executor) |
| 647 | { | 676 | { |
| 677 | + if (!StrideLimited()) { | ||
| 678 | + return ACLNN_SUCCESS; | ||
| 679 | + } | ||
| 648 | if (shapeInfo.needReshape) { | 680 | if (shapeInfo.needReshape) { |
| 649 | query = l0op::Reshape( | 681 | query = l0op::Reshape( |
| 650 | query, executor->AllocIntArray(shapeInfo.reshapedQueryShape.data(), shapeInfo.reshapedQueryShape.size()), | 682 | query, executor->AllocIntArray(shapeInfo.reshapedQueryShape.data(), shapeInfo.reshapedQueryShape.size()), |
| @@ -714,6 +746,9 @@ static aclnnStatus PreprocessQKV(const aclTensor *&query, const aclTensor *&key, | |||
| 714 | static aclnnStatus Postprocess(const aclTensor *&l0AttentionOutOut, const aclTensor *attentionOutOut, | 746 | static aclnnStatus Postprocess(const aclTensor *&l0AttentionOutOut, const aclTensor *attentionOutOut, |
| 715 | struct FaShapeInfo &shapeInfo, aclOpExecutor *executor) | 747 | struct FaShapeInfo &shapeInfo, aclOpExecutor *executor) |
| 716 | { | 748 | { |
| 749 | + if (!StrideLimited()) { | ||
| 750 | + return ACLNN_SUCCESS; | ||
| 751 | + } | ||
| 717 | if (shapeInfo.inputLayout == InputLayout::SBH && shapeInfo.needPad && !shapeInfo.needTranspose) { | 752 | if (shapeInfo.inputLayout == InputLayout::SBH && shapeInfo.needPad && !shapeInfo.needTranspose) { |
| 718 | // (S,B,Hp) -> (S,B,N,Dp) | 753 | // (S,B,Hp) -> (S,B,N,Dp) |
| 719 | FVector<int64_t, DIM_NUM_4> paddedSBNDShape{shapeInfo.axes.s1, shapeInfo.axes.b, shapeInfo.axes.n1, | 754 | FVector<int64_t, DIM_NUM_4> paddedSBNDShape{shapeInfo.axes.s1, shapeInfo.axes.b, shapeInfo.axes.n1, |
| @@ -873,16 +908,20 @@ aclnnStatus aclnnFlashAttentionScoreGetWorkspaceSize( | |||
| 873 | const aclTensor *keyRope = nullptr; | 908 | const aclTensor *keyRope = nullptr; |
| 874 | 909 | ||
| 875 | //检查format是否符合要求 | 910 | //检查format是否符合要求 |
| 876 | - if (GetCurrentPlatformInfo().GetSocVersion() != SocVersion::ASCEND910_95) { | 911 | + if (StrideLimited()) { |
| 877 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | 912 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, |
| 878 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); | 913 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); |
| 879 | } | 914 | } |
| 880 | - CHECK_RET(InputDtypeCheck(query, key, value, realShiftOptional, PSE_TYPE_V1, sinkOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); | 915 | + CHECK_RET(InputDtypeCheck(query, key, value, attentionOutOut, realShiftOptional, PSE_TYPE_V1, sinkOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); |
| 881 | FaShapeInfo shapeInfo; | 916 | FaShapeInfo shapeInfo; |
| 882 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); | 917 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); |
| 883 | 918 | ||
| 884 | aclOpExecutor *l0Executor = uniqueExecutor.get(); | 919 | aclOpExecutor *l0Executor = uniqueExecutor.get(); |
| 885 | - CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, queryRope, keyRope, sinkOptional, | 920 | + const aclTensor *dScaleQ = nullptr; |
| 921 | + const aclTensor *dScaleK = nullptr; | ||
| 922 | + const aclTensor *dScaleV = nullptr; | ||
| 923 | + CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, | ||
| 924 | + attenMaskOptional, queryRope, keyRope, sinkOptional, dScaleQ, dScaleK, dScaleV, | ||
| 886 | l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 925 | l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); |
| 887 | 926 | ||
| 888 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 927 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); |
| @@ -899,7 +938,12 @@ aclnnStatus aclnnFlashAttentionScoreGetWorkspaceSize( | |||
| 899 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; | 938 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; |
| 900 | // l0SoftmaxOutOut not used now | 939 | // l0SoftmaxOutOut not used now |
| 901 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[DIM_NUM_3]; | 940 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[DIM_NUM_3]; |
| 902 | - | 941 | + if (l0SoftmaxMaxOut == nullptr || l0SoftmaxSumOut == nullptr || l0AttentionOutOut == nullptr) { |
| 942 | + OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "l0SoftmaxMaxOut or l0SoftmaxSumOut or l0AttentionOutOut is null"); | ||
| 943 | + *workspaceSize = 0; | ||
| 944 | + uniqueExecutor.ReleaseTo(executor); | ||
| 945 | + return ACLNN_ERR_PARAM_NULLPTR; | ||
| 946 | + } | ||
| 903 | CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, | 947 | CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, |
| 904 | ACLNN_ERR_PARAM_NULLPTR); | 948 | ACLNN_ERR_PARAM_NULLPTR); |
| 905 | 949 | ||
| @@ -962,18 +1006,22 @@ aclnnStatus aclnnFlashAttentionVarLenScoreGetWorkspaceSize( | |||
| 962 | const aclTensor *keyRope = nullptr; | 1006 | const aclTensor *keyRope = nullptr; |
| 963 | 1007 | ||
| 964 | //检查format是否符合要求 | 1008 | //检查format是否符合要求 |
| 965 | - if (GetCurrentPlatformInfo().GetSocVersion() != SocVersion::ASCEND910_95) { | 1009 | + if (StrideLimited()) { |
| 966 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | 1010 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, |
| 967 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); | 1011 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); |
| 968 | } | 1012 | } |
| 969 | 1013 | ||
| 970 | - CHECK_RET(InputDtypeCheck(query, key, value, realShiftOptional, PSE_TYPE_V1, sinkOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); | 1014 | + CHECK_RET(InputDtypeCheck(query, key, value, attentionOutOut, realShiftOptional, PSE_TYPE_V1, sinkOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); |
| 971 | FaShapeInfo shapeInfo; | 1015 | FaShapeInfo shapeInfo; |
| 972 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo, actualSeqQLenOptional, | 1016 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo, actualSeqQLenOptional, |
| 973 | actualSeqKvLenOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); | 1017 | actualSeqKvLenOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); |
| 974 | 1018 | ||
| 975 | aclOpExecutor *l0Executor = uniqueExecutor.get(); | 1019 | aclOpExecutor *l0Executor = uniqueExecutor.get(); |
| 976 | - CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, queryRope, keyRope, sinkOptional, | 1020 | + const aclTensor *dScaleQ = nullptr; |
| 1021 | + const aclTensor *dScaleK = nullptr; | ||
| 1022 | + const aclTensor *dScaleV = nullptr; | ||
| 1023 | + CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | ||
| 1024 | + queryRope, keyRope, sinkOptional, dScaleQ, dScaleK, dScaleV, | ||
| 977 | l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 1025 | l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); |
| 978 | 1026 | ||
| 979 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 1027 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); |
| @@ -988,15 +1036,15 @@ aclnnStatus aclnnFlashAttentionVarLenScoreGetWorkspaceSize( | |||
| 988 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; | 1036 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; |
| 989 | // l0SoftmaxOutOut not used now | 1037 | // l0SoftmaxOutOut not used now |
| 990 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; | 1038 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; |
| 991 | - | ||
| 992 | - CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, | ||
| 993 | - ACLNN_ERR_PARAM_NULLPTR); | ||
| 994 | if (l0SoftmaxMaxOut == nullptr || l0SoftmaxSumOut == nullptr || l0AttentionOutOut == nullptr) { | 1039 | if (l0SoftmaxMaxOut == nullptr || l0SoftmaxSumOut == nullptr || l0AttentionOutOut == nullptr) { |
| 995 | OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "l0SoftmaxMaxOut or l0SoftmaxSumOut or l0AttentionOutOut is null"); | 1040 | OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "l0SoftmaxMaxOut or l0SoftmaxSumOut or l0AttentionOutOut is null"); |
| 996 | *workspaceSize = 0; | 1041 | *workspaceSize = 0; |
| 997 | uniqueExecutor.ReleaseTo(executor); | 1042 | uniqueExecutor.ReleaseTo(executor); |
| 998 | return ACLNN_ERR_PARAM_NULLPTR; | 1043 | return ACLNN_ERR_PARAM_NULLPTR; |
| 999 | } | 1044 | } |
| 1045 | + CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, | ||
| 1046 | + ACLNN_ERR_PARAM_NULLPTR); | ||
| 1047 | + | ||
| 1000 | auto viewCopyResult0 = l0op::ViewCopy(l0SoftmaxMaxOut, softmaxMaxOut, l0Executor); | 1048 | auto viewCopyResult0 = l0op::ViewCopy(l0SoftmaxMaxOut, softmaxMaxOut, l0Executor); |
| 1001 | CHECK_RET(viewCopyResult0 != nullptr, ACLNN_ERR_PARAM_NULLPTR); | 1049 | CHECK_RET(viewCopyResult0 != nullptr, ACLNN_ERR_PARAM_NULLPTR); |
| 1002 | auto viewCopyResult1 = l0op::ViewCopy(l0SoftmaxSumOut, softmaxSumOut, l0Executor); | 1050 | auto viewCopyResult1 = l0op::ViewCopy(l0SoftmaxSumOut, softmaxSumOut, l0Executor); |
| @@ -1050,18 +1098,22 @@ aclnnStatus aclnnFlashAttentionScoreV2GetWorkspaceSize( | |||
| 1050 | const aclTensor *keyRope = nullptr; | 1098 | const aclTensor *keyRope = nullptr; |
| 1051 | 1099 | ||
| 1052 | //检查format是否符合要求 | 1100 | //检查format是否符合要求 |
| 1053 | - if (GetCurrentPlatformInfo().GetSocVersion() != SocVersion::ASCEND910_95) { | 1101 | + if (StrideLimited()) { |
| 1054 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | 1102 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, |
| 1055 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); | 1103 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); |
| 1056 | } | 1104 | } |
| 1057 | 1105 | ||
| 1058 | - CHECK_RET(InputDtypeCheck(query, key, value, realShiftOptional, pseType, nullptr) == ACLNN_SUCCESS, | 1106 | + CHECK_RET(InputDtypeCheck(query, key, value, attentionOutOut, realShiftOptional, pseType, nullptr) == ACLNN_SUCCESS, |
| 1059 | ACLNN_ERR_PARAM_INVALID); | 1107 | ACLNN_ERR_PARAM_INVALID); |
| 1060 | FaShapeInfo shapeInfo; | 1108 | FaShapeInfo shapeInfo; |
| 1061 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); | 1109 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); |
| 1062 | 1110 | ||
| 1063 | aclOpExecutor *l0Executor = uniqueExecutor.get(); | 1111 | aclOpExecutor *l0Executor = uniqueExecutor.get(); |
| 1064 | - CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, queryRope, keyRope, sinkOptional, | 1112 | + const aclTensor *dScaleQ = nullptr; |
| 1113 | + const aclTensor *dScaleK = nullptr; | ||
| 1114 | + const aclTensor *dScaleV = nullptr; | ||
| 1115 | + CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | ||
| 1116 | + queryRope, keyRope, sinkOptional, dScaleQ, dScaleK, dScaleV, | ||
| 1065 | l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 1117 | l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); |
| 1066 | 1118 | ||
| 1067 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 1119 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); |
| @@ -1076,7 +1128,12 @@ aclnnStatus aclnnFlashAttentionScoreV2GetWorkspaceSize( | |||
| 1076 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; | 1128 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; |
| 1077 | // l0SoftmaxOutOut not used now | 1129 | // l0SoftmaxOutOut not used now |
| 1078 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; | 1130 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; |
| 1079 | - | 1131 | + if (l0SoftmaxMaxOut == nullptr || l0SoftmaxSumOut == nullptr || l0AttentionOutOut == nullptr) { |
| 1132 | + OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "l0SoftmaxMaxOut or l0SoftmaxSumOut or l0AttentionOutOut is null"); | ||
| 1133 | + *workspaceSize = 0; | ||
| 1134 | + uniqueExecutor.ReleaseTo(executor); | ||
| 1135 | + return ACLNN_ERR_PARAM_NULLPTR; | ||
| 1136 | + } | ||
| 1080 | CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, | 1137 | CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, |
| 1081 | ACLNN_ERR_PARAM_NULLPTR); | 1138 | ACLNN_ERR_PARAM_NULLPTR); |
| 1082 | 1139 | ||
| @@ -1133,18 +1190,22 @@ aclnnStatus aclnnFlashAttentionScoreV3GetWorkspaceSize( | |||
| 1133 | const aclTensor *keyRope = nullptr; | 1190 | const aclTensor *keyRope = nullptr; |
| 1134 | 1191 | ||
| 1135 | //检查format是否符合要求 | 1192 | //检查format是否符合要求 |
| 1136 | - if (GetCurrentPlatformInfo().GetSocVersion() != SocVersion::ASCEND910_95) { | 1193 | + if (StrideLimited()) { |
| 1137 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | 1194 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, |
| 1138 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); | 1195 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); |
| 1139 | } | 1196 | } |
| 1140 | 1197 | ||
| 1141 | - CHECK_RET(InputDtypeCheck(query, key, value, realShiftOptional, pseType, sinkOptional) == ACLNN_SUCCESS, | 1198 | + CHECK_RET(InputDtypeCheck(query, key, value, attentionOutOut, realShiftOptional, pseType, sinkOptional) == ACLNN_SUCCESS, |
| 1142 | ACLNN_ERR_PARAM_INVALID); | 1199 | ACLNN_ERR_PARAM_INVALID); |
| 1143 | FaShapeInfo shapeInfo; | 1200 | FaShapeInfo shapeInfo; |
| 1144 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); | 1201 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); |
| 1145 | 1202 | ||
| 1146 | aclOpExecutor *l0Executor = uniqueExecutor.get(); | 1203 | aclOpExecutor *l0Executor = uniqueExecutor.get(); |
| 1147 | - CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, queryRope, keyRope, sinkOptional, | 1204 | + const aclTensor *dScaleQ = nullptr; |
| 1205 | + const aclTensor *dScaleK = nullptr; | ||
| 1206 | + const aclTensor *dScaleV = nullptr; | ||
| 1207 | + CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | ||
| 1208 | + queryRope, keyRope, sinkOptional, dScaleQ, dScaleK, dScaleV, | ||
| 1148 | l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 1209 | l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); |
| 1149 | 1210 | ||
| 1150 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 1211 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); |
| @@ -1164,7 +1225,12 @@ aclnnStatus aclnnFlashAttentionScoreV3GetWorkspaceSize( | |||
| 1164 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; | 1225 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; |
| 1165 | // l0SoftmaxOutOut not used now | 1226 | // l0SoftmaxOutOut not used now |
| 1166 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; | 1227 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; |
| 1167 | - | 1228 | + if (l0SoftmaxMaxOut == nullptr || l0SoftmaxSumOut == nullptr || l0AttentionOutOut == nullptr) { |
| 1229 | + OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "l0SoftmaxMaxOut or l0SoftmaxSumOut or l0AttentionOutOut is null"); | ||
| 1230 | + *workspaceSize = 0; | ||
| 1231 | + uniqueExecutor.ReleaseTo(executor); | ||
| 1232 | + return ACLNN_ERR_PARAM_NULLPTR; | ||
| 1233 | + } | ||
| 1168 | CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, | 1234 | CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, |
| 1169 | ACLNN_ERR_PARAM_NULLPTR); | 1235 | ACLNN_ERR_PARAM_NULLPTR); |
| 1170 | 1236 | ||
| @@ -1189,6 +1255,100 @@ aclnnStatus aclnnFlashAttentionScoreV3(void *workspace, uint64_t workspaceSize, | |||
| 1189 | return CommonOpExecutorRun(workspace, workspaceSize, executor, stream); | 1255 | return CommonOpExecutorRun(workspace, workspaceSize, executor, stream); |
| 1190 | } | 1256 | } |
| 1191 | 1257 | ||
| 1258 | +aclnnStatus aclnnFlashAttentionScoreV4GetWorkspaceSize( | ||
| 1259 | + const aclTensor *query, const aclTensor *key, const aclTensor *value, const aclTensor *realShiftOptional, | ||
| 1260 | + const aclTensor *dropMaskOptional, const aclTensor *paddingMaskOptional, const aclTensor *attenMaskOptional, | ||
| 1261 | + const aclTensor *queryRopeOptional, const aclTensor *keyRopeOptional, const aclTensor *dScaleQOptional, | ||
| 1262 | + const aclTensor *dScaleKOptional, const aclTensor *dScaleVOptional, | ||
| 1263 | + const aclTensor *sinkOptional, const aclIntArray *prefixOptional, | ||
| 1264 | + const aclIntArray *actualSeqQLenOptional, const aclIntArray *actualSeqKvLenOptional, | ||
| 1265 | + const aclIntArray *qStartIdxOptional, const aclIntArray *kvStartIdxOptional, double scaleValue, | ||
| 1266 | + double keepProb, int64_t preTokens, int64_t nextTokens, int64_t headNum, char *inputLayout, int64_t innerPrecise, | ||
| 1267 | + int64_t sparseMode, int64_t outDtype, int64_t pseType, char *softmaxOutLayout, int64_t seed, int64_t offset, | ||
| 1268 | + const aclTensor *softmaxMaxOut, const aclTensor *softmaxSumOut, const aclTensor *softmaxOutOut, | ||
| 1269 | + const aclTensor *attentionOutOut, uint64_t *workspaceSize, aclOpExecutor **executor) | ||
| 1270 | +{ | ||
| 1271 | + CHECK_RET(CheckFaParam(query, key, value, inputLayout, softmaxMaxOut, softmaxSumOut, attentionOutOut, | ||
| 1272 | + workspaceSize, executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | ||
| 1273 | + L2_DFX_PHASE_1(aclnnFlashAttentionScoreV4, | ||
| 1274 | + DFX_IN(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, | ||
| 1275 | + attenMaskOptional, queryRopeOptional, keyRopeOptional, dScaleQOptional, dScaleKOptional, | ||
| 1276 | + dScaleVOptional, sinkOptional, prefixOptional, actualSeqQLenOptional, actualSeqKvLenOptional, | ||
| 1277 | + qStartIdxOptional, kvStartIdxOptional, scaleValue, keepProb, preTokens, nextTokens, headNum, | ||
| 1278 | + inputLayout, innerPrecise, sparseMode, outDtype, pseType, seed, offset), | ||
| 1279 | + DFX_OUT(softmaxMaxOut, softmaxSumOut, softmaxOutOut, attentionOutOut)); | ||
| 1280 | + | ||
| 1281 | + auto uniqueExecutor = CREATE_EXECUTOR(); | ||
| 1282 | + CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR); | ||
| 1283 | + // b, n1, s1 为0时,不进行任何处理 | ||
| 1284 | + // n2, s2, d 为0时,直接调用l0接口处理 | ||
| 1285 | + if (softmaxMaxOut->IsEmpty() && softmaxSumOut->IsEmpty() && attentionOutOut->IsEmpty()) { | ||
| 1286 | + *workspaceSize = 0; | ||
| 1287 | + uniqueExecutor.ReleaseTo(executor); | ||
| 1288 | + return ACLNN_SUCCESS; | ||
| 1289 | + } | ||
| 1290 | + CHECK_RET(InputDtypeCheck(query, key, value, attentionOutOut, realShiftOptional, pseType, sinkOptional) == | ||
| 1291 | + ACLNN_SUCCESS, | ||
| 1292 | + ACLNN_ERR_PARAM_INVALID); | ||
| 1293 | + FaShapeInfo shapeInfo; | ||
| 1294 | + CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo) == ACLNN_SUCCESS, | ||
| 1295 | + ACLNN_ERR_PARAM_INVALID); | ||
| 1296 | + | ||
| 1297 | + aclOpExecutor *l0Executor = uniqueExecutor.get(); | ||
| 1298 | + | ||
| 1299 | + CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | ||
| 1300 | + queryRopeOptional, keyRopeOptional, sinkOptional, dScaleQOptional, dScaleKOptional, | ||
| 1301 | + dScaleVOptional, l0Executor) == ACLNN_SUCCESS, | ||
| 1302 | + ACLNN_ERR_INNER_NULLPTR); | ||
| 1303 | + | ||
| 1304 | + CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | ||
| 1305 | + | ||
| 1306 | + // sink shape is 0 | ||
| 1307 | + if (sinkOptional != nullptr && sinkOptional->GetViewShape().GetDimNum() == 1 && | ||
| 1308 | + sinkOptional->GetViewShape()[0] == 0) { | ||
| 1309 | + sinkOptional = nullptr; | ||
| 1310 | + } | ||
| 1311 | + auto l0FlashAttentionScoreOuts = l0op::FlashAttentionScore( | ||
| 1312 | + query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, sinkOptional, | ||
| 1313 | + prefixOptional, actualSeqQLenOptional, actualSeqKvLenOptional, qStartIdxOptional, kvStartIdxOptional, | ||
| 1314 | + dScaleQOptional, dScaleKOptional, dScaleVOptional, queryRopeOptional, keyRopeOptional, | ||
| 1315 | + scaleValue, keepProb, preTokens, nextTokens, headNum, shapeInfo.l0InputLayoutStr.c_str(), | ||
| 1316 | + innerPrecise, sparseMode, pseType, seed, offset, outDtype, softmaxOutLayout, l0Executor); | ||
| 1317 | + | ||
| 1318 | + auto l0SoftmaxMaxOut = l0FlashAttentionScoreOuts[0]; | ||
| 1319 | + auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; | ||
| 1320 | + // l0SoftmaxOutOut not used now | ||
| 1321 | + auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; | ||
| 1322 | + if (l0SoftmaxMaxOut == nullptr || l0SoftmaxSumOut == nullptr || l0AttentionOutOut == nullptr) { | ||
| 1323 | + OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "l0SoftmaxMaxOut or l0SoftmaxSumOut or l0AttentionOutOut is null"); | ||
| 1324 | + *workspaceSize = 0; | ||
| 1325 | + uniqueExecutor.ReleaseTo(executor); | ||
| 1326 | + return ACLNN_ERR_PARAM_NULLPTR; | ||
| 1327 | + } | ||
| 1328 | + CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, | ||
| 1329 | + ACLNN_ERR_PARAM_NULLPTR); | ||
| 1330 | + | ||
| 1331 | + auto viewCopyResult0 = l0op::ViewCopy(l0SoftmaxMaxOut, softmaxMaxOut, l0Executor); | ||
| 1332 | + CHECK_RET(viewCopyResult0 != nullptr, ACLNN_ERR_PARAM_NULLPTR); | ||
| 1333 | + auto viewCopyResult1 = l0op::ViewCopy(l0SoftmaxSumOut, softmaxSumOut, l0Executor); | ||
| 1334 | + CHECK_RET(viewCopyResult1 != nullptr, ACLNN_ERR_PARAM_NULLPTR); | ||
| 1335 | + // l0SoftmaxOutOut not used now | ||
| 1336 | + auto viewCopyResult3 = l0op::ViewCopy(l0AttentionOutOut, attentionOutOut, l0Executor); | ||
| 1337 | + CHECK_RET(viewCopyResult3 != nullptr, ACLNN_ERR_PARAM_NULLPTR); | ||
| 1338 | + | ||
| 1339 | + *workspaceSize = uniqueExecutor->GetWorkspaceSize(); | ||
| 1340 | + uniqueExecutor.ReleaseTo(executor); | ||
| 1341 | + return ACLNN_SUCCESS; | ||
| 1342 | +} | ||
| 1343 | + | ||
| 1344 | +aclnnStatus aclnnFlashAttentionScoreV4(void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, | ||
| 1345 | + const aclrtStream stream) | ||
| 1346 | +{ | ||
| 1347 | + L2_DFX_PHASE_2(aclnnFlashAttentionScoreV4); | ||
| 1348 | + // 固定写法,调用框架能力,完成计算 | ||
| 1349 | + return CommonOpExecutorRun(workspace, workspaceSize, executor, stream); | ||
| 1350 | +} | ||
| 1351 | + | ||
| 1192 | aclnnStatus aclnnFlashAttentionVarLenScoreV2GetWorkspaceSize( | 1352 | aclnnStatus aclnnFlashAttentionVarLenScoreV2GetWorkspaceSize( |
| 1193 | const aclTensor *query, const aclTensor *key, const aclTensor *value, const aclTensor *realShiftOptional, | 1353 | const aclTensor *query, const aclTensor *key, const aclTensor *value, const aclTensor *realShiftOptional, |
| 1194 | const aclTensor *dropMaskOptional, const aclTensor *paddingMaskOptional, const aclTensor *attenMaskOptional, | 1354 | const aclTensor *dropMaskOptional, const aclTensor *paddingMaskOptional, const aclTensor *attenMaskOptional, |
| @@ -1230,18 +1390,22 @@ aclnnStatus aclnnFlashAttentionVarLenScoreV2GetWorkspaceSize( | |||
| 1230 | const aclTensor *keyRope = nullptr; | 1390 | const aclTensor *keyRope = nullptr; |
| 1231 | 1391 | ||
| 1232 | //检查format是否符合要求 | 1392 | //检查format是否符合要求 |
| 1233 | - if (GetCurrentPlatformInfo().GetSocVersion() != SocVersion::ASCEND910_95) { | 1393 | + if (StrideLimited()) { |
| 1234 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | 1394 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, |
| 1235 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); | 1395 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); |
| 1236 | } | 1396 | } |
| 1237 | 1397 | ||
| 1238 | - CHECK_RET(InputDtypeCheck(query, key, value, realShiftOptional, pseType, sinkOptional) == ACLNN_SUCCESS, | 1398 | + CHECK_RET(InputDtypeCheck(query, key, value, attentionOutOut, realShiftOptional, pseType, sinkOptional) == ACLNN_SUCCESS, |
| 1239 | ACLNN_ERR_PARAM_INVALID); | 1399 | ACLNN_ERR_PARAM_INVALID); |
| 1240 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo, actualSeqQLenOptional, | 1400 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo, actualSeqQLenOptional, |
| 1241 | actualSeqKvLenOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); | 1401 | actualSeqKvLenOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); |
| 1242 | 1402 | ||
| 1243 | aclOpExecutor *l0Executor = uniqueExecutor.get(); | 1403 | aclOpExecutor *l0Executor = uniqueExecutor.get(); |
| 1244 | - CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, queryRope, keyRope, sinkOptional, | 1404 | + const aclTensor *dScaleQ = nullptr; |
| 1405 | + const aclTensor *dScaleK = nullptr; | ||
| 1406 | + const aclTensor *dScaleV = nullptr; | ||
| 1407 | + CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | ||
| 1408 | + queryRope, keyRope, sinkOptional, dScaleQ, dScaleK, dScaleV, | ||
| 1245 | l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 1409 | l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); |
| 1246 | 1410 | ||
| 1247 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 1411 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); |
| @@ -1256,15 +1420,15 @@ aclnnStatus aclnnFlashAttentionVarLenScoreV2GetWorkspaceSize( | |||
| 1256 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; | 1420 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; |
| 1257 | // l0SoftmaxOutOut not used now | 1421 | // l0SoftmaxOutOut not used now |
| 1258 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; | 1422 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; |
| 1259 | - | 1423 | + if (l0SoftmaxMaxOut == nullptr || l0SoftmaxSumOut == nullptr || l0AttentionOutOut == nullptr) { |
| 1424 | + OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "l0SoftmaxMaxOut or l0SoftmaxSumOut or l0AttentionOutOut is null"); | ||
| 1425 | + *workspaceSize = 0; | ||
| 1426 | + uniqueExecutor.ReleaseTo(executor); | ||
| 1427 | + return ACLNN_ERR_PARAM_NULLPTR; | ||
| 1428 | + } | ||
| 1260 | CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, | 1429 | CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, |
| 1261 | ACLNN_ERR_PARAM_NULLPTR); | 1430 | ACLNN_ERR_PARAM_NULLPTR); |
| 1262 | - if (l0SoftmaxMaxOut == nullptr || l0SoftmaxSumOut == nullptr || l0AttentionOutOut == nullptr) { | 1431 | + |
| 1263 | - OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "l0SoftmaxMaxOut or l0SoftmaxSumOut or l0AttentionOutOut is null"); | ||
| 1264 | - *workspaceSize = 0; | ||
| 1265 | - uniqueExecutor.ReleaseTo(executor); | ||
| 1266 | - return ACLNN_ERR_PARAM_NULLPTR; | ||
| 1267 | - } | ||
| 1268 | auto viewCopyResult0 = l0op::ViewCopy(l0SoftmaxMaxOut, softmaxMaxOut, l0Executor); | 1432 | auto viewCopyResult0 = l0op::ViewCopy(l0SoftmaxMaxOut, softmaxMaxOut, l0Executor); |
| 1269 | CHECK_RET(viewCopyResult0 != nullptr, ACLNN_ERR_PARAM_NULLPTR); | 1433 | CHECK_RET(viewCopyResult0 != nullptr, ACLNN_ERR_PARAM_NULLPTR); |
| 1270 | auto viewCopyResult1 = l0op::ViewCopy(l0SoftmaxSumOut, softmaxSumOut, l0Executor); | 1434 | auto viewCopyResult1 = l0op::ViewCopy(l0SoftmaxSumOut, softmaxSumOut, l0Executor); |
| @@ -1326,20 +1490,24 @@ aclnnStatus aclnnFlashAttentionVarLenScoreV3GetWorkspaceSize( | |||
| 1326 | const aclTensor *sinkOptional = nullptr; | 1490 | const aclTensor *sinkOptional = nullptr; |
| 1327 | 1491 | ||
| 1328 | //检查format是否符合要求 | 1492 | //检查format是否符合要求 |
| 1329 | - if (GetCurrentPlatformInfo().GetSocVersion() != SocVersion::ASCEND910_95) { | 1493 | + if (StrideLimited()) { |
| 1330 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | 1494 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, |
| 1331 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); | 1495 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); |
| 1332 | } | 1496 | } |
| 1333 | 1497 | ||
| 1334 | - CHECK_RET(InputDtypeCheck(query, key, value, realShiftOptional, pseType, sinkOptional) == ACLNN_SUCCESS, | 1498 | + CHECK_RET(InputDtypeCheck(query, key, value, attentionOutOut, realShiftOptional, pseType, sinkOptional) == ACLNN_SUCCESS, |
| 1335 | ACLNN_ERR_PARAM_INVALID); | 1499 | ACLNN_ERR_PARAM_INVALID); |
| 1336 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo, actualSeqQLenOptional, | 1500 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo, actualSeqQLenOptional, |
| 1337 | actualSeqKvLenOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); | 1501 | actualSeqKvLenOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); |
| 1338 | 1502 | ||
| 1339 | aclOpExecutor *l0Executor = uniqueExecutor.get(); | 1503 | aclOpExecutor *l0Executor = uniqueExecutor.get(); |
| 1340 | 1504 | ||
| 1341 | - CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, queryRope, keyRope, sinkOptional, | 1505 | + const aclTensor *dScaleQ = nullptr; |
| 1342 | - l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 1506 | + const aclTensor *dScaleK = nullptr; |
| 1507 | + const aclTensor *dScaleV = nullptr; | ||
| 1508 | + CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | ||
| 1509 | + queryRope, keyRope, sinkOptional, dScaleQ, dScaleK, dScaleV, | ||
| 1510 | + l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | ||
| 1343 | 1511 | ||
| 1344 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 1512 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); |
| 1345 | 1513 | ||
| @@ -1356,15 +1524,15 @@ aclnnStatus aclnnFlashAttentionVarLenScoreV3GetWorkspaceSize( | |||
| 1356 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; | 1524 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; |
| 1357 | // l0SoftmaxOutOut not used now | 1525 | // l0SoftmaxOutOut not used now |
| 1358 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; | 1526 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; |
| 1359 | - | 1527 | + if (l0SoftmaxMaxOut == nullptr || l0SoftmaxSumOut == nullptr || l0AttentionOutOut == nullptr) { |
| 1528 | + OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "l0SoftmaxMaxOut or l0SoftmaxSumOut or l0AttentionOutOut is null"); | ||
| 1529 | + *workspaceSize = 0; | ||
| 1530 | + uniqueExecutor.ReleaseTo(executor); | ||
| 1531 | + return ACLNN_ERR_PARAM_NULLPTR; | ||
| 1532 | + } | ||
| 1360 | CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, | 1533 | CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, |
| 1361 | ACLNN_ERR_PARAM_NULLPTR); | 1534 | ACLNN_ERR_PARAM_NULLPTR); |
| 1362 | - if (l0SoftmaxMaxOut == nullptr || l0SoftmaxSumOut == nullptr || l0AttentionOutOut == nullptr) { | 1535 | + |
| 1363 | - OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "l0SoftmaxMaxOut or l0SoftmaxSumOut or l0AttentionOutOut is null"); | ||
| 1364 | - *workspaceSize = 0; | ||
| 1365 | - uniqueExecutor.ReleaseTo(executor); | ||
| 1366 | - return ACLNN_ERR_PARAM_NULLPTR; | ||
| 1367 | - } | ||
| 1368 | auto viewCopyResult0 = l0op::ViewCopy(l0SoftmaxMaxOut, softmaxMaxOut, l0Executor); | 1536 | auto viewCopyResult0 = l0op::ViewCopy(l0SoftmaxMaxOut, softmaxMaxOut, l0Executor); |
| 1369 | CHECK_RET(viewCopyResult0 != nullptr, ACLNN_ERR_PARAM_NULLPTR); | 1537 | CHECK_RET(viewCopyResult0 != nullptr, ACLNN_ERR_PARAM_NULLPTR); |
| 1370 | auto viewCopyResult1 = l0op::ViewCopy(l0SoftmaxSumOut, softmaxSumOut, l0Executor); | 1538 | auto viewCopyResult1 = l0op::ViewCopy(l0SoftmaxSumOut, softmaxSumOut, l0Executor); |
| @@ -1424,18 +1592,22 @@ aclnnStatus aclnnFlashAttentionVarLenScoreV4GetWorkspaceSize( | |||
| 1424 | const aclTensor *keyRope = nullptr; | 1592 | const aclTensor *keyRope = nullptr; |
| 1425 | 1593 | ||
| 1426 | //检查format是否符合要求 | 1594 | //检查format是否符合要求 |
| 1427 | - if (GetCurrentPlatformInfo().GetSocVersion() != SocVersion::ASCEND910_95) { | 1595 | + if (StrideLimited()) { |
| 1428 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | 1596 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, |
| 1429 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); | 1597 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); |
| 1430 | } | 1598 | } |
| 1431 | 1599 | ||
| 1432 | - CHECK_RET(InputDtypeCheck(query, key, value, realShiftOptional, PSE_TYPE_V1, sinkOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); | 1600 | + CHECK_RET(InputDtypeCheck(query, key, value, attentionOutOut, realShiftOptional, PSE_TYPE_V1, sinkOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); |
| 1433 | FaShapeInfo shapeInfo; | 1601 | FaShapeInfo shapeInfo; |
| 1434 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo, actualSeqQLenOptional, | 1602 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo, actualSeqQLenOptional, |
| 1435 | actualSeqKvLenOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); | 1603 | actualSeqKvLenOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); |
| 1436 | 1604 | ||
| 1437 | aclOpExecutor *l0Executor = uniqueExecutor.get(); | 1605 | aclOpExecutor *l0Executor = uniqueExecutor.get(); |
| 1438 | - CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, queryRope, keyRope, sinkOptional, | 1606 | + const aclTensor *dScaleQ = nullptr; |
| 1607 | + const aclTensor *dScaleK = nullptr; | ||
| 1608 | + const aclTensor *dScaleV = nullptr; | ||
| 1609 | + CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | ||
| 1610 | + queryRope, keyRope, sinkOptional, dScaleQ, dScaleK, dScaleV, | ||
| 1439 | l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 1611 | l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); |
| 1440 | 1612 | ||
| 1441 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 1613 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); |
| @@ -1450,15 +1622,15 @@ aclnnStatus aclnnFlashAttentionVarLenScoreV4GetWorkspaceSize( | |||
| 1450 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; | 1622 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; |
| 1451 | // l0SoftmaxOutOut not used now | 1623 | // l0SoftmaxOutOut not used now |
| 1452 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; | 1624 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; |
| 1453 | - | ||
| 1454 | - CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, | ||
| 1455 | - ACLNN_ERR_PARAM_NULLPTR); | ||
| 1456 | if (l0SoftmaxMaxOut == nullptr || l0SoftmaxSumOut == nullptr || l0AttentionOutOut == nullptr) { | 1625 | if (l0SoftmaxMaxOut == nullptr || l0SoftmaxSumOut == nullptr || l0AttentionOutOut == nullptr) { |
| 1457 | OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "l0SoftmaxMaxOut or l0SoftmaxSumOut or l0AttentionOutOut is null"); | 1626 | OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "l0SoftmaxMaxOut or l0SoftmaxSumOut or l0AttentionOutOut is null"); |
| 1458 | *workspaceSize = 0; | 1627 | *workspaceSize = 0; |
| 1459 | uniqueExecutor.ReleaseTo(executor); | 1628 | uniqueExecutor.ReleaseTo(executor); |
| 1460 | return ACLNN_ERR_PARAM_NULLPTR; | 1629 | return ACLNN_ERR_PARAM_NULLPTR; |
| 1461 | } | 1630 | } |
| 1631 | + CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, | ||
| 1632 | + ACLNN_ERR_PARAM_NULLPTR); | ||
| 1633 | + | ||
| 1462 | auto viewCopyResult0 = l0op::ViewCopy(l0SoftmaxMaxOut, softmaxMaxOut, l0Executor); | 1634 | auto viewCopyResult0 = l0op::ViewCopy(l0SoftmaxMaxOut, softmaxMaxOut, l0Executor); |
| 1463 | CHECK_RET(viewCopyResult0 != nullptr, ACLNN_ERR_PARAM_NULLPTR); | 1635 | CHECK_RET(viewCopyResult0 != nullptr, ACLNN_ERR_PARAM_NULLPTR); |
| 1464 | auto viewCopyResult1 = l0op::ViewCopy(l0SoftmaxSumOut, softmaxSumOut, l0Executor); | 1636 | auto viewCopyResult1 = l0op::ViewCopy(l0SoftmaxSumOut, softmaxSumOut, l0Executor); |
| @@ -1517,21 +1689,25 @@ aclnnStatus aclnnFlashAttentionVarLenScoreV5GetWorkspaceSize( | |||
| 1517 | } | 1689 | } |
| 1518 | 1690 | ||
| 1519 | //检查format是否符合要求 | 1691 | //检查format是否符合要求 |
| 1520 | - if (GetCurrentPlatformInfo().GetSocVersion() != SocVersion::ASCEND910_95) { | 1692 | + if (StrideLimited()) { |
| 1521 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | 1693 | CHECK_RET(CheckFormat(query, queryRope, key, keyRope, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, |
| 1522 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); | 1694 | sinkOptional, softmaxMaxOut, softmaxSumOut, attentionOutOut), ACLNN_ERR_PARAM_INVALID); |
| 1523 | } | 1695 | } |
| 1524 | 1696 | ||
| 1525 | FaShapeInfo shapeInfo; | 1697 | FaShapeInfo shapeInfo; |
| 1526 | - CHECK_RET(InputDtypeCheck(query, key, value, realShiftOptional, pseType, sinkOptional) == ACLNN_SUCCESS, | 1698 | + CHECK_RET(InputDtypeCheck(query, key, value, attentionOutOut, realShiftOptional, pseType, sinkOptional) == ACLNN_SUCCESS, |
| 1527 | ACLNN_ERR_PARAM_INVALID); | 1699 | ACLNN_ERR_PARAM_INVALID); |
| 1528 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo, actualSeqQLenOptional, | 1700 | CHECK_RET(AnalysisInput(query, key, value, inputLayout, headNum, shapeInfo, actualSeqQLenOptional, |
| 1529 | actualSeqKvLenOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); | 1701 | actualSeqKvLenOptional) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_INVALID); |
| 1530 | 1702 | ||
| 1531 | aclOpExecutor *l0Executor = uniqueExecutor.get(); | 1703 | aclOpExecutor *l0Executor = uniqueExecutor.get(); |
| 1532 | 1704 | ||
| 1533 | - CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, queryRope, keyRope, sinkOptional, | 1705 | + const aclTensor *dScaleQ = nullptr; |
| 1534 | - l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 1706 | + const aclTensor *dScaleK = nullptr; |
| 1707 | + const aclTensor *dScaleV = nullptr; | ||
| 1708 | + CHECK_RET(Contiguous(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | ||
| 1709 | + queryRope, keyRope, sinkOptional, dScaleQ, dScaleK, dScaleV, | ||
| 1710 | + l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | ||
| 1535 | 1711 | ||
| 1536 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); | 1712 | CHECK_RET(PreprocessQKV(query, key, value, shapeInfo, l0Executor) == ACLNN_SUCCESS, ACLNN_ERR_PARAM_NULLPTR); |
| 1537 | 1713 | ||
| @@ -1552,15 +1728,15 @@ aclnnStatus aclnnFlashAttentionVarLenScoreV5GetWorkspaceSize( | |||
| 1552 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; | 1728 | auto l0SoftmaxSumOut = l0FlashAttentionScoreOuts[1]; |
| 1553 | // l0SoftmaxOutOut not used now | 1729 | // l0SoftmaxOutOut not used now |
| 1554 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; | 1730 | auto l0AttentionOutOut = l0FlashAttentionScoreOuts[3]; |
| 1555 | - | 1731 | + if (l0SoftmaxMaxOut == nullptr || l0SoftmaxSumOut == nullptr || l0AttentionOutOut == nullptr) { |
| 1732 | + OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "l0SoftmaxMaxOut or l0SoftmaxSumOut or l0AttentionOutOut is null"); | ||
| 1733 | + *workspaceSize = 0; | ||
| 1734 | + uniqueExecutor.ReleaseTo(executor); | ||
| 1735 | + return ACLNN_ERR_PARAM_NULLPTR; | ||
| 1736 | + } | ||
| 1556 | CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, | 1737 | CHECK_RET(Postprocess(l0AttentionOutOut, attentionOutOut, shapeInfo, l0Executor) == ACLNN_SUCCESS, |
| 1557 | ACLNN_ERR_PARAM_NULLPTR); | 1738 | ACLNN_ERR_PARAM_NULLPTR); |
| 1558 | - if (l0SoftmaxMaxOut == nullptr || l0SoftmaxSumOut == nullptr || l0AttentionOutOut == nullptr) { | 1739 | + |
| 1559 | - OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "l0SoftmaxMaxOut or l0SoftmaxSumOut or l0AttentionOutOut is null"); | ||
| 1560 | - *workspaceSize = 0; | ||
| 1561 | - uniqueExecutor.ReleaseTo(executor); | ||
| 1562 | - return ACLNN_ERR_PARAM_NULLPTR; | ||
| 1563 | - } | ||
| 1564 | auto viewCopyResult0 = l0op::ViewCopy(l0SoftmaxMaxOut, softmaxMaxOut, l0Executor); | 1740 | auto viewCopyResult0 = l0op::ViewCopy(l0SoftmaxMaxOut, softmaxMaxOut, l0Executor); |
| 1565 | CHECK_RET(viewCopyResult0 != nullptr, ACLNN_ERR_PARAM_NULLPTR); | 1741 | CHECK_RET(viewCopyResult0 != nullptr, ACLNN_ERR_PARAM_NULLPTR); |
| 1566 | auto viewCopyResult1 = l0op::ViewCopy(l0SoftmaxSumOut, softmaxSumOut, l0Executor); | 1742 | auto viewCopyResult1 = l0op::ViewCopy(l0SoftmaxSumOut, softmaxSumOut, l0Executor); |
| @@ -136,7 +136,7 @@ const std::array<const aclTensor *, 4> FlashAttentionScore( | |||
| 136 | return {nullptr, nullptr, nullptr, nullptr}; | 136 | return {nullptr, nullptr, nullptr, nullptr}; |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | - ADD_TO_LAUNCHER_LIST_AICORE( | 139 | + ret = ADD_TO_LAUNCHER_LIST_AICORE( |
| 140 | FlashAttentionScore, | 140 | FlashAttentionScore, |
| 141 | OP_INPUT(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, | 141 | OP_INPUT(query, key, value, realShiftOptional, dropMaskOptional, paddingMaskOptional, attenMaskOptional, |
| 142 | prefixOptionalTensor, actualSeqQLen, actualSeqKvLen, qStartIdxOptionalTensor, kvStartIdxOptionalTensor, | 142 | prefixOptionalTensor, actualSeqQLen, actualSeqKvLen, qStartIdxOptionalTensor, kvStartIdxOptionalTensor, |
| @@ -145,6 +145,10 @@ const std::array<const aclTensor *, 4> FlashAttentionScore( | |||
| 145 | OP_ATTR(static_cast<float>(scaleValue), static_cast<float>(keepProb), preTockens, | 145 | OP_ATTR(static_cast<float>(scaleValue), static_cast<float>(keepProb), preTockens, |
| 146 | nextTockens, headNum, inputLayout, innerPrecise, sparseMode, pseType, | 146 | nextTockens, headNum, inputLayout, innerPrecise, sparseMode, pseType, |
| 147 | seed, offset, outDtype, softmaxOutLayout)); | 147 | seed, offset, outDtype, softmaxOutLayout)); |
| 148 | + if (ret != ACLNN_SUCCESS) { | ||
| 149 | + OP_LOGE(ACLNN_ERR_PARAM_INVALID, "FlashAttentionScore launch kernel failed."); | ||
| 150 | + return {nullptr, nullptr, nullptr, nullptr}; | ||
| 151 | + } | ||
| 148 | return {softmaxMaxOut, softmaxSumOut, softmaxOutOut, attentionOutOut}; | 152 | return {softmaxMaxOut, softmaxSumOut, softmaxOutOut, attentionOutOut}; |
| 149 | } | 153 | } |
| 150 | 154 | ||
| @@ -4533,11 +4533,11 @@ protected: | |||
| 4533 | }; | 4533 | }; |
| 4534 | 4534 | ||
| 4535 | // NOTE manually initialize tiling data in hostapi scenario in highest priority template | 4535 | // NOTE manually initialize tiling data in hostapi scenario in highest priority template |
| 4536 | -REGISTER_TILING_TEMPLATE_WITH_SOCVERSION(FlashAttentionScore, FlashAttentionScoreTilingDropMask, std::vector<int32_t>({static_cast<int32_t>(platform_ascendc::SocVersion::ASCEND910B), static_cast<int32_t>(platform_ascendc::SocVersion::ASCEND910_93)}), 90); | 4536 | +REGISTER_TILING_TEMPLATE_WITH_ARCH(FlashAttentionScore, FlashAttentionScoreTilingDropMask, std::vector<int32_t>({static_cast<int32_t>(NpuArch::DAV_2201)}), 90); |
| 4537 | -REGISTER_TILING_TEMPLATE_WITH_SOCVERSION(FlashAttentionScore, FlashAttentionVarLenScoreTiling, std::vector<int32_t>({static_cast<int32_t>(platform_ascendc::SocVersion::ASCEND910B), static_cast<int32_t>(platform_ascendc::SocVersion::ASCEND910_93)}), 94); | 4537 | +REGISTER_TILING_TEMPLATE_WITH_ARCH(FlashAttentionScore, FlashAttentionVarLenScoreTiling, std::vector<int32_t>({static_cast<int32_t>(NpuArch::DAV_2201)}), 94); |
| 4538 | -REGISTER_TILING_TEMPLATE_WITH_SOCVERSION(FlashAttentionScore, FlashAttentionScoreTilingS1s2Bn2gs1SameAB, std::vector<int32_t>({static_cast<int32_t>(platform_ascendc::SocVersion::ASCEND910B), static_cast<int32_t>(platform_ascendc::SocVersion::ASCEND910_93)}), 95); | 4538 | +REGISTER_TILING_TEMPLATE_WITH_ARCH(FlashAttentionScore, FlashAttentionScoreTilingS1s2Bn2gs1SameAB, std::vector<int32_t>({static_cast<int32_t>(NpuArch::DAV_2201)}), 95); |
| 4539 | -REGISTER_TILING_TEMPLATE_WITH_SOCVERSION(FlashAttentionScore, FlashAttentionScoreTilingS1s2Bn2gs1, std::vector<int32_t>({static_cast<int32_t>(platform_ascendc::SocVersion::ASCEND910B), static_cast<int32_t>(platform_ascendc::SocVersion::ASCEND910_93)}), 96); | 4539 | +REGISTER_TILING_TEMPLATE_WITH_ARCH(FlashAttentionScore, FlashAttentionScoreTilingS1s2Bn2gs1, std::vector<int32_t>({static_cast<int32_t>(NpuArch::DAV_2201)}), 96); |
| 4540 | -REGISTER_TILING_TEMPLATE_WITH_SOCVERSION(FlashAttentionScore, FlashAttentionScoreTilingS1Bn2gs1, std::vector<int32_t>({static_cast<int32_t>(platform_ascendc::SocVersion::ASCEND910B), static_cast<int32_t>(platform_ascendc::SocVersion::ASCEND910_93)}), 97); | 4540 | +REGISTER_TILING_TEMPLATE_WITH_ARCH(FlashAttentionScore, FlashAttentionScoreTilingS1Bn2gs1, std::vector<int32_t>({static_cast<int32_t>(NpuArch::DAV_2201)}), 97); |
| 4541 | -REGISTER_TILING_TEMPLATE_WITH_SOCVERSION(FlashAttentionScore, FlashAttentionScoreTilingB, std::vector<int32_t>({static_cast<int32_t>(platform_ascendc::SocVersion::ASCEND910B), static_cast<int32_t>(platform_ascendc::SocVersion::ASCEND910_93)}), 98); | 4541 | +REGISTER_TILING_TEMPLATE_WITH_ARCH(FlashAttentionScore, FlashAttentionScoreTilingB, std::vector<int32_t>({static_cast<int32_t>(NpuArch::DAV_2201)}), 98); |
| 4542 | } // namespace FA | 4542 | } // namespace FA |
| 4543 | } // namespace optiling | 4543 | } // namespace optiling |
| @@ -409,6 +409,7 @@ protected: | |||
| 409 | uint32_t aivNum; | 409 | uint32_t aivNum; |
| 410 | uint32_t aicNum; | 410 | uint32_t aicNum; |
| 411 | platform_ascendc::SocVersion socVersion; | 411 | platform_ascendc::SocVersion socVersion; |
| 412 | + NpuArch npuArch = NpuArch::DAV_RESV; | ||
| 412 | 413 | ||
| 413 | matmul_tiling::DataType bmmDtype = matmul_tiling::DataType::DT_FLOAT; | 414 | matmul_tiling::DataType bmmDtype = matmul_tiling::DataType::DT_FLOAT; |
| 414 | matmul_tiling::DataType bmm1OutDtype = matmul_tiling::DataType::DT_FLOAT; | 415 | matmul_tiling::DataType bmm1OutDtype = matmul_tiling::DataType::DT_FLOAT; |
| @@ -355,19 +355,19 @@ ASCENDC_EXTERN_C ge::graphStatus TilingFlashAttentionScore(gert::TilingContext * | |||
| 355 | return ge::GRAPH_FAILED); | 355 | return ge::GRAPH_FAILED); |
| 356 | 356 | ||
| 357 | auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfoPtr); | 357 | auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfoPtr); |
| 358 | - if (ascendcPlatform.GetSocVersion() == platform_ascendc::SocVersion::ASCEND910_95) { | 358 | + if (ascendcPlatform.GetCurNpuArch() == NpuArch::DAV_3510) { |
| 359 | - OP_LOGW(context, "Current soc version is ASCEND910_95."); | 359 | + OP_LOGW(context, "Current npu arch is dav-3510."); |
| 360 | if (IsEmptyInputRegbase(context)) { | 360 | if (IsEmptyInputRegbase(context)) { |
| 361 | return ge::GRAPH_SUCCESS; | 361 | return ge::GRAPH_SUCCESS; |
| 362 | } | 362 | } |
| 363 | } else { | 363 | } else { |
| 364 | - OP_LOGW(context, "Current soc version is not ASCEND910_95."); | 364 | + OP_LOGW(context, "Current npu arch is not dav-3510."); |
| 365 | if (IsEmptyInput(context)) { | 365 | if (IsEmptyInput(context)) { |
| 366 | return ge::GRAPH_SUCCESS; | 366 | return ge::GRAPH_SUCCESS; |
| 367 | } | 367 | } |
| 368 | } | 368 | } |
| 369 | 369 | ||
| 370 | - auto resultCode = TilingRegistryNew::GetInstance().DoTilingImpl(context); | 370 | + auto resultCode = TilingRegistryArch::GetInstance().DoTilingImpl(context); |
| 371 | return resultCode; | 371 | return resultCode; |
| 372 | } | 372 | } |
| 373 | 373 | ||
| @@ -386,6 +386,7 @@ ASCENDC_EXTERN_C ge::graphStatus TilingPrepareForFlashAttentionScore(gert::Tilin | |||
| 386 | compileInfoPtr->aivNum = ascendcPlatform.GetCoreNumAiv(); | 386 | compileInfoPtr->aivNum = ascendcPlatform.GetCoreNumAiv(); |
| 387 | compileInfoPtr->aicNum = ascendcPlatform.GetCoreNumAic(); | 387 | compileInfoPtr->aicNum = ascendcPlatform.GetCoreNumAic(); |
| 388 | compileInfoPtr->socVersion = ascendcPlatform.GetSocVersion(); | 388 | compileInfoPtr->socVersion = ascendcPlatform.GetSocVersion(); |
| 389 | + compileInfoPtr->npuArch = ascendcPlatform.GetCurNpuArch(); | ||
| 389 | ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, compileInfoPtr->ubSize); | 390 | ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, compileInfoPtr->ubSize); |
| 390 | ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L1, compileInfoPtr->l1Size); | 391 | ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L1, compileInfoPtr->l1Size); |
| 391 | ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L0_C, compileInfoPtr->l0cSize); | 392 | ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L0_C, compileInfoPtr->l0cSize); |
| @@ -28,6 +28,7 @@ struct FlashAttentionScoreCompileInfo { | |||
| 28 | uint64_t l0cSize; | 28 | uint64_t l0cSize; |
| 29 | uint64_t l2CacheSize; | 29 | uint64_t l2CacheSize; |
| 30 | platform_ascendc::SocVersion socVersion; | 30 | platform_ascendc::SocVersion socVersion; |
| 31 | + NpuArch npuArch; | ||
| 31 | }; | 32 | }; |
| 32 | 33 | ||
| 33 | } // namespace optiling | 34 | } // namespace optiling |
| @@ -0,0 +1,133 @@ | |||
| 1 | +/** | ||
| 2 | + * This program is free software, you can redistribute it and/or modify. | ||
| 3 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | + * This file is a part of the CANN Open Software. | ||
| 5 | + * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file common_header.h | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +constexpr int32_t BASE_BLOCK_LENGTH = 128; | ||
| 26 | +constexpr int32_t C0_SIZE = 16; | ||
| 27 | +constexpr int32_t SIZE_16 = 16; | ||
| 28 | +constexpr int32_t SIZE_32 = 32; | ||
| 29 | +constexpr int32_t SIZE_64 = 64; | ||
| 30 | +constexpr int32_t SIZE_128 = 128; | ||
| 31 | +constexpr int32_t SIZE_256 = 256; | ||
| 32 | +constexpr int32_t SIZE_384 = 384; | ||
| 33 | +constexpr int32_t SIZE_512 = 512; | ||
| 34 | +constexpr int32_t SIZE_ONE_K = 1024; | ||
| 35 | +constexpr int32_t SIZE_LONG_BLOCK = 16384; | ||
| 36 | +constexpr int32_t BASE_M_128 = 128; | ||
| 37 | +constexpr int32_t BASE_N_128 = 128; | ||
| 38 | + | ||
| 39 | +enum class ArchType { ASCEND_V220, ASCEND_V200, ASCEND_M200 }; | ||
| 40 | +enum class BufferType { ASCEND_UB, ASCEND_CB, ASCEND_L0A, ASCEND_L0B, ASCEND_L0C, ASCEND_MAX }; | ||
| 41 | + | ||
| 42 | +template <ArchType ArchTag> | ||
| 43 | +struct HardwareInfo { | ||
| 44 | + static uint32_t const l2BW = 5; | ||
| 45 | + static uint32_t const hbmBW = 1; | ||
| 46 | + static uint32_t const supportMix = 0; | ||
| 47 | + static uint32_t const l1Size = 512 * 1024; | ||
| 48 | + static uint32_t const l0ASize = 64 * 1024; | ||
| 49 | + static uint32_t const l0BSize = 64 * 1024; | ||
| 50 | + static uint32_t const l0CSize = 128 * 1024; | ||
| 51 | + static uint32_t const l2Size = 192 * 1024 * 1024; | ||
| 52 | + static uint32_t const biasSize = 1024; | ||
| 53 | + static uint32_t const fixBufSize = 7 * 1024; | ||
| 54 | + static uint32_t const ubSize = 192 * 1024; | ||
| 55 | + static uint32_t const fractalSize = 512; | ||
| 56 | + static uint32_t const l1l0BlockSize = 32; | ||
| 57 | + static uint32_t const btBlockSize = 64; | ||
| 58 | + static uint32_t const fbBlockSize = 128; | ||
| 59 | +}; | ||
| 60 | + | ||
| 61 | + | ||
| 62 | +template <ArchType ArchTag> | ||
| 63 | +struct AsdopsBuffer { | ||
| 64 | +public: | ||
| 65 | + __aicore__ AsdopsBuffer() | ||
| 66 | + { | ||
| 67 | + constexpr uint32_t bufferSize[(uint32_t)BufferType::ASCEND_MAX] = {HardwareInfo<ArchTag>::ubSize, | ||
| 68 | + HardwareInfo<ArchTag>::l1Size, | ||
| 69 | + HardwareInfo<ArchTag>::l0ASize, | ||
| 70 | + HardwareInfo<ArchTag>::l0BSize, | ||
| 71 | + HardwareInfo<ArchTag>::l0CSize}; | ||
| 72 | + | ||
| 73 | + tensor[(uint32_t)BufferType::ASCEND_UB].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_UB]); | ||
| 74 | + tensor[(uint32_t)BufferType::ASCEND_UB].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::VECIN); | ||
| 75 | + | ||
| 76 | + tensor[(uint32_t)BufferType::ASCEND_CB].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_CB]); | ||
| 77 | + tensor[(uint32_t)BufferType::ASCEND_CB].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::A1); | ||
| 78 | + tensor[(uint32_t)BufferType::ASCEND_L0A].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0A]); | ||
| 79 | + tensor[(uint32_t)BufferType::ASCEND_L0A].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::A2); | ||
| 80 | + tensor[(uint32_t)BufferType::ASCEND_L0B].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0B]); | ||
| 81 | + tensor[(uint32_t)BufferType::ASCEND_L0B].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::B2); | ||
| 82 | + tensor[(uint32_t)BufferType::ASCEND_L0C].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0C]); | ||
| 83 | + tensor[(uint32_t)BufferType::ASCEND_L0C].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::CO1); | ||
| 84 | + | ||
| 85 | + tensor[(uint32_t)BufferType::ASCEND_UB].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_UB]); | ||
| 86 | + tensor[(uint32_t)BufferType::ASCEND_UB].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::VECIN); | ||
| 87 | + tensor[(uint32_t)BufferType::ASCEND_CB].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_CB]); | ||
| 88 | + tensor[(uint32_t)BufferType::ASCEND_CB].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::A1); | ||
| 89 | + tensor[(uint32_t)BufferType::ASCEND_L0A].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0A]); | ||
| 90 | + tensor[(uint32_t)BufferType::ASCEND_L0A].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::A2); | ||
| 91 | + tensor[(uint32_t)BufferType::ASCEND_L0B].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0B]); | ||
| 92 | + tensor[(uint32_t)BufferType::ASCEND_L0B].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::B2); | ||
| 93 | + tensor[(uint32_t)BufferType::ASCEND_L0C].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0C]); | ||
| 94 | + tensor[(uint32_t)BufferType::ASCEND_L0C].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::CO1); | ||
| 95 | + | ||
| 96 | + }; | ||
| 97 | + | ||
| 98 | + template <BufferType BufferType_, typename DstDataType = half> | ||
| 99 | + __aicore__ AscendC::LocalTensor<DstDataType> GetBuffer(const uint32_t offset) const | ||
| 100 | + { | ||
| 101 | + return tensor[(uint32_t)BufferType_][offset].template ReinterpretCast<DstDataType>(); | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | +public: | ||
| 105 | + AscendC::LocalTensor<uint8_t> tensor[(uint32_t)BufferType::ASCEND_MAX]; | ||
| 106 | +}; | ||
| 107 | + | ||
| 108 | +struct AddrInfo { | ||
| 109 | + uint64_t left; | ||
| 110 | + uint64_t right; | ||
| 111 | + uint64_t out; | ||
| 112 | + int32_t kx = 0; | ||
| 113 | + int32_t ky = 0; | ||
| 114 | + int32_t lineStride = 0; | ||
| 115 | + bool lowerLeft; | ||
| 116 | + bool upperRight; | ||
| 117 | + int32_t S1Idx; | ||
| 118 | + int32_t S2Idx; | ||
| 119 | + int32_t blockStart; | ||
| 120 | +}; | ||
| 121 | + | ||
| 122 | + | ||
| 123 | +template <typename T> | ||
| 124 | +inline __aicore__ T RoundUp(const T val, const T align) | ||
| 125 | +{ | ||
| 126 | + static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type"); | ||
| 127 | + if (align == 0 || val + align - 1 < val) { | ||
| 128 | + return val; | ||
| 129 | + } | ||
| 130 | + return (val + align - 1) / align * align; | ||
| 131 | +} | ||
| 132 | + | ||
| 133 | + | ||
| @@ -0,0 +1,273 @@ | |||
| 1 | +/** | ||
| 2 | + * This program is free software, you can redistribute it and/or modify. | ||
| 3 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | + * This file is a part of the CANN Open Software. | ||
| 5 | + * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file cube1_op.h | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +template <typename TYPE, LayOutTypeEnum layOutType> | ||
| 21 | +__aicore__ inline void | ||
| 22 | +CubeOp1<TYPE, layOutType>::Cube1Compute(const AddrInfo &shapeInfo, __gm__ TYPE* left, __gm__ TYPE* right, __gm__ float* out, bool needNz2Nd) | ||
| 23 | +{ | ||
| 24 | + uint64_t gm2L1SrcDValueA = 0; | ||
| 25 | + uint64_t gm2L1SrcDValueB = 0; | ||
| 26 | + if constexpr (layOutType == LayOutTypeEnum::LAYOUT_TND) { | ||
| 27 | + gm2L1SrcDValueA = headDim * qHeadNum; | ||
| 28 | + gm2L1SrcDValueB = headDim * kvHeadNum; | ||
| 29 | + } else if constexpr (layOutType == LayOutTypeEnum::LAYOUT_BSH) { | ||
| 30 | + gm2L1SrcDValueA = headDim * qHeadNum; | ||
| 31 | + gm2L1SrcDValueB = headDim * kvHeadNum; | ||
| 32 | + } else if constexpr (layOutType == LayOutTypeEnum::LAYOUT_SBH) { | ||
| 33 | + gm2L1SrcDValueA = bNum * headDim * qHeadNum; | ||
| 34 | + gm2L1SrcDValueB = bNum * headDim * kvHeadNum; | ||
| 35 | + } else if constexpr (layOutType == LayOutTypeEnum::LAYOUT_BNSD) { | ||
| 36 | + gm2L1SrcDValueA = headDim; | ||
| 37 | + gm2L1SrcDValueB = headDim; | ||
| 38 | + } | ||
| 39 | + int32_t km = shapeInfo.ky; | ||
| 40 | + int32_t kn = shapeInfo.kx; | ||
| 41 | + | ||
| 42 | + int32_t l1_m_size_ = km; | ||
| 43 | + | ||
| 44 | + int32_t n_loop = CeilDiv(kn, BASE_N_128); | ||
| 45 | + | ||
| 46 | + auto gm_a = left + shapeInfo.left; | ||
| 47 | + auto gm_b = right + shapeInfo.right; | ||
| 48 | + auto gm_c = out; | ||
| 49 | + | ||
| 50 | + uint64_t left_offset = gm_a - (__gm__ TYPE*)0; | ||
| 51 | + uint64_t right_offset = gm_b - (__gm__ TYPE*)0; | ||
| 52 | + uint64_t out_offset = gm_c - (__gm__ float*)0; | ||
| 53 | + | ||
| 54 | + LocalTensor<TYPE>* l1_a_tensor = ping_pong_flag_l1_a_ ? &l1_a_pong_tensor : &l1_a_ping_tensor; | ||
| 55 | + | ||
| 56 | + Cube1LoadDataAToL1(*l1_a_tensor, temp_tensor_bf16[left_offset], l1_m_size_, gm2L1SrcDValueA); | ||
| 57 | + | ||
| 58 | + for (int n_index = 0; n_index < n_loop; n_index++) { | ||
| 59 | + int32_t l1_n_size_ = (n_index == n_loop - 1) ? (kn - n_index * BASE_N_128) : BASE_N_128; | ||
| 60 | + LocalTensor<TYPE>* l1_b_tensor = ping_pong_flag_l1_b_ ? &l1_b_pong_tensor : &l1_b_ping_tensor; | ||
| 61 | + | ||
| 62 | + Cube1LoadDataBToL1(*l1_b_tensor, temp_tensor_bf16[right_offset + n_index * BASE_N_128 * gm2L1SrcDValueB], | ||
| 63 | + l1_n_size_, gm2L1SrcDValueB); | ||
| 64 | + | ||
| 65 | + int32_t l1_m_size_align_ = RoundUp(l1_m_size_, C0_SIZE); | ||
| 66 | + int32_t l1_n_size_align_ = RoundUp(l1_n_size_, C0_SIZE); | ||
| 67 | + | ||
| 68 | + for (int n_offset = 0; n_offset < l1_n_size_; n_offset += BASE_BLOCK_LENGTH) { | ||
| 69 | + int32_t n_mad_ = Min((l1_n_size_ - n_offset), BASE_BLOCK_LENGTH); | ||
| 70 | + int32_t n0_ = RoundUp(n_mad_, C0_SIZE); | ||
| 71 | + | ||
| 72 | + LocalTensor<TYPE>* l0_b_tensor = ping_pong_flag_l0_b_ ? &l0_b_pong_tensor : &l0_b_ping_tensor; | ||
| 73 | + | ||
| 74 | + Cube1LoadDataBToL0((*l0_b_tensor), (*l1_b_tensor), n0_, n_offset, l1_n_size_align_, l1_n_size_); | ||
| 75 | + | ||
| 76 | + for (int m_offset = 0; m_offset < l1_m_size_; m_offset += SIZE_128) { | ||
| 77 | + int32_t m_mad_ = Min((l1_m_size_ - m_offset), BASE_BLOCK_LENGTH); | ||
| 78 | + int32_t m0_ = RoundUp(m_mad_, C0_SIZE); | ||
| 79 | + | ||
| 80 | + LocalTensor<TYPE>* l0_a_tensor = ping_pong_flag_l0_a_ ? &l0_a_pong_tensor : &l0_a_ping_tensor; | ||
| 81 | + | ||
| 82 | + Cube1LoadDataAToL0((*l0_a_tensor), (*l1_a_tensor), l1_m_size_align_, m0_, headDim, m_offset); | ||
| 83 | + | ||
| 84 | + LocalTensor<float>* l0_c_tensor = ping_pong_flag_l0_c_ ? &l0_c_pong_tensor : &l0_c_ping_tensor; | ||
| 85 | + Cube1Mmad(*l0_c_tensor, *l0_a_tensor, *l0_b_tensor, m_mad_, n_mad_); | ||
| 86 | + | ||
| 87 | + SET_FLAG(M, MTE1, FLAG_SHIFT + ping_pong_flag_l0_a_); | ||
| 88 | + | ||
| 89 | + Cube1CopyOut(temp_tensor_fp32, *l0_c_tensor, out_offset, m_mad_, m0_, | ||
| 90 | + n0_, l1_m_size_, n_index, m_offset, n_mad_, kn, needNz2Nd); | ||
| 91 | + | ||
| 92 | + ping_pong_flag_l0_c_ = 1 - ping_pong_flag_l0_c_; | ||
| 93 | + ping_pong_flag_l0_a_ = 1 - ping_pong_flag_l0_a_; | ||
| 94 | + } | ||
| 95 | + SET_FLAG(M, MTE1, FLAG_SHIFT + ping_pong_flag_l0_b_ + 2); | ||
| 96 | + ping_pong_flag_l0_b_ = 1 - ping_pong_flag_l0_b_; | ||
| 97 | + } | ||
| 98 | + SET_FLAG(MTE1, MTE2, ping_pong_flag_l1_b_); | ||
| 99 | + ping_pong_flag_l1_b_ = 1 - ping_pong_flag_l1_b_; | ||
| 100 | + } | ||
| 101 | + SET_FLAG(MTE1, MTE2, ping_pong_flag_l1_a_ + 2); | ||
| 102 | + ping_pong_flag_l1_a_ = 1 - ping_pong_flag_l1_a_; | ||
| 103 | +} | ||
| 104 | + | ||
| 105 | +template <typename TYPE, LayOutTypeEnum layOutType> | ||
| 106 | +__aicore__ inline void | ||
| 107 | +CubeOp1<TYPE, layOutType>::Cube1LoadDataBToL1(LocalTensor<TYPE> dstTensor, | ||
| 108 | + GlobalTensor<TYPE> srcTensor, | ||
| 109 | + int32_t l1_n_size_, uint64_t gm2L1SrcDValueB) | ||
| 110 | +{ | ||
| 111 | + int32_t l1_n_size_align_ = RoundUp(l1_n_size_, C0_SIZE); | ||
| 112 | + commonNd2NzParams.nValue = l1_n_size_; | ||
| 113 | + commonNd2NzParams.dValue = headDim; | ||
| 114 | + commonNd2NzParams.srcDValue = gm2L1SrcDValueB; | ||
| 115 | + commonNd2NzParams.dstNzC0Stride = l1_n_size_align_; | ||
| 116 | + WAIT_FLAG(MTE1, MTE2, ping_pong_flag_l1_b_); | ||
| 117 | + AscendC::DataCopy( | ||
| 118 | + dstTensor, | ||
| 119 | + srcTensor, | ||
| 120 | + commonNd2NzParams | ||
| 121 | + ); | ||
| 122 | + SET_FLAG(MTE2, MTE1, ping_pong_flag_l1_b_); | ||
| 123 | + WAIT_FLAG(MTE2, MTE1, ping_pong_flag_l1_b_); | ||
| 124 | +} | ||
| 125 | + | ||
| 126 | +template <typename TYPE, LayOutTypeEnum layOutType> | ||
| 127 | +__aicore__ inline void | ||
| 128 | +CubeOp1<TYPE, layOutType>::Cube1LoadDataAToL1(LocalTensor<TYPE> dstTensor, | ||
| 129 | + GlobalTensor<TYPE> srcTensor, | ||
| 130 | + int32_t l1_m_size_, uint64_t gm2L1SrcDValueA) | ||
| 131 | +{ | ||
| 132 | + int32_t l1_m_size_align_ = RoundUp(l1_m_size_, C0_SIZE); | ||
| 133 | + commonNd2NzParams.nValue = l1_m_size_; | ||
| 134 | + commonNd2NzParams.dValue = headDim; | ||
| 135 | + commonNd2NzParams.srcDValue = gm2L1SrcDValueA; | ||
| 136 | + commonNd2NzParams.dstNzC0Stride = l1_m_size_align_; | ||
| 137 | + WAIT_FLAG(MTE1, MTE2, ping_pong_flag_l1_a_ + 2); | ||
| 138 | + AscendC::DataCopy( | ||
| 139 | + dstTensor, | ||
| 140 | + srcTensor, | ||
| 141 | + commonNd2NzParams | ||
| 142 | + ); | ||
| 143 | + SET_FLAG(MTE2, MTE1, ping_pong_flag_l1_a_ + 2); | ||
| 144 | + WAIT_FLAG(MTE2, MTE1, ping_pong_flag_l1_a_ + 2); | ||
| 145 | +} | ||
| 146 | + | ||
| 147 | +template <typename TYPE, LayOutTypeEnum layOutType> | ||
| 148 | +__aicore__ inline void CubeOp1<TYPE, layOutType>::Cube1CopyOut(GlobalTensor<float> dstTensor, | ||
| 149 | + LocalTensor<float> srcTensor, uint64_t gm_out_offset, int32_t m_mad_, | ||
| 150 | + int32_t m0_, int32_t n0_, int32_t l1_m_size_, | ||
| 151 | + int32_t n_index, int m_offset, int32_t n_mad_, int32_t kn, | ||
| 152 | + bool needNz2Nd) | ||
| 153 | +{ | ||
| 154 | + commonFixpipeParamsV220.mSize = m_mad_; | ||
| 155 | + commonFixpipeParamsV220.srcStride = m0_; | ||
| 156 | + | ||
| 157 | + if (unlikely(needNz2Nd)) { | ||
| 158 | + // NZ出 | ||
| 159 | + commonFixpipeParamsV220.nSize = n0_; | ||
| 160 | + commonFixpipeParamsV220.dstStride = l1_m_size_ * 2; | ||
| 161 | + auto out_offset = n_index * l1_m_size_ * BASE_N_128 + m_offset * SIZE_16; | ||
| 162 | + AscendC::Fixpipe<float, float, AscendC::CFG_NZ>(dstTensor[gm_out_offset + out_offset], | ||
| 163 | + srcTensor, commonFixpipeParamsV220); | ||
| 164 | + } else { | ||
| 165 | + // ND出 | ||
| 166 | + commonFixpipeParamsV220.nSize = n_mad_; | ||
| 167 | + commonFixpipeParamsV220.dstStride = kn; | ||
| 168 | + auto out_offset = kn * m_offset + n_index * BASE_N_128; | ||
| 169 | + AscendC::Fixpipe<float, float, AscendC::CFG_ROW_MAJOR>(dstTensor[gm_out_offset + out_offset], | ||
| 170 | + srcTensor, commonFixpipeParamsV220); | ||
| 171 | + } | ||
| 172 | +} | ||
| 173 | + | ||
| 174 | +template <typename TYPE, LayOutTypeEnum layOutType> | ||
| 175 | +__aicore__ inline void CubeOp1<TYPE, layOutType>::Cube1Mmad(LocalTensor<float> dstCTensor, | ||
| 176 | + LocalTensor<TYPE> srcATensor, | ||
| 177 | + LocalTensor<TYPE> srcBTensor, | ||
| 178 | + int32_t m_mad_, int32_t n_mad_) | ||
| 179 | +{ | ||
| 180 | + uint16_t m_modify = (m_mad_ == 1) ? 2 : m_mad_; | ||
| 181 | + commonMadParams.m = m_modify; | ||
| 182 | + commonMadParams.n = n_mad_; | ||
| 183 | + commonMadParams.k = headDim; | ||
| 184 | + commonMadParams.unitFlag = 3; | ||
| 185 | + commonMadParams.cmatrixInitVal = true; | ||
| 186 | + AscendC::Mmad( | ||
| 187 | + dstCTensor, | ||
| 188 | + srcATensor, | ||
| 189 | + srcBTensor, | ||
| 190 | + commonMadParams | ||
| 191 | + ); | ||
| 192 | +} | ||
| 193 | + | ||
| 194 | +template <typename TYPE, LayOutTypeEnum layOutType> | ||
| 195 | +__aicore__ inline void CubeOp1<TYPE, layOutType>::Cube1LoadDataAToL0(LocalTensor<TYPE> dstTensor, | ||
| 196 | + LocalTensor<TYPE> srcTensor, | ||
| 197 | + int32_t l1_m_size_align_, int32_t m0_, uint64_t headDim, int m_offset) | ||
| 198 | +{ | ||
| 199 | + WAIT_FLAG(M, MTE1, FLAG_SHIFT + ping_pong_flag_l0_a_); | ||
| 200 | + commonLoadData2dParamsNoTranspose.repeatTimes = headDim / SIZE_16; | ||
| 201 | + commonLoadData2dParamsNoTranspose.srcStride = l1_m_size_align_ / SIZE_16; | ||
| 202 | + for (int32_t i = 0; i < m0_ / SIZE_16; i++) { | ||
| 203 | + AscendC::LoadData( | ||
| 204 | + dstTensor[i * headDim * SIZE_16], | ||
| 205 | + srcTensor[m_offset * SIZE_16 + i * SIZE_256], | ||
| 206 | + commonLoadData2dParamsNoTranspose | ||
| 207 | + ); | ||
| 208 | + } | ||
| 209 | + SET_FLAG(MTE1, M, ping_pong_flag_l0_a_); | ||
| 210 | + WAIT_FLAG(MTE1, M, ping_pong_flag_l0_a_); | ||
| 211 | +} | ||
| 212 | + | ||
| 213 | +template <typename TYPE, LayOutTypeEnum layOutType> | ||
| 214 | +__aicore__ inline void CubeOp1<TYPE, layOutType>::Cube1LoadDataBToL0(LocalTensor<TYPE> dstTensor, | ||
| 215 | + LocalTensor<TYPE> srcTensor, | ||
| 216 | + int32_t n0_, int n_offset, int32_t l1_n_size_align_, int32_t l1_n_size_) | ||
| 217 | +{ | ||
| 218 | + WAIT_FLAG(M, MTE1, FLAG_SHIFT + ping_pong_flag_l0_b_ + 2); | ||
| 219 | + if (l1_n_size_ == BASE_BLOCK_LENGTH) { | ||
| 220 | + commonLoadData2dParamsNoTranspose.repeatTimes = headDim * n0_ / SIZE_256; | ||
| 221 | + commonLoadData2dParamsNoTranspose.srcStride = 1; | ||
| 222 | + AscendC::LoadData( | ||
| 223 | + dstTensor, | ||
| 224 | + srcTensor, | ||
| 225 | + commonLoadData2dParamsNoTranspose | ||
| 226 | + ); | ||
| 227 | + } else { | ||
| 228 | + commonLoadData2dParamsNoTranspose.repeatTimes = n0_ / SIZE_16; | ||
| 229 | + commonLoadData2dParamsNoTranspose.srcStride = 1; | ||
| 230 | + for (int i = 0; i < headDim / SIZE_16; i++) { | ||
| 231 | + AscendC::LoadData( | ||
| 232 | + dstTensor[i * n0_ * SIZE_16], | ||
| 233 | + srcTensor[i * l1_n_size_align_ * SIZE_16 + n_offset * SIZE_16], | ||
| 234 | + commonLoadData2dParamsNoTranspose | ||
| 235 | + ); | ||
| 236 | + } | ||
| 237 | + } | ||
| 238 | + SET_FLAG(MTE1, M, ping_pong_flag_l0_b_ + 2); | ||
| 239 | + WAIT_FLAG(MTE1, M, ping_pong_flag_l0_b_ + 2); | ||
| 240 | +} | ||
| 241 | + | ||
| 242 | +template <typename TYPE, LayOutTypeEnum layOutType> | ||
| 243 | +__aicore__ inline void CubeOp1<TYPE, layOutType>::SetFlag() | ||
| 244 | +{ | ||
| 245 | + SET_FLAG(MTE1, MTE2, EVENT_ID0); | ||
| 246 | + SET_FLAG(MTE1, MTE2, EVENT_ID1); | ||
| 247 | + SET_FLAG(MTE1, MTE2, EVENT_ID2); | ||
| 248 | + SET_FLAG(MTE1, MTE2, EVENT_ID3); | ||
| 249 | + SET_FLAG(MTE1, MTE2, EVENT_ID4); | ||
| 250 | + SET_FLAG(MTE1, MTE2, EVENT_ID5); | ||
| 251 | + | ||
| 252 | + SET_FLAG(M, MTE1, EVENT_ID3); | ||
| 253 | + SET_FLAG(M, MTE1, EVENT_ID4); | ||
| 254 | + SET_FLAG(M, MTE1, EVENT_ID5); | ||
| 255 | + SET_FLAG(M, MTE1, EVENT_ID6); | ||
| 256 | +} | ||
| 257 | + | ||
| 258 | +template <typename TYPE, LayOutTypeEnum layOutType> | ||
| 259 | +__aicore__ inline void CubeOp1<TYPE, layOutType>::WaitFlag() | ||
| 260 | +{ | ||
| 261 | + WAIT_FLAG(MTE1, MTE2, EVENT_ID0); | ||
| 262 | + WAIT_FLAG(MTE1, MTE2, EVENT_ID1); | ||
| 263 | + WAIT_FLAG(MTE1, MTE2, EVENT_ID2); | ||
| 264 | + WAIT_FLAG(MTE1, MTE2, EVENT_ID3); | ||
| 265 | + WAIT_FLAG(MTE1, MTE2, EVENT_ID4); | ||
| 266 | + WAIT_FLAG(MTE1, MTE2, EVENT_ID5); | ||
| 267 | + | ||
| 268 | + WAIT_FLAG(M, MTE1, EVENT_ID3); | ||
| 269 | + WAIT_FLAG(M, MTE1, EVENT_ID4); | ||
| 270 | + WAIT_FLAG(M, MTE1, EVENT_ID5); | ||
| 271 | + WAIT_FLAG(M, MTE1, EVENT_ID6); | ||
| 272 | +} | ||
| 273 | + | ||
Aattention/flash_attention_score/op_kernel/arch32/basic_modules/cube_modules/cube2_op.h+238-0文件内容审核中,请稍后刷新重试
| @@ -23,6 +23,8 @@ | |||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | + | ||
| 27 | + | ||
| 26 | 28 | ||
| 27 | using matmul::MatmulType; | 29 | using matmul::MatmulType; |
| 28 | using AscendC::CrossCoreSetFlag; | 30 | using AscendC::CrossCoreSetFlag; |
| @@ -397,6 +399,9 @@ protected: | |||
| 397 | uint64_t SYNC_C1_V1_FLAG[3] = {4, 5, 6}; | 399 | uint64_t SYNC_C1_V1_FLAG[3] = {4, 5, 6}; |
| 398 | uint64_t SYNC_V1_C2_FLAG[3] = {7, 8, 9}; | 400 | uint64_t SYNC_V1_C2_FLAG[3] = {7, 8, 9}; |
| 399 | uint64_t SYNC_C2_V2_FLAG[3] = {1, 2, 3}; | 401 | uint64_t SYNC_C2_V2_FLAG[3] = {1, 2, 3}; |
| 402 | + | ||
| 403 | + // 基础API实现MATMUL | ||
| 404 | + CUBE_OP1::CubeOp1<INPUT_T, layOutType> cubeOp; | ||
| 400 | }; | 405 | }; |
| 401 | 406 | ||
| 402 | template <ImplModeEnum implMode, LayOutTypeEnum layOutType, bool hasPse, bool hasAtten, bool hasDrop, typename INPUT_T, | 407 | template <ImplModeEnum implMode, LayOutTypeEnum layOutType, bool hasPse, bool hasAtten, bool hasDrop, typename INPUT_T, |
| @@ -597,6 +602,14 @@ __aicore__ inline void FlashAttentionScoreS1s2Bn2gs1SameAB<implMode, layOutType, | |||
| 597 | this->pipe->InitBuffer(this->softmaxTempBuf, vecS1BaseSize * blockBytes); // 16k | 602 | this->pipe->InitBuffer(this->softmaxTempBuf, vecS1BaseSize * blockBytes); // 16k |
| 598 | } | 603 | } |
| 599 | this->pipe->InitBuffer(this->stage1PongBuf, stage1PongSize); // i.a 34k | 604 | this->pipe->InitBuffer(this->stage1PongBuf, stage1PongSize); // i.a 34k |
| 605 | + if constexpr (mmPolicyType != MmPolicyType::UNSPLITK) { | ||
| 606 | + if (this->dSize == 64) { | ||
| 607 | + cubeOp.Init(this->n2G, | ||
| 608 | + this->tilingData->inputParams.n2Size, | ||
| 609 | + this->dSize, | ||
| 610 | + this->tilingData->inputParams.bSize); | ||
| 611 | + } | ||
| 612 | + } | ||
| 600 | } | 613 | } |
| 601 | 614 | ||
| 602 | template <ImplModeEnum implMode, LayOutTypeEnum layOutType, bool hasPse, bool hasAtten, bool hasDrop, typename INPUT_T, | 615 | template <ImplModeEnum implMode, LayOutTypeEnum layOutType, bool hasPse, bool hasAtten, bool hasDrop, typename INPUT_T, |
| @@ -641,7 +654,7 @@ __aicore__ inline void FlashAttentionScoreS1s2Bn2gs1SameAB<implMode, layOutType, | |||
| 641 | // 计算切分轴的乘积 | 654 | // 计算切分轴的乘积 |
| 642 | this->s2BaseN2D = this->s2BaseSize * this->n2D; | 655 | this->s2BaseN2D = this->s2BaseSize * this->n2D; |
| 643 | this->s2BaseNratioSize = this->s2BaseSize * this->tilingData->coreParams.nRatio; | 656 | this->s2BaseNratioSize = this->s2BaseSize * this->tilingData->coreParams.nRatio; |
| 644 | - | 657 | + |
| 645 | if constexpr (hasRope == true) { | 658 | if constexpr (hasRope == true) { |
| 646 | this->gDRope = this->tilingData->inputParams.gSize * dRopeSize; | 659 | this->gDRope = this->tilingData->inputParams.gSize * dRopeSize; |
| 647 | this->n2DRope = this->tilingData->inputParams.n2Size * dRopeSize; | 660 | this->n2DRope = this->tilingData->inputParams.n2Size * dRopeSize; |
| @@ -673,7 +686,7 @@ __aicore__ inline void FlashAttentionScoreS1s2Bn2gs1SameAB<implMode, layOutType, | |||
| 673 | this->mm1Ka2 = this->bN2GDRope; | 686 | this->mm1Ka2 = this->bN2GDRope; |
| 674 | this->mm1Kb1 = this->bN2D; | 687 | this->mm1Kb1 = this->bN2D; |
| 675 | this->mm1Kb2 = this->bN2DRope; | 688 | this->mm1Kb2 = this->bN2DRope; |
| 676 | - this->mm1Kb = this->mm1Kb1 + this->mm1Kb2; | 689 | + this->mm1Kb = this->mm1Kb1 + this->mm1Kb2; |
| 677 | this->mm2Kb = this->bN2D2; | 690 | this->mm2Kb = this->bN2D2; |
| 678 | } else if constexpr (layOutType == LayOutTypeEnum::LAYOUT_BNSD) { | 691 | } else if constexpr (layOutType == LayOutTypeEnum::LAYOUT_BNSD) { |
| 679 | // BNSD | 692 | // BNSD |
| @@ -682,7 +695,7 @@ __aicore__ inline void FlashAttentionScoreS1s2Bn2gs1SameAB<implMode, layOutType, | |||
| 682 | this->s2BaseNratioD = this->s2BaseNratioSize * this->dSize; | 695 | this->s2BaseNratioD = this->s2BaseNratioSize * this->dSize; |
| 683 | this->mm1Ka1 = this->dSize; | 696 | this->mm1Ka1 = this->dSize; |
| 684 | this->mm1Kb1 = this->dSize; | 697 | this->mm1Kb1 = this->dSize; |
| 685 | - this->mm1Kb = this->mm1Kb1; | 698 | + this->mm1Kb = this->mm1Kb1; |
| 686 | this->mm2Kb = this->d2Size; | 699 | this->mm2Kb = this->d2Size; |
| 687 | } | 700 | } |
| 688 | 701 | ||
| @@ -1150,9 +1163,17 @@ FlashAttentionScoreS1s2Bn2gs1SameAB<implMode, layOutType, hasPse, hasAtten, hasD | |||
| 1150 | this->Bmm1SetTensorA(extraInfo, bmm1); | 1163 | this->Bmm1SetTensorA(extraInfo, bmm1); |
| 1151 | this->SetBmm1TensorB(extraInfo, bmm1); | 1164 | this->SetBmm1TensorB(extraInfo, bmm1); |
| 1152 | if constexpr (mmPolicyType != MmPolicyType::UNSPLITK) { | 1165 | if constexpr (mmPolicyType != MmPolicyType::UNSPLITK) { |
| 1153 | - bmm1.template IterateAll<false>(this->mm1Res[extraInfo.taskIdMod2], hasRope, false, true); | 1166 | + if (this->dSize != 64) |
| 1154 | - bmm1.End(); | 1167 | + { |
| 1155 | - return; | 1168 | + bmm1.template IterateAll<false>(this->mm1Res[extraInfo.taskIdMod2], hasRope, false, true); |
| 1169 | + bmm1.End(); | ||
| 1170 | + return; | ||
| 1171 | + } else | ||
| 1172 | + { | ||
| 1173 | + cubeOp.Cube1Process(extraInfo.qCoreOffset, extraInfo.kCoreOffset, extraInfo.cubeS1RealSize, extraInfo.s2RealSize, | ||
| 1174 | + this->queryGm, this->keyGm, this->mm1Res[extraInfo.taskIdMod2], extraInfo.needNz2Nd); | ||
| 1175 | + return; | ||
| 1176 | + } | ||
| 1156 | } | 1177 | } |
| 1157 | 1178 | ||
| 1158 | int32_t aRowNum = extraInfo.cubeS1RealSize / mm1BaseM; | 1179 | int32_t aRowNum = extraInfo.cubeS1RealSize / mm1BaseM; |
| @@ -2284,12 +2305,19 @@ __aicore__ inline void FlashAttentionScoreS1s2Bn2gs1SameAB<implMode, layOutType, | |||
| 2284 | bmm2.SetTensorA(this->stage1Res[extraInfo.taskIdMod2]); | 2305 | bmm2.SetTensorA(this->stage1Res[extraInfo.taskIdMod2]); |
| 2285 | bmm2.SetTensorB(this->valueGm[vCoreOffset]); | 2306 | bmm2.SetTensorB(this->valueGm[vCoreOffset]); |
| 2286 | bmm2.SetTail(extraInfo.cubeS1RealSize, this->d2Size, extraInfo.s2RealSize); | 2307 | bmm2.SetTail(extraInfo.cubeS1RealSize, this->d2Size, extraInfo.s2RealSize); |
| 2287 | - | 2308 | + if (this->dSize != 64) |
| 2288 | - bmm2.template IterateAll<false>(this->mm2Res[extraInfo.taskIdMod2], false, false, true); | 2309 | + { |
| 2289 | - bmm2.End(); | 2310 | + bmm2.template IterateAll<false>(this->mm2Res[extraInfo.taskIdMod2], false, false, true); |
| 2290 | - return; | 2311 | + bmm2.End(); |
| 2312 | + return; | ||
| 2313 | + } else { | ||
| 2314 | + cubeOp.Cube2Process(vCoreOffset, extraInfo.cubeS1RealSize, extraInfo.s2RealSize, | ||
| 2315 | + this->stage1Res[extraInfo.taskIdMod2], this->valueGm[vCoreOffset], | ||
| 2316 | + this->mm2Res[extraInfo.taskIdMod2]); | ||
| 2317 | + return; | ||
| 2318 | + } | ||
| 2291 | } | 2319 | } |
| 2292 | - | 2320 | + |
| 2293 | LocalTensor<INPUT_T> scmATensor; | 2321 | LocalTensor<INPUT_T> scmATensor; |
| 2294 | LocalTensor<INPUT_T> scmBTensor; | 2322 | LocalTensor<INPUT_T> scmBTensor; |
| 2295 | 2323 | ||
Mattention/flash_attention_score/op_kernel/arch35/flash_attention_score_drop_mask_adapter_regbase.h+2-2
| @@ -16,7 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | -#include "kernel_operator.h" | 19 | +#include "kernel_basic_intf.h" |
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | class FlashAttentionScoreDropMaskAdapterRegbase { | 22 | class FlashAttentionScoreDropMaskAdapterRegbase { |
| @@ -98,7 +98,7 @@ __aicore__ inline void FlashAttentionScoreDropMaskAdapterRegbase::Process() | |||
| 98 | 98 | ||
| 99 | int32_t baseUbCalSize = tilingData->dropmaskParamsRegbase.baseUbCalSize; | 99 | int32_t baseUbCalSize = tilingData->dropmaskParamsRegbase.baseUbCalSize; |
| 100 | AscendC::LocalTensor<half> dropMaskSelSrc = dropMaskSelSrcTBuf.template Get<half>(); | 100 | AscendC::LocalTensor<half> dropMaskSelSrc = dropMaskSelSrcTBuf.template Get<half>(); |
| 101 | - AscendC::Duplicate<half>(dropMaskSelSrc, 1.0, baseUbCalSize); | 101 | + AscendC::Duplicate<half>(dropMaskSelSrc, static_cast<half>(1.0), baseUbCalSize); |
| 102 | 102 | ||
| 103 | AscendC::BinaryRepeatParams binaryRepeatParams; | 103 | AscendC::BinaryRepeatParams binaryRepeatParams; |
| 104 | binaryRepeatParams.src0BlkStride = 1; | 104 | binaryRepeatParams.src0BlkStride = 1; |
| @@ -16,10 +16,14 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | -#include "kernel_operator.h" | 19 | +#include "kernel_basic_intf.h" |
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | + | ||
| 22 | 23 | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 23 | using namespace optiling; | 27 | using namespace optiling; |
| 24 | 28 | ||
| 25 | template <typename INPUT_T> class FlashAttentionScoreEmptyTensorRegbase { | 29 | template <typename INPUT_T> class FlashAttentionScoreEmptyTensorRegbase { |
| @@ -40,6 +40,28 @@ | |||
| 40 | GET_TILING_DATA_WITH_STRUCT(FlashAttentionScoreSimplifiedTilingData, tilingDataIn, tiling); \ | 40 | GET_TILING_DATA_WITH_STRUCT(FlashAttentionScoreSimplifiedTilingData, tilingDataIn, tiling); \ |
| 41 | const FlashAttentionScoreSimplifiedTilingData *__restrict tilingData = &tilingDataIn; \ | 41 | const FlashAttentionScoreSimplifiedTilingData *__restrict tilingData = &tilingDataIn; \ |
| 42 | 42 | ||
| 43 | + | ||
| 44 | + | ||
| 45 | + do { \ | ||
| 46 | + __gm__ uint8_t *user = GetUserWorkspace(workspace); \ | ||
| 47 | + REGBASE_COPY_TILING_DATA(tiling); \ | ||
| 48 | + TPipe tPipe; \ | ||
| 49 | + if (tilingData->inputParamsRegbase.needDropMaskOp) { \ | ||
| 50 | + FlashAttentionScoreDropMaskAdapterRegbase dropMaskAdapter; \ | ||
| 51 | + dropMaskAdapter.Init(dropMask, user, tilingData, &tPipe); \ | ||
| 52 | + dropMaskAdapter.Process(); \ | ||
| 53 | + tPipe.Reset(); \ | ||
| 54 | + } \ | ||
| 55 | + using CubeBlockType = typename BaseApi::FABlockCube<__VA_ARGS__>; \ | ||
| 56 | + using VecBlockType = typename BaseApi::FABlockVecTrain<__VA_ARGS__>; \ | ||
| 57 | + templateClass<CubeBlockType, VecBlockType> op; \ | ||
| 58 | + op.InitBaseAPI(query, key, value, pse, dropMask, paddingMask, attenMask, prefix, actualSeqLengths, \ | ||
| 59 | + actualSeqLengthsKv, nullptr, nullptr, nullptr, deqScaleQ, deqScaleK, deqScaleV, nullptr, \ | ||
| 60 | + nullptr,queryRope, keyRope, softmaxMax, softmaxSum, softmaxOut, nullptr, attentionOut, user, \ | ||
| 61 | + tilingData, &tPipe); \ | ||
| 62 | + op.Process(); \ | ||
| 63 | + } while (0) | ||
| 64 | + | ||
| 43 | 65 | ||
| 44 | do { \ | 66 | do { \ |
| 45 | __gm__ uint8_t *user = GetUserWorkspace(workspace); \ | 67 | __gm__ uint8_t *user = GetUserWorkspace(workspace); \ |
| @@ -61,6 +83,7 @@ | |||
| 61 | op.Process(); \ | 83 | op.Process(); \ |
| 62 | } while (0) | 84 | } while (0) |
| 63 | 85 | ||
| 86 | + | ||
| 64 | 87 | ||
| 65 | template<uint8_t implMode, uint8_t layout, uint16_t s1TemplateType, uint16_t s2TemplateType, | 88 | template<uint8_t implMode, uint8_t layout, uint16_t s1TemplateType, uint16_t s2TemplateType, |
| 66 | uint16_t dTemplateType, uint16_t dvTemplateType, uint8_t pseMode, bool hasAtten, bool hasDrop, bool hasRope, | 89 | uint16_t dTemplateType, uint16_t dvTemplateType, uint8_t pseMode, bool hasAtten, bool hasDrop, bool hasRope, |
| @@ -15,8 +15,13 @@ | |||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | + | ||
| 18 | 19 | ||
| 19 | 20 | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 20 | namespace BaseApi { | 25 | namespace BaseApi { |
| 21 | template <typename CubeBlockType, typename VecBlockType> | 26 | template <typename CubeBlockType, typename VecBlockType> |
| 22 | class FlashAttentionScoreKernelTrain | 27 | class FlashAttentionScoreKernelTrain |
| @@ -35,6 +40,8 @@ private: | |||
| 35 | __aicore__ inline int64_t CalcRealTimes(int64_t relativePos, int64_t length); | 40 | __aicore__ inline int64_t CalcRealTimes(int64_t relativePos, int64_t length); |
| 36 | __aicore__ inline int64_t CalcRealCoreIdx(int64_t relativePos, int64_t times, int64_t offsetCoreIdx, | 41 | __aicore__ inline int64_t CalcRealCoreIdx(int64_t relativePos, int64_t times, int64_t offsetCoreIdx, |
| 37 | bool isPartialCalc); | 42 | bool isPartialCalc); |
| 43 | + __aicore__ inline int64_t CalcRealCoreIdxVarlen(int64_t calcLoops, int64_t calcLoopsRemain, | ||
| 44 | + int64_t cycleCoreNums); | ||
| 38 | }; | 45 | }; |
| 39 | 46 | ||
| 40 | template <typename CubeBlockType, typename VecBlockType> | 47 | template <typename CubeBlockType, typename VecBlockType> |
| @@ -95,6 +102,20 @@ __aicore__ inline int64_t FlashAttentionScoreKernelTrain<CubeBlockType, VecBlock | |||
| 95 | return realCoreIdx; | 102 | return realCoreIdx; |
| 96 | } | 103 | } |
| 97 | 104 | ||
| 105 | +template <typename CubeBlockType, typename VecBlockType> | ||
| 106 | +__aicore__ inline int64_t FlashAttentionScoreKernelTrain<CubeBlockType, VecBlockType>::CalcRealCoreIdxVarlen( | ||
| 107 | + int64_t calcLoops, int64_t calcLoopsRemain, int64_t cycleCoreNums) | ||
| 108 | +{ | ||
| 109 | + int64_t realCoreIdx = 0; | ||
| 110 | + if (calcLoopsRemain == 0) { | ||
| 111 | + realCoreIdx = calcLoops * cycleCoreNums + this->aicIdx; | ||
| 112 | + } else { | ||
| 113 | + realCoreIdx = calcLoops * cycleCoreNums + (cycleCoreNums - this->aicIdx - 1); | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + return realCoreIdx; | ||
| 117 | +} | ||
| 118 | + | ||
| 98 | template <typename CubeBlockType, typename VecBlockType> | 119 | template <typename CubeBlockType, typename VecBlockType> |
| 99 | __aicore__ inline int64_t FlashAttentionScoreKernelTrain<CubeBlockType, VecBlockType>::CalcRealTimes( | 120 | __aicore__ inline int64_t FlashAttentionScoreKernelTrain<CubeBlockType, VecBlockType>::CalcRealTimes( |
| 100 | int64_t relativePos, int64_t length) | 121 | int64_t relativePos, int64_t length) |
| @@ -122,6 +143,17 @@ __aicore__ inline int64_t FlashAttentionScoreKernelTrain<CubeBlockType, VecBlock | |||
| 122 | * s1基本块4 -- core3 | 143 | * s1基本块4 -- core3 |
| 123 | * s1基本块5 -- core2 | 144 | * s1基本块5 -- core2 |
| 124 | * s1基本块6 -- core1 | 145 | * s1基本块6 -- core1 |
| 146 | + * | ||
| 147 | + * 三、正倒序循环分核:将每个S1的基本块,先正序依次分发给各个核计算,再倒序依次分发给各个核计算,以此循环 | ||
| 148 | + * s1基本块1 -- core1 | ||
| 149 | + * s1基本块2 -- core2 | ||
| 150 | + * s1基本块3 -- core3 | ||
| 151 | + * s1基本块4 -- core3 | ||
| 152 | + * s1基本块5 -- core2 | ||
| 153 | + * s1基本块6 -- core1 | ||
| 154 | + * s1基本块7 -- core1 | ||
| 155 | + * s1基本块8 -- core2 | ||
| 156 | + * ... | ||
| 125 | */ | 157 | */ |
| 126 | template <typename CubeBlockType, typename VecBlockType> | 158 | template <typename CubeBlockType, typename VecBlockType> |
| 127 | __aicore__ inline void FlashAttentionScoreKernelTrain<CubeBlockType, VecBlockType>::Process() | 159 | __aicore__ inline void FlashAttentionScoreKernelTrain<CubeBlockType, VecBlockType>::Process() |
| @@ -130,8 +162,9 @@ __aicore__ inline void FlashAttentionScoreKernelTrain<CubeBlockType, VecBlockTyp | |||
| 130 | int64_t multiCoreInnerLimit = 0; | 162 | int64_t multiCoreInnerLimit = 0; |
| 131 | 163 | ||
| 132 | // 新分核模式 | 164 | // 新分核模式 |
| 133 | - // 1、S2全量计算的部分,采用顺序分核; | 165 | + // 1、非TND场景 S2全量计算的部分,采用顺序分核; |
| 134 | - // 2、S2部分计算的部分,采用对称分核:将N分成一半,上半部分顺序分核,下半部分与上半部分对称分核; | 166 | + // 2、非TND场景 S2部分计算的部分,采用对称分核:将N分成一半,上半部分顺序分核,下半部分与上半部分对称分核; |
| 167 | + // 3、TND场景 正倒序循环分核 | ||
| 135 | int64_t halfN = 0; | 168 | int64_t halfN = 0; |
| 136 | int64_t partialCalcForwardNum = 0; // 当前核 在顺序部分计算中分配的S1方向上基本块个数; | 169 | int64_t partialCalcForwardNum = 0; // 当前核 在顺序部分计算中分配的S1方向上基本块个数; |
| 137 | int64_t partialCalcReverseNum = 0; // 当前核 在倒序部分计算中分配的S1方向上基本块个数; | 170 | int64_t partialCalcReverseNum = 0; // 当前核 在倒序部分计算中分配的S1方向上基本块个数; |
| @@ -140,26 +173,46 @@ __aicore__ inline void FlashAttentionScoreKernelTrain<CubeBlockType, VecBlockTyp | |||
| 140 | int64_t halfNCoreIdx = 0; // 下半部分第一个S1方向基本块对应的核索引; | 173 | int64_t halfNCoreIdx = 0; // 下半部分第一个S1方向基本块对应的核索引; |
| 141 | int64_t partialCalcLength = this->sharedParams.firstFullLoadS1OuterIdx + 1; // 部分计算在单个S1上的长度; | 174 | int64_t partialCalcLength = this->sharedParams.firstFullLoadS1OuterIdx + 1; // 部分计算在单个S1上的长度; |
| 142 | int64_t relativePosReverse = 0; // 当前核 与第一个S1方向基本块对应的核索引 相差的个数 | 175 | int64_t relativePosReverse = 0; // 当前核 与第一个S1方向基本块对应的核索引 相差的个数 |
| 176 | + int64_t varlenCalcLoops = 0; // TND场景 需要进行计算的循环次数(正序+倒序为一次循环) | ||
| 177 | + int64_t varlenCalcLoopsRemain = 0; | ||
| 178 | + int64_t varlenCalcTimes = 0; // TND场景 需要计算的S1方向上基本块总数 | ||
| 179 | + int64_t varlenCycleCoreNums = this->sharedParams.coreNum * 2; // TND场景 一次循环正序+倒序为两倍核数 | ||
| 180 | + | ||
| 143 | if (this->sharedParams.splitCoreMode == 1) { | 181 | if (this->sharedParams.splitCoreMode == 1) { |
| 144 | - const int64_t totalN = this->constInfo.n2G * this->sharedParams.bSize; | 182 | + if (layout == LayOutTypeEnum::LAYOUT_TND) { |
| 145 | - halfN = CeilDiv(totalN, 2); | 183 | + varlenCalcLoops = this->sharedParams.totalSize / varlenCycleCoreNums; |
| 146 | - int64_t partialCalcForwardLength = halfN * partialCalcLength; | 184 | + varlenCalcLoopsRemain = this->sharedParams.totalSize % varlenCycleCoreNums; |
| 147 | - int64_t partialCalcReverseLength = (totalN - halfN) * partialCalcLength; | 185 | + varlenCalcTimes = varlenCalcLoops * 2; |
| 148 | - int64_t fullCalcForwardLength = 0; | 186 | + if (varlenCalcLoopsRemain >= this->aicIdx + 1) { |
| 149 | - if (this->sharedParams.firstFullLoadS1OuterIdx == -1) { | 187 | + varlenCalcTimes++; |
| 150 | - fullCalcForwardLength = totalN * this->constInfo.s1OuterSize; | 188 | + if (varlenCalcLoopsRemain > this->sharedParams.coreNum && |
| 189 | + (this->aicIdx + 1) > varlenCycleCoreNums - varlenCalcLoopsRemain) { | ||
| 190 | + varlenCalcTimes++; | ||
| 191 | + } | ||
| 192 | + } | ||
| 193 | + multiCoreInnerOffset = 0; | ||
| 194 | + multiCoreInnerLimit = varlenCalcTimes; | ||
| 151 | } else { | 195 | } else { |
| 152 | - fullCalcForwardLength = totalN * (this->constInfo.s1OuterSize - partialCalcLength); | 196 | + const int64_t totalN = this->constInfo.n2G * this->sharedParams.bSize; |
| 197 | + halfN = CeilDiv(totalN, 2); | ||
| 198 | + int64_t partialCalcForwardLength = halfN * partialCalcLength; | ||
| 199 | + int64_t partialCalcReverseLength = (totalN - halfN) * partialCalcLength; | ||
| 200 | + int64_t fullCalcForwardLength = 0; | ||
| 201 | + if (this->sharedParams.firstFullLoadS1OuterIdx == -1) { | ||
| 202 | + fullCalcForwardLength = totalN * this->constInfo.s1OuterSize; | ||
| 203 | + } else { | ||
| 204 | + fullCalcForwardLength = totalN * (this->constInfo.s1OuterSize - partialCalcLength); | ||
| 205 | + } | ||
| 206 | + halfNCoreIdx = (partialCalcForwardLength - 1) % this->sharedParams.coreNum; | ||
| 207 | + relativePosReverse = (halfNCoreIdx - this->aicIdx + this->sharedParams.coreNum) % this->sharedParams.coreNum; | ||
| 208 | + partialCalcForwardNum = CalcRealTimes(this->aicIdx, partialCalcForwardLength); | ||
| 209 | + partialCalcReverseNum = CalcRealTimes(relativePosReverse, partialCalcReverseLength); | ||
| 210 | + fullCalcForwardNum = CalcRealTimes(this->aicIdx, fullCalcForwardLength); | ||
| 211 | + partialCalcNum = partialCalcForwardNum + partialCalcReverseNum; | ||
| 212 | + // 表示当前核需要计算的次数 | ||
| 213 | + multiCoreInnerOffset = 0; | ||
| 214 | + multiCoreInnerLimit = partialCalcForwardNum + partialCalcReverseNum + fullCalcForwardNum; | ||
| 153 | } | 215 | } |
| 154 | - halfNCoreIdx = (partialCalcForwardLength - 1) % this->sharedParams.coreNum; | ||
| 155 | - relativePosReverse = (halfNCoreIdx - this->aicIdx + this->sharedParams.coreNum) % this->sharedParams.coreNum; | ||
| 156 | - partialCalcForwardNum = CalcRealTimes(this->aicIdx, partialCalcForwardLength); | ||
| 157 | - partialCalcReverseNum = CalcRealTimes(relativePosReverse, partialCalcReverseLength); | ||
| 158 | - fullCalcForwardNum = CalcRealTimes(this->aicIdx, fullCalcForwardLength); | ||
| 159 | - partialCalcNum = partialCalcForwardNum + partialCalcReverseNum; | ||
| 160 | - // 表示当前核需要计算的次数 | ||
| 161 | - multiCoreInnerOffset = 0; | ||
| 162 | - multiCoreInnerLimit = partialCalcForwardNum + partialCalcReverseNum + fullCalcForwardNum; | ||
| 163 | } else { | 216 | } else { |
| 164 | // 表示核内切分起点 | 217 | // 表示核内切分起点 |
| 165 | multiCoreInnerOffset = this->sharedParams.multiCoreInnerOffset; | 218 | multiCoreInnerOffset = this->sharedParams.multiCoreInnerOffset; |
| @@ -169,7 +222,11 @@ __aicore__ inline void FlashAttentionScoreKernelTrain<CubeBlockType, VecBlockTyp | |||
| 169 | // 初始化AxisIdx | 222 | // 初始化AxisIdx |
| 170 | RunParamStr<isInfer> runParam; | 223 | RunParamStr<isInfer> runParam; |
| 171 | if constexpr (layout == LayOutTypeEnum::LAYOUT_TND) { | 224 | if constexpr (layout == LayOutTypeEnum::LAYOUT_TND) { |
| 172 | - CalS1OuterSize(multiCoreInnerOffset, runParam); | 225 | + if (this->sharedParams.splitCoreMode == 1) { |
| 226 | + CalS1OuterSize(this->aicIdx, runParam); | ||
| 227 | + } else { | ||
| 228 | + CalS1OuterSize(multiCoreInnerOffset, runParam); | ||
| 229 | + } | ||
| 173 | } | 230 | } |
| 174 | RunInfo<isInfer> runInfo[4]; | 231 | RunInfo<isInfer> runInfo[4]; |
| 175 | int64_t taskId = 0; | 232 | int64_t taskId = 0; |
| @@ -192,14 +249,20 @@ __aicore__ inline void FlashAttentionScoreKernelTrain<CubeBlockType, VecBlockTyp | |||
| 192 | } else { | 249 | } else { |
| 193 | // 非最后三次伪循环,需要将当前核处理的次数转化为S1方向上基本块的索引值 | 250 | // 非最后三次伪循环,需要将当前核处理的次数转化为S1方向上基本块的索引值 |
| 194 | if (this->sharedParams.splitCoreMode == 1) { | 251 | if (this->sharedParams.splitCoreMode == 1) { |
| 195 | - if (multiCoreInnerIdx >= 0 && multiCoreInnerIdx < partialCalcForwardNum) { | 252 | + if (layout == LayOutTypeEnum::LAYOUT_TND) { |
| 196 | - realCoreInnerIdx = CalcRealCoreIdx(this->aicIdx, multiCoreInnerIdx, 0, true); | 253 | + int64_t curCalcLoops = multiCoreInnerIdx >> 1; |
| 197 | - } else if (multiCoreInnerIdx >= partialCalcForwardNum && multiCoreInnerIdx < partialCalcNum) { | 254 | + int64_t curCalcLoopsRemain = multiCoreInnerIdx & 1; |
| 198 | - realCoreInnerIdx = CalcRealCoreIdx(relativePosReverse, multiCoreInnerIdx - partialCalcForwardNum, | 255 | + realCoreInnerIdx = CalcRealCoreIdxVarlen(curCalcLoops, curCalcLoopsRemain, varlenCycleCoreNums); |
| 199 | - halfN * this->constInfo.s1OuterSize, true); | ||
| 200 | } else { | 256 | } else { |
| 201 | - realCoreInnerIdx = CalcRealCoreIdx(this->aicIdx, multiCoreInnerIdx - partialCalcNum, | 257 | + if (multiCoreInnerIdx >= 0 && multiCoreInnerIdx < partialCalcForwardNum) { |
| 202 | - partialCalcLength, false); | 258 | + realCoreInnerIdx = CalcRealCoreIdx(this->aicIdx, multiCoreInnerIdx, 0, true); |
| 259 | + } else if (multiCoreInnerIdx >= partialCalcForwardNum && multiCoreInnerIdx < partialCalcNum) { | ||
| 260 | + realCoreInnerIdx = CalcRealCoreIdx(relativePosReverse, multiCoreInnerIdx - partialCalcForwardNum, | ||
| 261 | + halfN * this->constInfo.s1OuterSize, true); | ||
| 262 | + } else { | ||
| 263 | + realCoreInnerIdx = CalcRealCoreIdx(this->aicIdx, multiCoreInnerIdx - partialCalcNum, | ||
| 264 | + partialCalcLength, false); | ||
| 265 | + } | ||
| 203 | } | 266 | } |
| 204 | } else { | 267 | } else { |
| 205 | realCoreInnerIdx = multiCoreInnerIdx; | 268 | realCoreInnerIdx = multiCoreInnerIdx; |
| @@ -356,6 +419,10 @@ __aicore__ inline void FlashAttentionScoreKernelTrain<CubeBlockType, VecBlockTyp | |||
| 356 | if (this->sharedParams.sparseType == static_cast<uint8_t>(SparseModeEnum::CAUSAL)) { | 419 | if (this->sharedParams.sparseType == static_cast<uint8_t>(SparseModeEnum::CAUSAL)) { |
| 357 | runParam.s2LineStartIdx = 0; | 420 | runParam.s2LineStartIdx = 0; |
| 358 | runParam.s2LineEndIdx = Min((runParam.s1oIdx + 1) * this->s1BaseSize, actualS2Len); | 421 | runParam.s2LineEndIdx = Min((runParam.s1oIdx + 1) * this->s1BaseSize, actualS2Len); |
| 422 | + } else if (this->sharedParams.sparseType == static_cast<uint8_t>(SparseModeEnum::RIGHT_DOWN_CAUSAL)) { | ||
| 423 | + runParam.s2LineStartIdx = 0; | ||
| 424 | + runParam.s2LineEndIdx = | ||
| 425 | + Min((runParam.s1oIdx + 1) * this->s1BaseSize + actualS2Len - actualS1Len, actualS2Len); | ||
| 359 | } else if (this->sharedParams.sparseType == | 426 | } else if (this->sharedParams.sparseType == |
| 360 | static_cast<uint8_t>(SparseModeEnum::BAND)) { | 427 | static_cast<uint8_t>(SparseModeEnum::BAND)) { |
| 361 | runParam.s2LineStartIdx = Max( | 428 | runParam.s2LineStartIdx = Max( |
| @@ -13,11 +13,11 @@ | |||
| 13 | * \brief | 13 | * \brief |
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | -#include "kernel_operator.h" | 16 | +#include "kernel_basic_intf.h" |
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | -#ifdef NOT_DYNAMIC_COMPILE | 20 | +#if __has_include("../../common/op_kernel/arch35/flash_attention_score_tiling_regbase.h") |
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | 23 | ||
| @@ -0,0 +1,35 @@ | |||
| 1 | +# FlashAttentionScore算子测试框架 | ||
| 2 | + | ||
| 3 | +## 文件结构 | ||
| 4 | + | ||
| 5 | +pytest/ | ||
| 6 | +- test_case.py # 测试用例集 | ||
| 7 | +- test_flash_attn.py # 执行主程序 | ||
| 8 | +- test_utils.py # 工具方法 | ||
| 9 | +- cpu_impl.py # cpu实现 | ||
| 10 | +- npu_impl.py # npu实现 | ||
| 11 | + | ||
| 12 | +## 功能说明 | ||
| 13 | + | ||
| 14 | +基于pytest测试框架,实现FA算子的功能验证: | ||
| 15 | +- **CPU侧**:复现算子功能用以生成golden数据 | ||
| 16 | +- **NPU侧**:通过torch_npu进行算子直调获取实际数据 | ||
| 17 | +- **精度对比**:进行CPU与NPU结果的精度对比验证算子功能 | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +## 环境配置 | ||
| 21 | + | ||
| 22 | +### 前置要求 | ||
| 23 | + | ||
| 24 | +1. 确认torch_npu为最新版本 | ||
| 25 | +2. source CANN包环境变量 | ||
| 26 | + | ||
| 27 | +### Custom包调用 | ||
| 28 | + | ||
| 29 | +支持custom包调用 | ||
| 30 | + | ||
| 31 | +## 使用方法 | ||
| 32 | + | ||
| 33 | +在pytest文件夹路径下执行: | ||
| 34 | + | ||
| 35 | +pytest -s | ||
| @@ -0,0 +1,235 @@ | |||
| 1 | +#!/usr/bin/python | ||
| 2 | +# -*- coding: utf-8 -*- | ||
| 3 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 5 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 8 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 10 | +# ====================================================================================================================== | ||
| 11 | + | ||
| 12 | +import torch | ||
| 13 | +import torch_npu | ||
| 14 | +import math | ||
| 15 | +import numpy as np | ||
| 16 | +import random | ||
| 17 | +from test_utils import * | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +def tsoftmax(x): | ||
| 21 | + x_max = torch.max(x, dim=-1, keepdims=True)[0] | ||
| 22 | + x_sub = x.sub(x_max) | ||
| 23 | + y = torch.exp(x_sub) | ||
| 24 | + x_sum = y.sum(dim=-1, keepdims=True) | ||
| 25 | + res = y.div(x_sum) | ||
| 26 | + return res, x_max, x_sum | ||
| 27 | + | ||
| 28 | + | ||
| 29 | +def skip_invalid_row(b, n, sq, softmax_res, x_max, x_sum): | ||
| 30 | + for i in range(b): | ||
| 31 | + for j in range(n): | ||
| 32 | + for k in range(sq): | ||
| 33 | + if x_max[i, j, k, :] == -40000.: | ||
| 34 | + softmax_res[i, j, k, :] = 0 | ||
| 35 | + x_max[i, j, k, :] = torch.finfo(torch.float).min | ||
| 36 | + x_sum[i, j, k, :] = torch.finfo(torch.float).max | ||
| 37 | + return softmax_res, x_max, x_sum | ||
| 38 | + | ||
| 39 | + | ||
| 40 | +def forward(q, k, v, drop_mask, atten_mask, pse_type, pse, scale, keep_prob, skip_invalid_row=False): | ||
| 41 | + q = q.float() | ||
| 42 | + k = k.float() | ||
| 43 | + v = v.float() | ||
| 44 | + | ||
| 45 | + qk = torch.matmul(q, k.permute(0, 1, 3, 2)) | ||
| 46 | + if pse is None: | ||
| 47 | + qk = qk.mul(scale) | ||
| 48 | + else: | ||
| 49 | + if pse_type == 1: | ||
| 50 | + qk = qk.add(pse).mul(scale) | ||
| 51 | + else: | ||
| 52 | + qk = qk.mul(scale).add(pse) | ||
| 53 | + if atten_mask is not None: | ||
| 54 | + qk = qk.masked_fill_(atten_mask.cpu().bool(), value=torch.tensor(-40000)) | ||
| 55 | + softmax_res, x_max, x_sum = tsoftmax(qk) | ||
| 56 | + | ||
| 57 | + if skip_invalid_row: | ||
| 58 | + b, n, sq, _ = softmax_res.shape | ||
| 59 | + softmax_res, x_max, x_sum = skip_invalid_row(b, n, sq, softmax_res, x_max, x_sum) | ||
| 60 | + | ||
| 61 | + if drop_mask is not None: | ||
| 62 | + drop_res = softmax_res * drop_mask * (1.0 / keep_prob) | ||
| 63 | + else: | ||
| 64 | + drop_res = softmax_res | ||
| 65 | + | ||
| 66 | + out = torch.matmul(drop_res, v) | ||
| 67 | + | ||
| 68 | + x_max = x_max.broadcast_to(-1, -1, -1, 8) | ||
| 69 | + x_sum = x_sum.broadcast_to(-1, -1, -1, 8) | ||
| 70 | + return out, x_max, x_sum | ||
| 71 | + | ||
| 72 | + | ||
| 73 | +def get_cu_seqlens(seqlens_list): | ||
| 74 | + cu = torch.zeros(len(seqlens_list) + 1, dtype=torch.int64) | ||
| 75 | + for i in range(1, len(seqlens_list) + 1): | ||
| 76 | + cu[i] = cu[i - 1] + seqlens_list[i - 1] | ||
| 77 | + return cu | ||
| 78 | + | ||
| 79 | + | ||
| 80 | +def broadcastKV(n1, n2, kv_tensor, dtype): | ||
| 81 | + factor = n1 // n2 | ||
| 82 | + kv_shape = kv_tensor.shape | ||
| 83 | + b = kv_shape[0] | ||
| 84 | + s = kv_shape[2] | ||
| 85 | + d = kv_shape[3] | ||
| 86 | + kv_res = torch.zeros(b, n1, s, d).to(dtype) | ||
| 87 | + for i in range(n1): | ||
| 88 | + j = i // factor | ||
| 89 | + kv_res[:, i:i + 1, :, :] = kv_tensor[:, j:j + 1, :, :] | ||
| 90 | + return kv_res | ||
| 91 | + | ||
| 92 | + | ||
| 93 | +def tforward_normal(q, k, v, pse, **kwargs): | ||
| 94 | + b = kwargs.get("B") | ||
| 95 | + n1 = kwargs.get("N1") | ||
| 96 | + n2 = kwargs.get("N2", n1) | ||
| 97 | + s1 = kwargs.get("Sq") | ||
| 98 | + s2 = kwargs.get("Skv", s1) | ||
| 99 | + d = kwargs.get("D") | ||
| 100 | + sparse_mode = kwargs.get("sparse_mode", None) | ||
| 101 | + pre_tokens = kwargs.get("pre_tokens", 2147483647) | ||
| 102 | + next_tokens = kwargs.get("next_tokens", 2147483647) | ||
| 103 | + prefix = kwargs.get("prefix", []) | ||
| 104 | + seed = kwargs.get("seed", 0) | ||
| 105 | + offset = kwargs.get("offset", 0) | ||
| 106 | + | ||
| 107 | + scale = kwargs.get("scale", 1 / (d ** 0.5)) | ||
| 108 | + pse_type = kwargs.get("pse_type", 1) | ||
| 109 | + keep_prob = kwargs.get("keep_prob", 1) | ||
| 110 | + | ||
| 111 | + if abs(1 - keep_prob) < 2e-14: | ||
| 112 | + drop_mask = None | ||
| 113 | + else: | ||
| 114 | + drop_mask = gen_dropmask(b, n1, s1, s2, keep_prob, seed, offset) | ||
| 115 | + | ||
| 116 | + atten_mask = generate_cpu_mask(b, s1, s2, sparse_mode, pre_tokens, next_tokens, prefix) | ||
| 117 | + skip_invalid_row = False | ||
| 118 | + if atten_mask is not None: | ||
| 119 | + if sparse_mode == 0: | ||
| 120 | + skip_invalid_row = next_tokens < 0 or pre_tokens + s2 < s1 | ||
| 121 | + elif sparse_mode == 3: | ||
| 122 | + skip_invalid_row = s1 > s2 | ||
| 123 | + elif sparse_mode == 4: | ||
| 124 | + skip_invalid_row = pre_tokens < 0 or next_tokens + s2 < s1 | ||
| 125 | + elif sparse_mode in [5, 6]: | ||
| 126 | + skip_invalid_row = True if 0 in prefix else False | ||
| 127 | + | ||
| 128 | + if n1 != n2: | ||
| 129 | + k = broadcastKV(n1, n2, k, k.dtype) | ||
| 130 | + v = broadcastKV(n1, n2, v, v.dtype) | ||
| 131 | + out, x_max, x_sum = forward(q, k, v, drop_mask, atten_mask, pse_type, pse, scale, keep_prob, skip_invalid_row) | ||
| 132 | + return out, x_max, x_sum | ||
| 133 | + | ||
| 134 | + | ||
| 135 | +def tforward_tnd(q, k, v, pse, **kwargs): | ||
| 136 | + actual_seq_qlen = list(kwargs.get("actual_seq_qlen")) | ||
| 137 | + actual_seq_kvlen = list(kwargs.get("actual_seq_kvlen", actual_seq_qlen)) | ||
| 138 | + assert isinstance(actual_seq_qlen, list) | ||
| 139 | + assert isinstance(actual_seq_kvlen, list) | ||
| 140 | + seqlen_q_list = get_seqlen_list(actual_seq_qlen).numpy() | ||
| 141 | + seqlen_k_list = get_seqlen_list(actual_seq_kvlen).numpy() | ||
| 142 | + actual_seq_qlen.insert(0, 0) | ||
| 143 | + actual_seq_kvlen.insert(0, 0) | ||
| 144 | + input_layout = kwargs.get("input_layout") | ||
| 145 | + sparse_mode = kwargs.get("sparse_mode", None) | ||
| 146 | + pre_tokens = kwargs.get("pre_tokens", 2147483647) | ||
| 147 | + next_tokens = kwargs.get("next_tokens", 2147483647) | ||
| 148 | + prefix = kwargs.get("prefix", []) | ||
| 149 | + seed = kwargs.get("seed", 0) | ||
| 150 | + offset = kwargs.get("offset", 0) | ||
| 151 | + max_seqlen_q = seqlen_q_list.max() | ||
| 152 | + max_seqlen_k = seqlen_k_list.max() | ||
| 153 | + qk_size = seqlen_q_list * [math.ceil(i / 16) * 16 for i in seqlen_k_list] | ||
| 154 | + qk_pointer = get_cu_seqlens(qk_size).to(torch.int64) | ||
| 155 | + | ||
| 156 | + b = len(seqlen_q_list) | ||
| 157 | + n1 = kwargs.get("N1") | ||
| 158 | + n2 = kwargs.get("N2", n1) | ||
| 159 | + d = kwargs.get("D") | ||
| 160 | + d_v = kwargs.get("DV", d) | ||
| 161 | + s1 = max(actual_seq_qlen) | ||
| 162 | + s2 = max(actual_seq_kvlen) | ||
| 163 | + | ||
| 164 | + scale = kwargs.get("scale", 1 / (d ** 0.5)) | ||
| 165 | + pse_type = kwargs.get("pse_type", 1) | ||
| 166 | + keep_prob = kwargs.get("keep_prob", 1) | ||
| 167 | + | ||
| 168 | + pse_s1 = max(1024, max_seqlen_q) | ||
| 169 | + band_index = 0 | ||
| 170 | + if sparse_mode == 7: | ||
| 171 | + for index in range(b - 1, -1, -1): | ||
| 172 | + if seqlen_q_list[index] != 0: | ||
| 173 | + band_index = index | ||
| 174 | + break | ||
| 175 | + elif sparse_mode == 8: | ||
| 176 | + for index in range(b): | ||
| 177 | + if seqlen_k_list[index] != 0: | ||
| 178 | + band_index = index | ||
| 179 | + break | ||
| 180 | + | ||
| 181 | + if abs(1 - keep_prob) < 2e-14: | ||
| 182 | + drop_mask = None | ||
| 183 | + else: | ||
| 184 | + drop_mask = gen_dropmask_tnd(qk_pointer[-1].item() * n1, keep_prob, seed, offset) | ||
| 185 | + | ||
| 186 | + out_golden = torch.zeros([1, n1, s1, d_v], dtype=q.dtype) | ||
| 187 | + x_max = torch.empty(0) | ||
| 188 | + x_sum = torch.empty(0) | ||
| 189 | + for i in range(b): | ||
| 190 | + if seqlen_q_list[i] != 0 and seqlen_q_list[i] != 0: | ||
| 191 | + qi = q[:, :, actual_seq_qlen[i]:actual_seq_qlen[i + 1]] | ||
| 192 | + ki = k[:, :, actual_seq_kvlen[i]:actual_seq_kvlen[i + 1]] | ||
| 193 | + vi = v[:, :, actual_seq_kvlen[i]:actual_seq_kvlen[i + 1]] | ||
| 194 | + | ||
| 195 | + if n1 != n2: | ||
| 196 | + ki = broadcastKV(n1, n2, ki, ki.dtype) | ||
| 197 | + vi = broadcastKV(n1, n2, vi, vi.dtype) | ||
| 198 | + | ||
| 199 | + if pse is None: | ||
| 200 | + psei = None | ||
| 201 | + else: | ||
| 202 | + pse_layout = kwargs.get("pse_layout").lower() | ||
| 203 | + assert pse_layout in ["bn", "n", "bnhs", "1nhs"] | ||
| 204 | + if pse_layout == "bn": | ||
| 205 | + psei = pse[i:i + 1, :, -seqlen_q_list[i]:, -seqlen_k_list[i]:] | ||
| 206 | + elif pse_layout == "n": | ||
| 207 | + psei = pse[:, :, -seqlen_q_list[i]:, -seqlen_k_list[i]:] | ||
| 208 | + elif pse_layout == "bnhs": | ||
| 209 | + psei = pse[i:i + 1, :, pse_s1 - seqlen_q_list[i]:pse_s1, max_seqlen_k - seqlen_k_list[i]:max_seqlen_k] | ||
| 210 | + elif pse_layout == "1nhs": | ||
| 211 | + psei = pse[:, :, pse_s1 - seqlen_q_list[i]:pse_s1, max_seqlen_k - seqlen_k_list[i]:max_seqlen_k] | ||
| 212 | + | ||
| 213 | + if drop_mask is None: | ||
| 214 | + drop_maski = None | ||
| 215 | + else: | ||
| 216 | + drop_maski = drop_mask[(qk_pointer[i] * n1):(qk_pointer[i + 1] * n1)].reshape(n1, seqlen_q_list[i], math.ceil(seqlen_k_list[i] / 16) * 16)[:, :, :seqlen_k_list[i]] | ||
| 217 | + | ||
| 218 | + if sparse_mode is None: | ||
| 219 | + atten_maski = None | ||
| 220 | + else: | ||
| 221 | + atten_maski = generate_cpu_mask(1, seqlen_q_list[i], seqlen_k_list[i], sparse_mode, pre_tokens, next_tokens, prefix, i, band_index) | ||
| 222 | + | ||
| 223 | + outi, x_maxi, x_sumi = forward(qi, ki, vi, drop_maski, atten_maski, pse_type, psei, scale, keep_prob) | ||
| 224 | + out_golden[:, :, actual_seq_qlen[i]:actual_seq_qlen[i + 1]] = outi | ||
| 225 | + x_max = torch.cat((x_max, x_maxi.contiguous().view(-1))) | ||
| 226 | + x_sum = torch.cat((x_sum, x_sumi.contiguous().view(-1))) | ||
| 227 | + return out_golden, x_max, x_sum | ||
| 228 | + | ||
| 229 | + | ||
| 230 | +def tforward(q, k, v, pse, **kwargs): | ||
| 231 | + input_layout=kwargs.get("input_layout") | ||
| 232 | + if input_layout == "TND": | ||
| 233 | + return tforward_tnd(q, k, v, pse, **kwargs) | ||
| 234 | + else: | ||
| 235 | + return tforward_normal(q, k, v, pse, **kwargs) | ||
| @@ -0,0 +1,88 @@ | |||
| 1 | +#!/usr/bin/python | ||
| 2 | +# -*- coding: utf-8 -*- | ||
| 3 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 5 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 8 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 10 | +# ====================================================================================================================== | ||
| 11 | + | ||
| 12 | +import torch | ||
| 13 | +import torch_npu | ||
| 14 | +import math | ||
| 15 | +import numpy as np | ||
| 16 | +import random | ||
| 17 | +from einops import rearrange | ||
| 18 | +from test_utils import trans_bnsd_to_layout | ||
| 19 | + | ||
| 20 | +device_id = 0 | ||
| 21 | +device = torch.device(f"npu:{device_id}") | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +def fa_npu(q, k, v, q_rope, k_rope, atten_mask, pse, **kwargs): | ||
| 25 | + input_layout = kwargs.get("input_layout", "BNSD") | ||
| 26 | + n1 = kwargs.get("N1") | ||
| 27 | + d = kwargs.get("D") | ||
| 28 | + d_rope = kwargs.get("DRope", 0) | ||
| 29 | + sparse_mode = kwargs.get("sparse_mode", 0) | ||
| 30 | + prefix = kwargs.get("prefix", None) | ||
| 31 | + pre_tokens = kwargs.get("pre_tokens", 2147483647) | ||
| 32 | + next_tokens = kwargs.get("next_tokens", 2147483647) | ||
| 33 | + actual_seq_qlen = kwargs.get("actual_seq_qlen", None) | ||
| 34 | + actual_seq_kvlen = kwargs.get("actual_seq_kvlen", actual_seq_qlen) | ||
| 35 | + scale = kwargs.get("scale", 1 / (d ** 0.5)) | ||
| 36 | + pse_type = kwargs.get("pse_type", 1) | ||
| 37 | + keep_prob = kwargs.get("keep_prob", 1) | ||
| 38 | + q_start_idx = kwargs.get("q_start_idx", None) | ||
| 39 | + kv_start_idx = kwargs.get("kv_start_idx", None) | ||
| 40 | + seed = kwargs.get("seed", 0) | ||
| 41 | + | ||
| 42 | + q1 = trans_bnsd_to_layout(q, input_layout).contiguous().to(device) | ||
| 43 | + k1 = trans_bnsd_to_layout(k, input_layout).contiguous().to(device) | ||
| 44 | + v1 = trans_bnsd_to_layout(v, input_layout).contiguous().to(device) | ||
| 45 | + | ||
| 46 | + if d_rope != 0: | ||
| 47 | + query_rope = trans_bnsd_to_layout(q_rope, input_layout).contiguous().to(device) | ||
| 48 | + key_rope = trans_bnsd_to_layout(k_rope, input_layout).contiguous().to(device) | ||
| 49 | + else: | ||
| 50 | + query_rope = None | ||
| 51 | + key_rope = None | ||
| 52 | + if pse is not None: | ||
| 53 | + pse1 = pse.to(device) | ||
| 54 | + else: | ||
| 55 | + pse1 = None | ||
| 56 | + | ||
| 57 | + if atten_mask is not None: | ||
| 58 | + atten_mask1 = atten_mask.to(device) | ||
| 59 | + else: | ||
| 60 | + atten_mask1 = None | ||
| 61 | + | ||
| 62 | + torch.npu.manual_seed(seed) | ||
| 63 | + | ||
| 64 | + out_all = torch_npu.npu_fusion_attention_v2( | ||
| 65 | + q1, k1, v1, n1, input_layout, | ||
| 66 | + # optional parameters | ||
| 67 | + pse=pse1, | ||
| 68 | + atten_mask=atten_mask1, | ||
| 69 | + actual_seq_qlen=actual_seq_qlen, | ||
| 70 | + actual_seq_kvlen=actual_seq_kvlen, | ||
| 71 | + query_rope=query_rope, | ||
| 72 | + key_rope=key_rope, | ||
| 73 | + scale=scale, | ||
| 74 | + keep_prob=keep_prob, | ||
| 75 | + pre_tokens=pre_tokens, | ||
| 76 | + next_tokens=next_tokens, | ||
| 77 | + prefix=prefix, | ||
| 78 | + pse_type=pse_type, | ||
| 79 | + q_start_idx=tuple([q_start_idx]) if q_start_idx is not None else None, | ||
| 80 | + kv_start_idx=tuple([kv_start_idx]) if kv_start_idx is not None else None, | ||
| 81 | + sparse_mode=sparse_mode) | ||
| 82 | + torch.npu.synchronize() | ||
| 83 | + | ||
| 84 | + npu_out = out_all[0].cpu() | ||
| 85 | + npu_max = out_all[1].cpu() | ||
| 86 | + npu_sum = out_all[2].cpu() | ||
| 87 | + | ||
| 88 | + return npu_out, npu_max, npu_sum | ||
| @@ -0,0 +1,199 @@ | |||
| 1 | +#!/usr/bin/python | ||
| 2 | +# -*- coding: utf-8 -*- | ||
| 3 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 5 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 8 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 10 | +# ====================================================================================================================== | ||
| 11 | + | ||
| 12 | +import torch | ||
| 13 | + | ||
| 14 | +####### 参数说明 ######## | ||
| 15 | +# B:必选; batch_size,TND格式下可选 | ||
| 16 | +# N1:必选; head_num | ||
| 17 | +# N2:可选; kv's head_num,支持GQA/MHA/MQA | ||
| 18 | +# Sq:必选; query's sequence length;TND格式下可选 | ||
| 19 | +# Skv:可选; key&value's sequence length | ||
| 20 | +# D:必选; 表示query&key&value的head_dim | ||
| 21 | +# DV:可选; value's head_dim;设置该参数,value的head_dim以DV为准 | ||
| 22 | +# DRope:可选; query_rope&key_rope's head_dim,支持D=128,DRope=64 | ||
| 23 | +# input_layout:必选; 输入tensor的格式, [BNSD, BSH, BSND, SBH, TND] | ||
| 24 | +# dtype:必选; 数据类型, [torch.float16, torch.bfloat16, torch.float] | ||
| 25 | +# scale:可选; 注意力得分缩放系数 | ||
| 26 | +# actual_seq_qlen:可选; TND下必选;query实际的序列长度 | ||
| 27 | +# actual_seq_kvlen:可选; TND下必选;key&value实际的序列长度 | ||
| 28 | + | ||
| 29 | +# keep_prob:可选; dropout的保留概率:keep_prob = 1 - dropout_p;dropout的cpu实现方式基于Ascend 950PR/Ascend 950DT | ||
| 30 | +# seed:可选; 随机种子,用于随机数生成 | ||
| 31 | + | ||
| 32 | +# sparse_mode:可选; sparse模式, [0, 1, 2, 3, 4, 5, 6, 7, 8] | ||
| 33 | +# - sparse_mode=3:等价于gpu的"causal=true" | ||
| 34 | +# pre_tokens:可选; 配合sparse_mode使用,详细资料可参考算子文档 | ||
| 35 | +# next_tokens:可选; 配合sparse_mode使用,详细资料可参考算子文档 | ||
| 36 | +# prefix:可选; list类型,sparse_mode=5/6时需要设置,满足len(prefix)==batch_size | ||
| 37 | + | ||
| 38 | +# pse_type:可选; 位置编码, [0, 1, 2, 3] | ||
| 39 | +# - 0/1: pse_layout取值在[bnss, 1nss, bn1s, bnhs, 1nhs],TND格式下取值在[bnhs, 1nhs] | ||
| 40 | +# - 2: pse_layout取值在[bn, n],等价于gpu的"alibi=true" | ||
| 41 | +# - 3: pse_layout取值在[bn, n] | ||
| 42 | +# pse_layout:可选; 用于生成golden,取值范围[bnss, 1nss, bn1s, bnhs, 1nhs, bn, n],约束如上 | ||
| 43 | +# q_start_idx:可选; query的位置起始偏移 | ||
| 44 | +# kv_start_idx:可选; key&value的位置起始偏移 | ||
| 45 | + | ||
| 46 | +TestCases = { | ||
| 47 | + "GQA_01": { | ||
| 48 | + "B": 4, | ||
| 49 | + "N1": 16, | ||
| 50 | + "N2": 8, | ||
| 51 | + "Sq": 256, | ||
| 52 | + "Skv": 256, | ||
| 53 | + "D": 128, | ||
| 54 | + "input_layout": "BSND", | ||
| 55 | + "dtype": torch.bfloat16, | ||
| 56 | + "sparse_mode": 3, # causal=true | ||
| 57 | + }, | ||
| 58 | + "MLA_02": { | ||
| 59 | + "N1": 16, | ||
| 60 | + "N2": 8, | ||
| 61 | + "actual_seq_qlen": [256], | ||
| 62 | + "D": 128, | ||
| 63 | + "DRope": 64, # rope head-dim | ||
| 64 | + "input_layout": "TND", | ||
| 65 | + "dtype": torch.bfloat16, | ||
| 66 | + "sparse_mode": 3, | ||
| 67 | + }, | ||
| 68 | + "MLA_03": { | ||
| 69 | + "B": 4, | ||
| 70 | + "N1": 16, | ||
| 71 | + "N2": 8, | ||
| 72 | + "Sq": 256, | ||
| 73 | + "D": 192, # query&key's head-dim | ||
| 74 | + "DV": 128, # value's head-dim | ||
| 75 | + "input_layout": "BSH", | ||
| 76 | + "dtype": torch.float16, | ||
| 77 | + "sparse_mode": 3, | ||
| 78 | + }, | ||
| 79 | + "ALIBI_04": { | ||
| 80 | + "B": 4, | ||
| 81 | + "N1": 8, | ||
| 82 | + "Sq": 256, | ||
| 83 | + "D": 256, # query&key's head-dim | ||
| 84 | + "input_layout": "BNSD", | ||
| 85 | + "dtype": torch.bfloat16, | ||
| 86 | + "sparse_mode": 3, | ||
| 87 | + "pse_type": 2, | ||
| 88 | + "pse_layout": "bn" # for generate golden data | ||
| 89 | + }, | ||
| 90 | + "ALIBI_05": { | ||
| 91 | + "B": 4, | ||
| 92 | + "N1": 8, | ||
| 93 | + "Sq": 256, | ||
| 94 | + "D": 128, # query&key's head-dim | ||
| 95 | + "input_layout": "BSND", | ||
| 96 | + "dtype": torch.float16, | ||
| 97 | + "sparse_mode": 3, | ||
| 98 | + "pse_type": 3, # special alibi | ||
| 99 | + "pse_layout": "n" # for generate golden data | ||
| 100 | + }, | ||
| 101 | + "SPARSE_06": { | ||
| 102 | + "B": 4, | ||
| 103 | + "N1": 8, | ||
| 104 | + "Sq": 256, | ||
| 105 | + "D": 768, # query&key's head-dim | ||
| 106 | + "input_layout": "SBH", | ||
| 107 | + "dtype": torch.bfloat16, | ||
| 108 | + "sparse_mode": 0, | ||
| 109 | + "pre_tokens": 128, | ||
| 110 | + "next_tokens": 128, | ||
| 111 | + "pse_type": 3, # special alibi | ||
| 112 | + "pse_layout": "n" # for generate golden data | ||
| 113 | + }, | ||
| 114 | + "SPARSE_07": { | ||
| 115 | + "B": 4, | ||
| 116 | + "N1": 8, | ||
| 117 | + "Sq": 256, | ||
| 118 | + "D": 128, # query&key's head-dim | ||
| 119 | + "input_layout": "BSND", | ||
| 120 | + "dtype": torch.float32, | ||
| 121 | + "sparse_mode": 4, # if sparse_mode=4, window_size=(pre_tokens, next_tokens) | ||
| 122 | + "pre_tokens": 128, | ||
| 123 | + "next_tokens": 128, | ||
| 124 | + "pse_type": 3, # special alibi | ||
| 125 | + "pse_layout": "n" # for generate golden data | ||
| 126 | + }, | ||
| 127 | + "SPARSE_08": { | ||
| 128 | + "B": 4, | ||
| 129 | + "N1": 8, | ||
| 130 | + "Sq": 256, | ||
| 131 | + "D": 128, # query&key's head-dim | ||
| 132 | + "input_layout": "BSND", | ||
| 133 | + "dtype": torch.bfloat16, | ||
| 134 | + "sparse_mode": 5, | ||
| 135 | + "prefix": [100, 128, 130, 150], | ||
| 136 | + "pse_type": 3, # special alibi | ||
| 137 | + "pse_layout": "n" # for generate golden data | ||
| 138 | + }, | ||
| 139 | + "DROPOUT_09": { | ||
| 140 | + "B": 4, | ||
| 141 | + "N1": 8, | ||
| 142 | + "Sq": 256, | ||
| 143 | + "Skv": 512, | ||
| 144 | + "D": 128, # query&key's head-dim | ||
| 145 | + "input_layout": "BSND", | ||
| 146 | + "dtype": torch.float32, | ||
| 147 | + "sparse_mode": 5, | ||
| 148 | + "prefix": [100, 128, 401, 300], | ||
| 149 | + "pse_type": 0, # special alibi | ||
| 150 | + "pse_layout": "bnss", # for generate golden data | ||
| 151 | + "keep_prob": 0.9, # keep_prob = 1 - dropout_p | ||
| 152 | + }, | ||
| 153 | + "TND_01": { | ||
| 154 | + "N1": 8, | ||
| 155 | + "N2": 4, | ||
| 156 | + "actual_seq_qlen": [128, 256, 512], | ||
| 157 | + "D": 128, # query&key's head-dim | ||
| 158 | + "DRope": 64, # rope head-dim | ||
| 159 | + "input_layout": "TND", | ||
| 160 | + "dtype": torch.bfloat16, | ||
| 161 | + "sparse_mode": 3, | ||
| 162 | + }, | ||
| 163 | + "TND_02": { | ||
| 164 | + "N1": 8, | ||
| 165 | + "actual_seq_qlen": [2048], | ||
| 166 | + "D": 192, # query&key's head-dim | ||
| 167 | + "input_layout": "TND", | ||
| 168 | + "dtype": torch.bfloat16, | ||
| 169 | + "sparse_mode": 6, | ||
| 170 | + "prefix": [1568] | ||
| 171 | + }, | ||
| 172 | + "TND_03": { | ||
| 173 | + "N1": 8, | ||
| 174 | + "N2": 4, | ||
| 175 | + "actual_seq_qlen": [256, 512, 768], | ||
| 176 | + "actual_seq_kvlen": [256, 512, 768], | ||
| 177 | + "D": 128, # query&key's head-dim | ||
| 178 | + "input_layout": "TND", | ||
| 179 | + "dtype": torch.bfloat16, | ||
| 180 | + "sparse_mode": 3, | ||
| 181 | + "pse_type": 3, # special alibi | ||
| 182 | + "pse_layout": "n", # for generate golden data | ||
| 183 | + "keep_prob": 0.9, # keep_prob = 1 - dropout_p | ||
| 184 | + }, | ||
| 185 | + "TND_04": { | ||
| 186 | + "N1": 8, | ||
| 187 | + "N2": 4, | ||
| 188 | + "actual_seq_qlen": [128, 256, 512], | ||
| 189 | + "actual_seq_kvlen": [256, 512, 768], | ||
| 190 | + "D": 128, # query&key's head-dim | ||
| 191 | + "input_layout": "TND", | ||
| 192 | + "dtype": torch.bfloat16, | ||
| 193 | + "sparse_mode": 8, | ||
| 194 | + "next_tokens": 64, | ||
| 195 | + "q_start_idx": 64, | ||
| 196 | + "kv_start_idx": 32, | ||
| 197 | + "keep_prob": 0.9, # keep_prob = 1 - dropout_p | ||
| 198 | + } | ||
| 199 | +} | ||


API设计一致性: aclnnFlashAttentionScoreV4GetWorkspaceSize函数参数列表与其他版本(如V2、V3)存在不一致性,新增了多个可选参数(queryRopeOptional, keyRopeOptional, dScaleQOptional等),但函数命名和注释没有明确说明这些新增参数的具体用途和版本差异。这可能导致API使用者混淆,不知道何时应该使用哪个版本。
问题类型: API设计一致性 文件路径:
attention/flash_attention_score/op_api/aclnn_flash_attention_score.h行号: 143 问题代码:修改建议:
此评论由代码审查工具自动生成