已合并
修改log_add_exp小值域情况下精度误差 #3631
zhangqijia1创建于 6月29日
修改log_add_exp小值域情况下精度误差 #3631
已合并
共 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 | + | ||
| 111 | static aclnnStatus CheckParams(const aclTensor* self, const aclTensor* other, const aclTensor* out) { | 144 | static 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之后的shape | 154 | // 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 | ||
| 135 | aclnnStatus aclnnLogAddExpGetWorkspaceSize(const aclTensor* self, const aclTensor* other, aclTensor* out, | 164 | aclnnStatus 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 { | |||
| 38 | constexpr int CAST_NONE_MODE = 0; | 38 | constexpr int CAST_NONE_MODE = 0; |
| 39 | constexpr int CAST_RINT_MODE = 1; | 39 | constexpr int CAST_RINT_MODE = 1; |
| 40 | constexpr int CMP_EQ_MODE = 2; // AscendC::CMPMODE::EQ | 40 | constexpr int CMP_EQ_MODE = 2; // AscendC::CMPMODE::EQ |
| 41 | +constexpr int CMP_NE_MODE = 5; // AscendC::CMPMODE::NE | ||
| 41 | constexpr int SEL_TT_MODE = 2; // AscendC::SELMODE::VSEL_TENSOR_TENSOR_MODE | 42 | constexpr int SEL_TT_MODE = 2; // AscendC::SELMODE::VSEL_TENSOR_TENSOR_MODE |
| 42 | constexpr float POS_INF = INFINITY; | 43 | constexpr float POS_INF = INFINITY; |
| 43 | constexpr float NEG_INF = -INFINITY; | 44 | constexpr 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 | ||
| 63 | template <typename T> | 82 | template <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>; |