已合并
aclnnDiv\aclnnDivMod混合数据类型内存优化 #943
aclnnDiv\aclnnDivMod混合数据类型内存优化 #943
已合并
xiu_ling_wang创建于 1月27日
5 个文件变更+265-114
@@ -367,7 +367,99 @@ inline static bool isDivsMixDtypeSupport(const aclTensor* self, const aclScalar*
367 (self->GetDataType() == DataType::DT_FLOAT && other->GetDataType() == DataType::DT_FLOAT16) ||367 (self->GetDataType() == DataType::DT_FLOAT && other->GetDataType() == DataType::DT_FLOAT16) ||
368 (self->GetDataType() == DataType::DT_BF16 && other->GetDataType() == DataType::DT_FLOAT) ||368 (self->GetDataType() == DataType::DT_BF16 && other->GetDataType() == DataType::DT_FLOAT) ||
369 (self->GetDataType() == DataType::DT_FLOAT && other->GetDataType() == DataType::DT_BF16) ||369 (self->GetDataType() == DataType::DT_FLOAT && other->GetDataType() == DataType::DT_BF16) ||
370- (self->GetDataType() == DataType::DT_BF16 && other->GetDataType() == DataType::DT_DOUBLE);370+ (self->GetDataType() == DataType::DT_BF16 && other->GetDataType() == DataType::DT_DOUBLE) ||
371+ (self->GetDataType() == DataType::DT_FLOAT16 && other->GetDataType() == DataType::DT_BF16) ||
372+ (self->GetDataType() == DataType::DT_BF16 && other->GetDataType() == DataType::DT_FLOAT16);
373+}
374+ 
375+inline static bool checkMixDtypeConditions(DataType selfDtype, DataType otherDtype){
CANN-robot
CANN-robotCANN-robot1月27日

代码结构与可维护性: checkMixDtypeConditions函数(第375-382行)与isDivsMixDtypeSupport函数(第360-373行)存在功能重叠但逻辑不完全一致。isDivsMixDtypeSupport检查了更多数据类型组合(包括DT_BF16和DT_DOUBLE),而checkMixDtypeConditions只检查了部分组合。这可能导致不一致的判断结果。

问题类型: 代码结构与可维护性 文件路径: math/div/op_api/aclnn_div.cpp 行号: 375 问题代码:

inline static bool checkMixDtypeConditions(DataType selfDtype, DataType otherDtype){
    return (selfDtype == DataType::DT_FLOAT16 && otherDtype == DataType::DT_FLOAT) ||
        (selfDtype == DataType::DT_FLOAT16 && otherDtype == DataType::DT_BF16) ||
        (selfDtype == DataType::DT_BF16 && otherDtype == DataType::DT_FLOAT) ||
        (selfDtype == DataType::DT_BF16 && otherDtype == DataType::DT_FLOAT16) ||
        (selfDtype == DataType::DT_FLOAT && otherDtype == DataType::DT_FLOAT16) ||
        (selfDtype == DataType::DT_FLOAT && otherDtype == DataType::DT_BF16);
}

修改建议:

统一混合数据类型的检查逻辑。要么扩展checkMixDtypeConditions以包含isDivsMixDtypeSupport中的所有组合,要么重构代码只使用一个检查函数。同时添加注释说明哪些数据类型组合被认为是混合数据类型。

此评论由代码审查工具自动生成

likedislike
376+ return (selfDtype == DataType::DT_FLOAT16 && otherDtype == DataType::DT_FLOAT) ||
377+ (selfDtype == DataType::DT_FLOAT16 && otherDtype == DataType::DT_BF16) ||
378+ (selfDtype == DataType::DT_BF16 && otherDtype == DataType::DT_FLOAT) ||
379+ (selfDtype == DataType::DT_BF16 && otherDtype == DataType::DT_FLOAT16) ||
380+ (selfDtype == DataType::DT_FLOAT && otherDtype == DataType::DT_FLOAT16) ||
381+ (selfDtype == DataType::DT_FLOAT && otherDtype == DataType::DT_BF16);
382+}
383+ 
384+inline static bool isMixDtypeScalarSupport(const aclTensor* self, const aclScalar* other)
385+{
386+ auto socVersion = GetCurrentPlatformInfo().GetSocVersion();
387+ if (socVersion != SocVersion::ASCEND910B && socVersion != SocVersion::ASCEND910_93) {
388+ return false;
389+ }
390+ return checkMixDtypeConditions(self->GetDataType(), other->GetDataType());
391+}
392+ 
393+inline static bool isMixDtypeTensorSupport(const aclTensor* self, const aclTensor* other)
394+{
395+ auto socVersion = GetCurrentPlatformInfo().GetSocVersion();
396+ if (socVersion != SocVersion::ASCEND910B && socVersion != SocVersion::ASCEND910_93) {
397+ return false;
398+ }
399+ return checkMixDtypeConditions(self->GetDataType(), other->GetDataType());
400+}
401+ 
402+static aclnnStatus HandleMixDataTypeDiv(
403+ const aclTensor* self, const aclTensor* other, aclOpExecutor* executor, const aclTensor** divOpOut
404+) {
405+ // 固定写法,将输入self转换成连续的tensor
406+ auto selfContiguous = l0op::Contiguous(self, executor);
407+ CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
408+ 
409+ // 固定写法,将输入other转换成连续的tensor
410+ auto otherContiguous = l0op::Contiguous(other, executor);
411+ CHECK_RET(otherContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
412+ 
413+ *divOpOut = l0op::RealDiv(selfContiguous, otherContiguous, false, executor);
CANN-robot
CANN-robotCANN-robot1月27日

指针与引用安全: 在HandleMixDataTypeDiv函数中,第414行对divOpOut指针进行了空指针检查,但检查的是指针的指针(divOpOut)而不是指针本身(divOpOut)。CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR)应该检查的是divOpOut是否为nullptr,因为divOpOut是const aclTensor**类型,而l0op::RealDiv返回的是const aclTensor*。这里检查的是二级指针本身是否为空,而不是检查返回的tensor指针是否为空。

问题类型: 指针与引用安全 文件路径: math/div/op_api/aclnn_div.cpp 行号: 413 问题代码:

    *divOpOut = l0op::RealDiv(selfContiguous, otherContiguous, false, executor);
    CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);

