已合并
修改log_add_exp小值域情况下精度误差 #3631
修改log_add_exp小值域情况下精度误差 #3631
已合并
zhangqijia1创建于 6月29日
2 个文件变更+63-21
@@ -108,6 +108,39 @@ static bool CheckShape(const aclTensor* self, const aclTensor* other) {
108 return true;108 return true;
109}109}
110 110 
111+static bool CheckFormat(const aclTensor* self, const aclTensor* other, const aclTensor* out)
112+{
113+ if (self->GetStorageFormat() != out->GetStorageFormat()) {
114+ OP_LOGE(
115+ ACLNN_ERR_PARAM_INVALID, "Format of self and output should be equal. self [%s], out [%s].",
116+ ToString(self->GetStorageFormat()).GetString(), ToString(out->GetStorageFormat()).GetString());
117+ return false;
118+ }
119+ 
120+ if (other->GetStorageFormat() != out->GetStorageFormat()) {
121+ OP_LOGE(
122+ ACLNN_ERR_PARAM_INVALID, "Format of other and output should be equal. other [%s], out [%s].",
123+ ToString(other->GetStorageFormat()).GetString(), ToString(out->GetStorageFormat()).GetString());
124+ return false;
125+ }
126+ 
127+ if (IsPrivateFormat(self->GetStorageFormat())) {
128+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Format only support ND、NCHW、NHWC、HWCN、NDHWC、NCDHW.");
129+ return false;
130+ }
131+ 
132+ return true;
133+}
134+ 
135+static void WarnFormat(const aclTensor* self, const aclTensor* target)
136+{
137+ ge::Format selfStorageFormat = self->GetStorageFormat();
138+ ge::Format targetStorageFormat = target->GetStorageFormat();
139+ if (selfStorageFormat != ge::Format::FORMAT_ND || targetStorageFormat != ge::Format::FORMAT_ND) {
140+ OP_LOGW("aclnnLogAddExp only support format ND.");
141+ }
142+}
143+ 
111static aclnnStatus CheckParams(const aclTensor* self, const aclTensor* other, const aclTensor* out) {144static aclnnStatus CheckParams(const aclTensor* self, const aclTensor* other, const aclTensor* out) {
112 // 1. 检查参数是否为空指针145 // 1. 检查参数是否为空指针
113 CHECK_RET(CheckNotNull3Tensor(self, other, out), ACLNN_ERR_PARAM_NULLPTR);146 CHECK_RET(CheckNotNull3Tensor(self, other, out), ACLNN_ERR_PARAM_NULLPTR);
@@ -121,15 +154,11 @@ static aclnnStatus CheckParams(const aclTensor* self, const aclTensor* other, co
121 // 4. 检查self和other是否broadcast,如可以求broadcast之后的shape154 // 4. 检查self和other是否broadcast,如可以求broadcast之后的shape
122 CHECK_RET(CheckBroadcastLogAddExp(self, other, out), ACLNN_ERR_PARAM_INVALID);155 CHECK_RET(CheckBroadcastLogAddExp(self, other, out), ACLNN_ERR_PARAM_INVALID);
123 156 
124- return ACLNN_SUCCESS;157+ if (IsRegBase()) {
125-}158+ CHECK_RET(CheckFormat(self, other, out), ACLNN_ERR_PARAM_INVALID);
159+ }
126 160 
127-static void CheckFormat(const aclTensor* self, const aclTensor* target){161+ return ACLNN_SUCCESS;
128- ge::Format selfStorageFormat = self->GetStorageFormat();
129- ge::Format targetStorageFormat = target->GetStorageFormat();
130- if (selfStorageFormat != ge::Format::FORMAT_ND || targetStorageFormat != ge::Format::FORMAT_ND){
131- OP_LOGW("aclnnLogAddExp only support format ND.");
132- }
133}162}
134 163 
135aclnnStatus aclnnLogAddExpGetWorkspaceSize(const aclTensor* self, const aclTensor* other, aclTensor* out,164aclnnStatus aclnnLogAddExpGetWorkspaceSize(const aclTensor* self, const aclTensor* other, aclTensor* out,
@@ -145,7 +174,9 @@ aclnnStatus aclnnLogAddExpGetWorkspaceSize(const aclTensor* self, const aclTenso
145 auto ret = CheckParams(self, other, out);174 auto ret = CheckParams(self, other, out);
146 CHECK_RET(ret == ACLNN_SUCCESS, ret);175 CHECK_RET(ret == ACLNN_SUCCESS, ret);
147 176 
148- CheckFormat(self, other);177+ if (!IsRegBase()) {
178+ WarnFormat(self, other);
179+ }
149 180 
150 // 算子的空tensor在kernel中支持,对标竞品根据算子实际情况补充181 // 算子的空tensor在kernel中支持,对标竞品根据算子实际情况补充
151 if (self->IsEmpty() || other->IsEmpty()) {182 if (self->IsEmpty() || other->IsEmpty()) {
@@ -38,6 +38,7 @@ namespace LogAddExpOp {
38constexpr int CAST_NONE_MODE = 0;38constexpr int CAST_NONE_MODE = 0;
39constexpr int CAST_RINT_MODE = 1;39constexpr int CAST_RINT_MODE = 1;
40constexpr int CMP_EQ_MODE = 2; // AscendC::CMPMODE::EQ40constexpr int CMP_EQ_MODE = 2; // AscendC::CMPMODE::EQ
41+constexpr int CMP_NE_MODE = 5; // AscendC::CMPMODE::NE
41constexpr int SEL_TT_MODE = 2; // AscendC::SELMODE::VSEL_TENSOR_TENSOR_MODE42constexpr int SEL_TT_MODE = 2; // AscendC::SELMODE::VSEL_TENSOR_TENSOR_MODE
42constexpr float POS_INF = INFINITY;43constexpr float POS_INF = INFINITY;
43constexpr float NEG_INF = -INFINITY;44constexpr float NEG_INF = -INFINITY;
@@ -58,6 +59,24 @@ struct InfGuardedSub {
58 using SubFixed = Bind<Vec::Select<uint8_t, CT, SEL_TT_MODE>, MaskBothNeg, DupZero, SubFixPos>;59 using SubFixed = Bind<Vec::Select<uint8_t, CT, SEL_TT_MODE>, MaskBothNeg, DupZero, SubFixPos>;
59};60};
60 61 
62+// 稳定计算 log1p(x),避免 x 很小时 1+x 舍入为 1 导致结果变 0。
63+template <typename CT, typename In>
64+struct StableLog1p {
65+ using ConstOne = MAKE_CONST(CT, 1);
66+ using ConstNegOne = MAKE_CONST(CT, -1);
67+ using OpAddOne = Bind<Vec::Adds<CT>, In, ConstOne>;
68+ using OpMid = Bind<Vec::Adds<CT>, OpAddOne, ConstNegOne>;
69+ using OpRatio = Bind<Vec::Div<CT>, In, OpMid>;
70+ using OpLog = Bind<Vec::Log<CT>, OpAddOne>;
71+ using OpMul = Bind<Vec::Mul<CT>, OpLog, OpRatio>;
72+ using MaskNotOne = Bind<Vec::Compare<uint8_t, CT, CMP_NE_MODE>, OpAddOne, ConstOne>;
73+ using FixSmall = Bind<Vec::Select<uint8_t, CT, SEL_TT_MODE>, MaskNotOne, OpMul, In>;
74+ using ConstPosInf = MAKE_CONST(CT, POS_INF);
75+ using DupPosInf = Bind<Vec::Duplicate<CT>, ConstPosInf>;
76+ using MaskNotInf = Bind<Vec::Compare<uint8_t, CT, CMP_NE_MODE>, OpAddOne, ConstPosInf>;
77+ using OpOut = Bind<Vec::Select<uint8_t, CT, SEL_TT_MODE>, MaskNotInf, FixSmall, DupPosInf>;
78+};
79+ 
61// ==================== Simplified (base=-1, scale=1.0, shift=0.0) ====================80// ==================== Simplified (base=-1, scale=1.0, shift=0.0) ====================
62 81 
63template <typename T>82template <typename T>
@@ -71,9 +90,7 @@ struct LogAddExpSimplifiedCompute {
71 using ConstNegOne = MAKE_CONST(T, -1);90 using ConstNegOne = MAKE_CONST(T, -1);
72 using OpNeg = Bind<Vec::Muls<T>, OpAbs, ConstNegOne>;91 using OpNeg = Bind<Vec::Muls<T>, OpAbs, ConstNegOne>;
73 using OpExp = Bind<Vec::Exp<T>, OpNeg>;92 using OpExp = Bind<Vec::Exp<T>, OpNeg>;
74- using ConstOne = MAKE_CONST(T, 1);93+ using OpLog = typename StableLog1p<T, OpExp>::OpOut;
75- using OpAdds = Bind<Vec::Adds<T>, OpExp, ConstOne>;
76- using OpLog = Bind<Vec::Log<T>, OpAdds>;
77 using OpAdd = Bind<Vec::Add<T>, OpMax, OpLog>;94 using OpAdd = Bind<Vec::Add<T>, OpMax, OpLog>;
78 95 
79 using OpCopyOut = Bind<Vec::CopyOut<T>, Placeholder::Out0<T>, OpAdd>;96 using OpCopyOut = Bind<Vec::CopyOut<T>, Placeholder::Out0<T>, OpAdd>;
@@ -97,9 +114,7 @@ struct LogAddExpSimplifiedWithCastCompute {
97 using ConstNegOne = MAKE_CONST(float, -1);114 using ConstNegOne = MAKE_CONST(float, -1);
98 using OpNeg = Bind<Vec::Muls<float>, OpAbs, ConstNegOne>;115 using OpNeg = Bind<Vec::Muls<float>, OpAbs, ConstNegOne>;
99 using OpExp = Bind<Vec::Exp<float>, OpNeg>;116 using OpExp = Bind<Vec::Exp<float>, OpNeg>;
100- using ConstOne = MAKE_CONST(float, 1);117+ using OpLog = typename StableLog1p<float, OpExp>::OpOut;
101- using OpAdds = Bind<Vec::Adds<float>, OpExp, ConstOne>;
102- using OpLog = Bind<Vec::Log<float>, OpAdds>;
103 using OpAdd = Bind<Vec::Add<float>, OpMax, OpLog>;118 using OpAdd = Bind<Vec::Add<float>, OpMax, OpLog>;
104 119 
105 using OpCastRes = Bind<Vec::Cast<T, float, CAST_RINT_MODE>, OpAdd>;120 using OpCastRes = Bind<Vec::Cast<T, float, CAST_RINT_MODE>, OpAdd>;
@@ -128,9 +143,7 @@ struct LogAddExpFullCompute {
128 using VarLnBase = Placeholder::Var<float, 2>;143 using VarLnBase = Placeholder::Var<float, 2>;
129 using OpMulLnBase = Bind<Vec::Muls<T>, OpShift, VarLnBase>;144 using OpMulLnBase = Bind<Vec::Muls<T>, OpShift, VarLnBase>;
130 using OpExp = Bind<Vec::Exp<T>, OpMulLnBase>;145 using OpExp = Bind<Vec::Exp<T>, OpMulLnBase>;
131- using ConstOne = MAKE_CONST(T, 1);146+ using OpLog = typename StableLog1p<T, OpExp>::OpOut;
132- using OpAdds = Bind<Vec::Adds<T>, OpExp, ConstOne>;
133- using OpLog = Bind<Vec::Log<T>, OpAdds>;
134 using VarInvLnBase = Placeholder::Var<float, 3>;147 using VarInvLnBase = Placeholder::Var<float, 3>;
135 using OpMulInvLnBase = Bind<Vec::Muls<T>, OpLog, VarInvLnBase>;148 using OpMulInvLnBase = Bind<Vec::Muls<T>, OpLog, VarInvLnBase>;
136 using OpAdd = Bind<Vec::Add<T>, OpMax, OpMulInvLnBase>;149 using OpAdd = Bind<Vec::Add<T>, OpMax, OpMulInvLnBase>;
@@ -160,9 +173,7 @@ struct LogAddExpFullWithCastCompute {
160 using VarLnBase = Placeholder::Var<float, 2>;173 using VarLnBase = Placeholder::Var<float, 2>;
161 using OpMulLnBase = Bind<Vec::Muls<float>, OpShift, VarLnBase>;174 using OpMulLnBase = Bind<Vec::Muls<float>, OpShift, VarLnBase>;
162 using OpExp = Bind<Vec::Exp<float>, OpMulLnBase>;175 using OpExp = Bind<Vec::Exp<float>, OpMulLnBase>;
163- using ConstOne = MAKE_CONST(float, 1);176+ using OpLog = typename StableLog1p<float, OpExp>::OpOut;
164- using OpAdds = Bind<Vec::Adds<float>, OpExp, ConstOne>;
165- using OpLog = Bind<Vec::Log<float>, OpAdds>;
166 using VarInvLnBase = Placeholder::Var<float, 3>;177 using VarInvLnBase = Placeholder::Var<float, 3>;
167 using OpMulInvLnBase = Bind<Vec::Muls<float>, OpLog, VarInvLnBase>;178 using OpMulInvLnBase = Bind<Vec::Muls<float>, OpLog, VarInvLnBase>;
168 using OpAdd = Bind<Vec::Add<float>, OpMax, OpMulInvLnBase>;179 using OpAdd = Bind<Vec::Add<float>, OpMax, OpMulInvLnBase>;