修改建议:

将CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR)改为CHECK_RET(*divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR),以正确检查RealDiv函数返回的tensor指针是否为空。

此评论由代码审查工具自动生成

likedislike
414+ CHECK_RET(*divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
415+ 
416+ return ACLNN_SUCCESS;
417+}
418+ 
419+static aclnnStatus HandleNotMixDataTypeDiv(
420+ const aclTensor* self, const aclTensor* other, aclOpExecutor* executor, const aclTensor** divOpOut
421+) {
422+ // RealDiv算子需要对self和other两个输入做隐式数据类型转换,根据具体算子语义按需调用
423+ auto npuArch = op::GetCurrentPlatformInfo().GetCurNpuArch();
424+ auto promoteType = (!IsRegBase(npuArch)) ?
425+ CompatibleInferDivDtype(self->GetDataType(), other->GetDataType()) :
426+ InferDivModeDtype(self->GetDataType(), other->GetDataType(), MODE_REAL_DIV);
427+ 
428+ // 处理self输入
429+ const aclTensor* selfProcessed = nullptr;
430+ if (self->GetDataType() == promoteType && l0op::IsRealDivSupportNonContiguous(self)) {
431+ selfProcessed = executor->CreateView(
432+ self, self->GetViewShape(), self->GetStorageShape(), self->GetViewStrides(), self->GetViewOffset());
433+ } else {
434+ // 固定写法,将输入self转换成连续的tensor
435+ auto selfContiguous = l0op::Contiguous(self, executor);
436+ CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
437+ 
438+ // 将输入self的数据类型转换成隐式数据类型,根据具体算子语义按需调用
439+ selfProcessed = l0op::Cast(selfContiguous, promoteType, executor);
440+ }
441+ CHECK_RET(selfProcessed != nullptr, ACLNN_ERR_INNER_NULLPTR);
442+ 
443+ // 处理other输入
444+ const aclTensor* otherProcessed = nullptr;
445+ if (other->GetDataType() == promoteType && l0op::IsRealDivSupportNonContiguous(self)) {
446+ otherProcessed = executor->CreateView(
447+ other, other->GetViewShape(), other->GetStorageShape(), other->GetViewStrides(), other->GetViewOffset());
448+ } else {
449+ // 固定写法,将输入other转换成连续的tensor
450+ auto otherContiguous = l0op::Contiguous(other, executor);
451+ CHECK_RET(otherContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
452+ 
453+ // 将输入other的数据类型转换成隐式数据类型,根据具体算子语义按需调用
454+ otherProcessed = l0op::Cast(otherContiguous, promoteType, executor);
455+ }
456+ CHECK_RET(otherProcessed != nullptr, ACLNN_ERR_INNER_NULLPTR);
457+ 
458+ // 调用l0算子RealDiv进行计算
459+ *divOpOut = l0op::RealDiv(selfProcessed, otherProcessed, MODE_REAL_DIV, executor);
460+ CHECK_RET(*divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
461+ 
462+ return ACLNN_SUCCESS;
371}463}
372 464 
373aclnnStatus aclnnDivGetWorkspaceSize(465aclnnStatus aclnnDivGetWorkspaceSize(
@@ -390,45 +482,15 @@ aclnnStatus aclnnDivGetWorkspaceSize(
390 return ACLNN_SUCCESS;482 return ACLNN_SUCCESS;
391 }483 }
392 484 
393- // RealDiv算子需要对selfother两个输入做隐式数据类型转换,根据具体算子语义按需调用485+ bool isMixDataType = isMixDtypeTensorSupport(self, other);
394- auto npuArch = op::GetCurrentPlatformInfo().GetCurNpuArch();486+ const aclTensor* divOpOut = nullptr;
395- auto promoteType = (!IsRegBase(npuArch)) ?487+ if (isMixDataType) {
396- CompatibleInferDivDtype(self->GetDataType(), other->GetDataType()) :488+ auto mixResult = HandleMixDataTypeDiv(self, other, uniqueExecutor.get(), &divOpOut);
397- InferDivModeDtype(self->GetDataType(), other->GetDataType(), MODE_REAL_DIV);489+ CHECK_RET(mixResult == ACLNN_SUCCESS, mixResult);
398- 
399- // 处理self输入
400- const aclTensor* selfProcessed = nullptr;
401- if (self->GetDataType() == promoteType && l0op::IsRealDivSupportNonContiguous(self)) {
402- selfProcessed = uniqueExecutor.get()->CreateView(
403- self, self->GetViewShape(), self->GetStorageShape(), self->GetViewStrides(), self->GetViewOffset());
404 } else {490 } else {
405- // 固定写法,将输入self转换成连续的tensor491+ auto notMixResult = HandleNotMixDataTypeDiv(self, other, uniqueExecutor.get(), &divOpOut);
406- auto selfContiguous = l0op::Contiguous(self, uniqueExecutor.get());492+ CHECK_RET(notMixResult == ACLNN_SUCCESS, notMixResult);
407- CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
408- 
409- // 将输入self的数据类型转换成隐式数据类型,根据具体算子语义按需调用
410- selfProcessed = l0op::Cast(selfContiguous, promoteType, uniqueExecutor.get());
411 }493 }
412- CHECK_RET(selfProcessed != nullptr, ACLNN_ERR_INNER_NULLPTR);
413- 
414- // 处理other输入
415- const aclTensor* otherProcessed = nullptr;
416- if (other->GetDataType() == promoteType && l0op::IsRealDivSupportNonContiguous(self)) {
417- otherProcessed = uniqueExecutor.get()->CreateView(
418- other, other->GetViewShape(), other->GetStorageShape(), other->GetViewStrides(), other->GetViewOffset());
419- } else {
420- // 固定写法,将输入other转换成连续的tensor
421- auto otherContiguous = l0op::Contiguous(other, uniqueExecutor.get());
422- CHECK_RET(otherContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
423- 
424- // 将输入other的数据类型转换成隐式数据类型,根据具体算子语义按需调用
425- otherProcessed = l0op::Cast(otherContiguous, promoteType, uniqueExecutor.get());
426- }
427- CHECK_RET(otherProcessed != nullptr, ACLNN_ERR_INNER_NULLPTR);
428- 
429- // 调用l0算子RealDiv进行计算
430- auto divOpOut = l0op::RealDiv(selfProcessed, otherProcessed, MODE_REAL_DIV, uniqueExecutor.get());
431- CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
432 494 
433 // 固定写法,将计算结果转换成输出out的数据类型495 // 固定写法,将计算结果转换成输出out的数据类型
434 auto castOut = l0op::Cast(divOpOut, out->GetDataType(), uniqueExecutor.get());496 auto castOut = l0op::Cast(divOpOut, out->GetDataType(), uniqueExecutor.get());
@@ -568,7 +630,7 @@ aclnnStatus aclnnDivsGetWorkspaceSize(
568 self->GetViewStrides(), self->GetViewOffset()) :630 self->GetViewStrides(), self->GetViewOffset()) :
569 l0op::Contiguous(self, uniqueExecutor.get());631 l0op::Contiguous(self, uniqueExecutor.get());
570 CHECK_RET(selfProcessed != nullptr, ACLNN_ERR_INNER_NULLPTR);632 CHECK_RET(selfProcessed != nullptr, ACLNN_ERR_INNER_NULLPTR);
571- divOpOut = l0op::RealDiv(selfProcessed, otherConvert, MODE_REAL_DIV, uniqueExecutor.get());633+ divOpOut = l0op::RealDiv(selfProcessed, otherConvert, true, uniqueExecutor.get());
CANN-robot
CANN-robotCANN-robot1月27日

逻辑运算与副作用: 在第621行,混合数据类型处理时调用l0op::RealDiv时使用了true作为第三个参数,但在非混合数据类型的处理中(第482行)使用的是MODE_REAL_DIV。这两个参数的含义可能不同:true可能表示标量除法模式,而MODE_REAL_DIV是常量0。这可能导致不一致的行为。

问题类型: 逻辑运算与副作用 文件路径: math/div/op_api/aclnn_div.cpp 行号: 624 问题代码:

        divOpOut = l0op::RealDiv(selfProcessed, otherConvert, true, uniqueExecutor.get());

修改建议:

检查l0op::RealDiv函数的参数定义,确保混合数据类型和非混合数据类型处理使用一致的参数。如果true确实表示标量模式,那么应该添加注释说明;否则应该使用与第482行相同的MODE_REAL_DIV常量。

此评论由代码审查工具自动生成

likedislike
572 CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);634 CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
573 } else {635 } else {
574 auto promoteType = (!IsRegBase(npuArch)) ?636 auto promoteType = (!IsRegBase(npuArch)) ?
CANN-robot
CANN-robotCANN-robot1月27日

代码结构与可维护性: 在第630-638行,aclnnDivsGetWorkspaceSize函数中,promoteType的计算逻辑复杂且存在重复。第630行已经调用InferDivsModeDtype计算了promoteType,但第631-638行又用不同的逻辑重新计算了promoteType,这会覆盖之前的结果。这种重复和覆盖可能导致意外的数据类型提升结果。

问题类型: 代码结构与可维护性 文件路径: math/div/op_api/aclnn_div.cpp 行号: 627 问题代码:

        auto promoteType = (!IsRegBase(npuArch)) ?
                               CompatibleInferDivsDtype(self->GetDataType(), other->GetDataType()) :
                               InferDivsModeDtype(self->GetDataType(), other->GetDataType(), MODE_REAL_DIV);
        promoteType = (IsFloatingType(self->GetDataType()) || IsComplexType(self->GetDataType())) ?
                           self->GetDataType() : op::DataType::DT_FLOAT;
        promoteType = (self->GetDataType() == op::DataType::DT_BOOL && other->GetDataType() == op::DataType::DT_BOOL) ?
                           self->GetDataType() : promoteType;
        promoteType = (IsComplexType(other->GetDataType())) ? op::PromoteType(promoteType, other->GetDataType()) : promoteType;
        if (IsRegBase(npuArch)) {
            promoteType = op::PromoteType(self->GetDataType(), other->GetDataType()) == op::DataType::DT_INT32
                          ? op::DataType::DT_INT32 : promoteType;
        }

修改建议:

简化promoteType的计算逻辑,避免重复和覆盖。如果InferDivsModeDtype已经提供了正确的数据类型提升,就不需要后续的复杂覆盖逻辑。或者将整个逻辑封装到一个单独的函数中,提高代码可读性和可维护性。

此评论由代码审查工具自动生成

likedislike
@@ -655,47 +717,64 @@ aclnnStatus aclnnDivModGetWorkspaceSize(
655 717 
656 auto selfCasted = selfContiguous;718 auto selfCasted = selfContiguous;
657 auto otherCasted = otherContiguous;719 auto otherCasted = otherContiguous;
658- op::DataType promoteType;720+ 
659- bool needToInt32 = false;721+ bool isMixDataType = isMixDtypeTensorSupport(self, other);
660- op::DataType oriType = out->GetDataType();
661- auto npuArch = op::GetCurrentPlatformInfo().GetCurNpuArch();
662- if (!IsRegBase(npuArch)) {
663- auto promoteRet = CompatibleInferDivModeDtype(self->GetDataType(), other->GetDataType(), mode, promoteType);
664- CHECK_RET(promoteRet == ACLNN_SUCCESS, promoteRet);
665- } else {
666- promoteType = InferDivModeDtype(self->GetDataType(), other->GetDataType(), mode);
667- // customization
668- bool needToFloat = (promoteType == op::DataType::DT_BOOL && mode == MODE_FLOOR_DIV);
669- promoteType = needToFloat ? op::DataType::DT_FLOAT : promoteType;
670- // aicore is not supported, aicpu has problems when div 0
671- needToInt32 = (promoteType == op::DataType::DT_INT16 && mode == MODE_FLOOR_DIV) ||
672- ((promoteType == op::DataType::DT_INT8 || promoteType == op::DataType::DT_UINT8 ||
673- promoteType == op::DataType::DT_INT16) &&
674- mode == MODE_TRUNC_DIV);
675- oriType = promoteType;
676- promoteType = needToInt32 ? op::DataType::DT_INT32 : promoteType;
677- }
678- selfCasted = l0op::Cast(selfContiguous, promoteType, uniqueExecutor.get());
679- CHECK_RET(selfCasted != nullptr, ACLNN_ERR_INNER_NULLPTR);
680- otherCasted = l0op::Cast(otherContiguous, promoteType, uniqueExecutor.get());
681- CHECK_RET(otherCasted != nullptr, ACLNN_ERR_INNER_NULLPTR);
682 const aclTensor* divOpOut = nullptr;722 const aclTensor* divOpOut = nullptr;
683- // 根据mode分三种场景调用算子计算723+ if (isMixDataType) {
684- if (mode == MODE_FLOOR_DIV) {724+ if (mode == MODE_FLOOR_DIV) {
685- divOpOut = l0op::FloorDiv(selfCasted, otherCasted, uniqueExecutor.get());725+ divOpOut = l0op::FloorDiv(selfCasted, otherCasted, false, uniqueExecutor.get());
CANN-robot
CANN-robotCANN-robot1月27日

逻辑运算与副作用: 在第716行,混合数据类型处理时调用l0op::FloorDiv使用了false作为第三个参数,但在非混合数据类型的处理中(第753行)没有这个参数。这可能导致函数调用不一致,需要确认l0op::FloorDiv的函数签名。

问题类型: 逻辑运算与副作用 文件路径: math/div/op_api/aclnn_div.cpp 行号: 716 问题代码:

            divOpOut = l0op::FloorDiv(selfCasted, otherCasted, false, uniqueExecutor.get());

修改建议:

检查l0op::FloorDiv的函数定义,确认参数列表。如果第753行的调用是正确的,那么第716行可能需要移除第三个参数false。确保所有调用方式一致。

此评论由代码审查工具自动生成

likedislike
686- } else {726+ } else {
687- divOpOut = l0op::RealDiv(selfCasted, otherCasted, mode, uniqueExecutor.get());727+ divOpOut = l0op::RealDiv(selfCasted, otherCasted, false, uniqueExecutor.get());
728+ CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
729+ if (mode == MODE_TRUNC_DIV && divOpOut->GetDataType() != op::DataType::DT_INT64 &&
730+ divOpOut->GetDataType() != op::DataType::DT_INT16) {
731+ divOpOut = l0op::Trunc(divOpOut, uniqueExecutor.get());
732+ }
733+ }
688 CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);734 CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
689- if (mode == MODE_TRUNC_DIV && divOpOut->GetDataType() != op::DataType::DT_INT64 &&735+ } else {
690- divOpOut->GetDataType() != op::DataType::DT_INT16) {736+ op::DataType promoteType;
691- divOpOut = l0op::Trunc(divOpOut, uniqueExecutor.get());737+ bool needToInt32 = false;
738+ op::DataType oriType = out->GetDataType();
739+ auto npuArch = op::GetCurrentPlatformInfo().GetCurNpuArch();
740+ if (!IsRegBase(npuArch)) {
741+ auto promoteRet = CompatibleInferDivModeDtype(self->GetDataType(), other->GetDataType(), mode, promoteType);
742+ CHECK_RET(promoteRet == ACLNN_SUCCESS, promoteRet);
743+ } else {
744+ promoteType = InferDivModeDtype(self->GetDataType(), other->GetDataType(), mode);
745+ // customization
746+ bool needToFloat = (promoteType == op::DataType::DT_BOOL && mode == MODE_FLOOR_DIV);
747+ promoteType = needToFloat ? op::DataType::DT_FLOAT : promoteType;
748+ // aicore is not supported, aicpu has problems when div 0
749+ needToInt32 = (promoteType == op::DataType::DT_INT16 && mode == MODE_FLOOR_DIV) ||
750+ ((promoteType == op::DataType::DT_INT8 || promoteType == op::DataType::DT_UINT8 ||
751+ promoteType == op::DataType::DT_INT16) &&
752+ mode == MODE_TRUNC_DIV);
753+ oriType = promoteType;
754+ promoteType = needToInt32 ? op::DataType::DT_INT32 : promoteType;
755+ }
756+ selfCasted = l0op::Cast(selfContiguous, promoteType, uniqueExecutor.get());
757+ CHECK_RET(selfCasted != nullptr, ACLNN_ERR_INNER_NULLPTR);
758+ otherCasted = l0op::Cast(otherContiguous, promoteType, uniqueExecutor.get());
759+ CHECK_RET(otherCasted != nullptr, ACLNN_ERR_INNER_NULLPTR);
760+ // 根据mode分三种场景调用算子计算
761+ if (mode == MODE_FLOOR_DIV) {
762+ divOpOut = l0op::FloorDiv(selfCasted, otherCasted, uniqueExecutor.get());
763+ } else {
764+ divOpOut = l0op::RealDiv(selfCasted, otherCasted, mode, uniqueExecutor.get());
765+ CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
766+ if (mode == MODE_TRUNC_DIV && divOpOut->GetDataType() != op::DataType::DT_INT64 &&
767+ divOpOut->GetDataType() != op::DataType::DT_INT16) {
768+ divOpOut = l0op::Trunc(divOpOut, uniqueExecutor.get());
769+ }
770+ }
771+ CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
772+ if (needToInt32) {
773+ divOpOut = l0op::Cast(divOpOut, oriType, uniqueExecutor.get());
774+ CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
692 }775 }
693 }776 }
694- CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);777+
695- if (needToInt32) {
696- divOpOut = l0op::Cast(divOpOut, oriType, uniqueExecutor.get());
697- CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
698- }
699 auto castOut = l0op::Cast(divOpOut, out->GetDataType(), uniqueExecutor.get());778 auto castOut = l0op::Cast(divOpOut, out->GetDataType(), uniqueExecutor.get());
700 CHECK_RET(castOut != nullptr, ACLNN_ERR_INNER_NULLPTR);779 CHECK_RET(castOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
701 780 
@@ -737,47 +816,65 @@ aclnnStatus aclnnDivModsGetWorkspaceSize(
737 CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);816 CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
738 817 
739 auto selfCasted = selfContiguous;818 auto selfCasted = selfContiguous;
740- op::DataType promoteType;819+ bool isMixDataType = isMixDtypeScalarSupport(self, other);
741- bool needToInt32 = false;
742- op::DataType oriType = out->GetDataType();
743- auto npuArch = op::GetCurrentPlatformInfo().GetCurNpuArch();
744- if (!IsRegBase(npuArch)) {
745- auto promoteRet = CompatibleInferDivsModeDtype(self->GetDataType(), other->GetDataType(), mode, promoteType);
746- CHECK_RET(promoteRet == ACLNN_SUCCESS, promoteRet);
747- } else {
748- promoteType = InferDivsModeDtype(self->GetDataType(), other->GetDataType(), mode);
749- // customization
750- bool needToFloat = (promoteType == op::DataType::DT_BOOL && mode == MODE_FLOOR_DIV);
751- promoteType = needToFloat ? op::DataType::DT_FLOAT : promoteType;
752- // aicore is not supported, aicpu has problems when div 0
753- needToInt32 = (promoteType == op::DataType::DT_INT16 && mode == MODE_FLOOR_DIV) ||
754- ((promoteType == op::DataType::DT_INT8 || promoteType == op::DataType::DT_UINT8 ||
755- promoteType == op::DataType::DT_INT16) &&
756- mode == MODE_TRUNC_DIV);
757- oriType = promoteType;
758- promoteType = needToInt32 ? op::DataType::DT_INT32 : promoteType;
759- }
760- selfCasted = l0op::Cast(selfContiguous, promoteType, uniqueExecutor.get());
761- CHECK_RET(selfCasted != nullptr, ACLNN_ERR_INNER_NULLPTR);
762- auto otherCasted = uniqueExecutor.get()->ConvertToTensor(other, promoteType);
763- CHECK_RET(otherCasted != nullptr, ACLNN_ERR_INNER_NULLPTR);
764 const aclTensor* divOpOut = nullptr;820 const aclTensor* divOpOut = nullptr;
765- // 根据mode分三种场景调用算子计算821+ if (isMixDataType) {
766- if (mode == MODE_FLOOR_DIV) {822+ auto otherConvert = uniqueExecutor.get()->ConvertToTensor(other, other->GetDataType());
767- divOpOut = l0op::FloorDiv(selfCasted, otherCasted, uniqueExecutor.get());823+ CHECK_RET(otherConvert != nullptr, ACLNN_ERR_INNER_NULLPTR);
768- } else {824+ if (mode == MODE_FLOOR_DIV) {
769- divOpOut = l0op::RealDiv(selfCasted, otherCasted, mode, uniqueExecutor.get());825+ divOpOut = l0op::FloorDiv(selfCasted, otherConvert, true, uniqueExecutor.get());
826+ } else {
827+ divOpOut = l0op::RealDiv(selfCasted, otherConvert, true, uniqueExecutor.get());
828+ CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
829+ if (mode == MODE_TRUNC_DIV && divOpOut->GetDataType() != op::DataType::DT_INT64 &&
830+ divOpOut->GetDataType() != op::DataType::DT_INT16) {
831+ divOpOut = l0op::Trunc(divOpOut, uniqueExecutor.get());
832+ }
833+ }
770 CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);834 CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
771- if (mode == MODE_TRUNC_DIV && divOpOut->GetDataType() != op::DataType::DT_INT64 &&835+ } else {
772- divOpOut->GetDataType() != op::DataType::DT_INT16) {836+ op::DataType promoteType;
773- divOpOut = l0op::Trunc(divOpOut, uniqueExecutor.get());837+ bool needToInt32 = false;
838+ op::DataType oriType = out->GetDataType();
839+ auto npuArch = op::GetCurrentPlatformInfo().GetCurNpuArch();
840+ if (!IsRegBase(npuArch)) {
841+ auto promoteRet = CompatibleInferDivsModeDtype(self->GetDataType(), other->GetDataType(), mode, promoteType);
842+ CHECK_RET(promoteRet == ACLNN_SUCCESS, promoteRet);
843+ } else {
844+ promoteType = InferDivsModeDtype(self->GetDataType(), other->GetDataType(), mode);
845+ // customization
846+ bool needToFloat = (promoteType == op::DataType::DT_BOOL && mode == MODE_FLOOR_DIV);
847+ promoteType = needToFloat ? op::DataType::DT_FLOAT : promoteType;
848+ // aicore is not supported, aicpu has problems when div 0
849+ needToInt32 = (promoteType == op::DataType::DT_INT16 && mode == MODE_FLOOR_DIV) ||
850+ ((promoteType == op::DataType::DT_INT8 || promoteType == op::DataType::DT_UINT8 ||
851+ promoteType == op::DataType::DT_INT16) &&
852+ mode == MODE_TRUNC_DIV);
853+ oriType = promoteType;
854+ promoteType = needToInt32 ? op::DataType::DT_INT32 : promoteType;
855+ }
856+ selfCasted = l0op::Cast(selfContiguous, promoteType, uniqueExecutor.get());
857+ CHECK_RET(selfCasted != nullptr, ACLNN_ERR_INNER_NULLPTR);
858+ auto otherCasted = uniqueExecutor.get()->ConvertToTensor(other, promoteType);
859+ CHECK_RET(otherCasted != nullptr, ACLNN_ERR_INNER_NULLPTR);
860+ // 根据mode分三种场景调用算子计算
861+ if (mode == MODE_FLOOR_DIV) {
862+ divOpOut = l0op::FloorDiv(selfCasted, otherCasted, uniqueExecutor.get());
863+ } else {
864+ divOpOut = l0op::RealDiv(selfCasted, otherCasted, mode, uniqueExecutor.get());
865+ CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
866+ if (mode == MODE_TRUNC_DIV && divOpOut->GetDataType() != op::DataType::DT_INT64 &&
867+ divOpOut->GetDataType() != op::DataType::DT_INT16) {
868+ divOpOut = l0op::Trunc(divOpOut, uniqueExecutor.get());
869+ }
870+ }
871+ CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
872+ if (needToInt32) {
873+ divOpOut = l0op::Cast(divOpOut, oriType, uniqueExecutor.get());
874+ CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
774 }875 }
775 }876 }
776- CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);877+
777- if (needToInt32) {
778- divOpOut = l0op::Cast(divOpOut, oriType, uniqueExecutor.get());
779- CHECK_RET(divOpOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
780- }
781 auto castOut = l0op::Cast(divOpOut, out->GetDataType(), uniqueExecutor.get());878 auto castOut = l0op::Cast(divOpOut, out->GetDataType(), uniqueExecutor.get());
782 CHECK_RET(castOut != nullptr, ACLNN_ERR_INNER_NULLPTR);879 CHECK_RET(castOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
783 880 
@@ -92,4 +92,28 @@ const aclTensor* FloorDiv(const aclTensor* self, const aclTensor* other, aclOpEx
92 }92 }
93}93}
94 94 
95+const aclTensor* FloorDiv(const aclTensor* self, const aclTensor* other, bool isScalar, aclOpExecutor* executor)
96+{
97+ op::Shape broadcastShape;
98+ if (!BroadcastInferShape(self->GetViewShape(), other->GetViewShape(), broadcastShape)) {
99+ OP_LOGE(
100+ ACLNN_ERR_PARAM_INVALID, "Broadcast %s and %s failed.", op::ToString(self->GetViewShape()).GetString(),
101+ op::ToString(other->GetViewShape()).GetString());
102+ return nullptr;
103+ }
104+
105+ aclTensor* out;
106+ if (isScalar || self->GetDataType() == other->GetDataType()) {
107+ out = executor->AllocTensor(broadcastShape, self->GetDataType());
108+ } else {
109+ out = executor->AllocTensor(broadcastShape, op::DataType::DT_FLOAT);
110+ }
111+ 
112+ if (IsAiCoreSupport(self)) {
113+ return FloorDivAiCore(self, other, out, executor);
114+ } else {
115+ return FloorDivAiCpu(self, other, out, executor);
116+ }
117+}
118+ 
95} // namespace l0op119} // namespace l0op
@@ -13,7 +13,8 @@
13#include "opdev/op_executor.h"13#include "opdev/op_executor.h"
14 14 
15namespace l0op {15namespace l0op {
16-const aclTensor* FloorDiv(const aclTensor* self, const aclTensor* other, aclOpExecutor* executor);16+ const aclTensor* FloorDiv(const aclTensor* self, const aclTensor* other, aclOpExecutor* executor);
17+ const aclTensor* FloorDiv(const aclTensor* self, const aclTensor* other, bool isScalar, aclOpExecutor* executor);
17}18}
18 19 
19#endif // PTA_NPU_OP_API_INC_LEVEL0_OP_FLOOR_DIV_OP_H_20#endif // PTA_NPU_OP_API_INC_LEVEL0_OP_FLOOR_DIV_OP_H_
@@ -131,4 +131,32 @@ const aclTensor* RealDiv(const aclTensor* self, const aclTensor* other, const in
131 return divOut;131 return divOut;
132}132}
133 133 
134+static const aclTensor* RealDivKernel(const aclTensor* self, const aclTensor* other, aclTensor* divOut,
135+ aclOpExecutor* executor) {
136+ if (IsAiCoreSupport(self)) {
137+ return RealDivAiCore(self, other, divOut, executor);
138+ } else {
139+ return RealDivAiCpu(self, other, divOut, executor);
140+ }
141+}
142+ 
143+const aclTensor* RealDiv(const aclTensor* self, const aclTensor* other, bool isScalar, aclOpExecutor* executor) {
144+ op::Shape broadcastShape;
145+ if (!BroadcastInferShape(self->GetViewShape(), other->GetViewShape(), broadcastShape)) {
146+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Broadcast %s and %s failed.", op::ToString(self->GetViewShape()).GetString(),
147+ op::ToString(other->GetViewShape()).GetString());
148+ return nullptr;
149+ }
150+ 
151+ aclTensor* divOut;
152+ if ((isScalar && self->GetDataType() != op::DataType::DT_BOOL) ||
153+ ((!isScalar) && self->GetDataType() == other->GetDataType() && self->GetDataType() != op::DataType::DT_BOOL)) {
154+ divOut = executor->AllocTensor(broadcastShape, self->GetDataType());
155+ } else {
156+ divOut = executor->AllocTensor(broadcastShape, op::DataType::DT_FLOAT);
157+ }
158+ 
159+ return RealDivKernel(self, other, divOut, executor);
160+}
161+ 
134} // namespace l0op162} // namespace l0op
@@ -16,6 +16,7 @@
16namespace l0op {16namespace l0op {
17 const aclTensor *RealDiv(const aclTensor *self, const aclTensor *other, aclOpExecutor *executor);17 const aclTensor *RealDiv(const aclTensor *self, const aclTensor *other, aclOpExecutor *executor);
18 const aclTensor *RealDiv(const aclTensor *self, const aclTensor *other, const int mode, aclOpExecutor *executor);18 const aclTensor *RealDiv(const aclTensor *self, const aclTensor *other, const int mode, aclOpExecutor *executor);
19+ const aclTensor *RealDiv(const aclTensor *self, const aclTensor *other, bool isScalar, aclOpExecutor *executor);
19 bool IsRealDivSupportNonContiguous(const aclTensor* self);20 bool IsRealDivSupportNonContiguous(const aclTensor* self);
20}21}
21 22