diff options
-rw-r--r-- | include/attribute.def | 5 | ||||
-rw-r--r-- | include/cfloat.h | 44 | ||||
-rw-r--r-- | include/tosa_generated.h | 52 | ||||
-rw-r--r-- | python/serializer/tosa_serializer.py | 10 | ||||
-rw-r--r-- | python/tosa/ResizeAttribute.py | 117 | ||||
-rw-r--r-- | schema/tosa.fbs | 6 | ||||
-rw-r--r-- | src/tosa_serialization_handler.cpp | 18 | ||||
m--------- | third_party/flatbuffers | 0 |
8 files changed, 50 insertions, 202 deletions
diff --git a/include/attribute.def b/include/attribute.def index 0e97629..52d5179 100644 --- a/include/attribute.def +++ b/include/attribute.def @@ -57,10 +57,7 @@ DEF_ATTRIBUTE(Pad, 1, DEF_ATTRIBUTE(Axis, 1, int32_t, S, axis) -DEF_ATTRIBUTE(Resize, 4, - int16_t, V, scale, - int16_t, V, offset, - int16_t, V, border, +DEF_ATTRIBUTE(Resize, 1, ResizeMode, S, mode) DEF_ATTRIBUTE(Clamp, 2, diff --git a/include/cfloat.h b/include/cfloat.h index 0cf4896..cbbe09a 100644 --- a/include/cfloat.h +++ b/include/cfloat.h @@ -211,10 +211,33 @@ public: if (in.is_nan() || in.is_infinity()) { + // The mapping of infinity to the destination type depends upon + // the overflow mode and the features of the destination type. + // OVERFLOW mode is the "expected" behaviour, in which exception + // values (NaN and infinity) map to themselves in the + // destination type (assuming they exist). In SATURATION mode, + // infinity maps to the largest absolute value of the + // destination type _even if_ an infinity encoding is available. + // See the FP8 specification document. + // + // By default, exceptional values are encoded with an all-1 + // exponent field. new_exponent_bits = (UINT64_C(1) << out_exp_bits) - 1; if (in.is_nan()) { + // NaN always maps to NaN if it's available. + // + // NB: if the type has both NaN AND Infinity support, then + // the entirety of the significand can be used to encode + // different values of NaN (excepting significand = 0, + // which is reserved for infinity). This makes it possible + // to encode both quiet and signalling varieties. + // Generally, the LSB of the significand represents "not + // quiet". However, when there is only 1 NaN encoding + // (which is generally the case when infinity is not + // supported), then there cannot be separate quiet and + // signalling varieties of NaN. if constexpr (out_type::has_inf) { // Copy across the `not_quiet bit`; set the LSB. @@ -228,17 +251,18 @@ public: new_significand = (UINT64_C(1) << out_type::n_significand_bits) - 1; } } - else if constexpr (out_type::has_inf && overflow_mode == OverflowMode::Saturate) + else if constexpr (overflow_mode == OverflowMode::Saturate) { - new_exponent_bits -= 1; - new_significand = (UINT64_C(1) << out_type::n_significand_bits) - 1; - } - else if constexpr (!out_type::has_inf && overflow_mode == OverflowMode::Saturate) - { - new_significand = (UINT64_C(1) << out_type::n_significand_bits) - (out_type::has_nan ? 2 : 1); + // In SATURATE mode, infinity in the input maps to the + // largest absolute value in the output type; even if + // infinity is available. This is in compliance with Table 3 + // of the FP8 specification. + return out_type::max(sign_bit); } else if constexpr (!out_type::has_inf && overflow_mode == OverflowMode::Overflow) { + // In OVERFLOW mode, infinities in the input type map to NaN + // in the output type, if infinity is not available. new_significand = (UINT64_C(1) << out_type::n_significand_bits) - 1; } } @@ -492,20 +516,20 @@ public: { // Where we have NaN and Infinity, exponents all `1` corresponds // to some of these values. - return from_bits(false, (UINT64_C(1) << n_exponent_bits) - 2, (UINT64_C(1) << n_significand_bits) - 1); + return from_bits(sign, (UINT64_C(1) << n_exponent_bits) - 2, (UINT64_C(1) << n_significand_bits) - 1); } else if constexpr (has_nan || has_inf) { // Where we have either NaN or infinity (but not both), // exponents all `1` AND significand all `1` corresponds to the // special value. - return from_bits(false, (UINT64_C(1) << n_exponent_bits) - 1, (UINT64_C(1) << n_significand_bits) - 2); + return from_bits(sign, (UINT64_C(1) << n_exponent_bits) - 1, (UINT64_C(1) << n_significand_bits) - 2); } else { // With no special values to encode, the maximum value is // encoded as all `1`s. - return from_bits(false, (UINT64_C(1) << n_exponent_bits) - 1, (UINT64_C(1) << n_significand_bits) - 1); + return from_bits(sign, (UINT64_C(1) << n_exponent_bits) - 1, (UINT64_C(1) << n_significand_bits) - 1); } } diff --git a/include/tosa_generated.h b/include/tosa_generated.h index c907c89..a215891 100644 --- a/include/tosa_generated.h +++ b/include/tosa_generated.h @@ -10,7 +10,7 @@ // generated, otherwise it may not be compatible. static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && FLATBUFFERS_VERSION_MINOR == 3 && - FLATBUFFERS_VERSION_REVISION == 7, + FLATBUFFERS_VERSION_REVISION == 25, "Non-compatible flatbuffers version included"); namespace tosa { @@ -1087,31 +1087,13 @@ inline ::flatbuffers::Offset<AxisAttribute> CreateAxisAttribute( struct ResizeAttribute FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { typedef ResizeAttributeBuilder Builder; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_SCALE = 4, - VT_OFFSET = 6, - VT_BORDER = 8, VT_MODE = 10 }; - const ::flatbuffers::Vector<int16_t> *scale() const { - return GetPointer<const ::flatbuffers::Vector<int16_t> *>(VT_SCALE); - } - const ::flatbuffers::Vector<int16_t> *offset() const { - return GetPointer<const ::flatbuffers::Vector<int16_t> *>(VT_OFFSET); - } - const ::flatbuffers::Vector<int16_t> *border() const { - return GetPointer<const ::flatbuffers::Vector<int16_t> *>(VT_BORDER); - } tosa::ResizeMode mode() const { return static_cast<tosa::ResizeMode>(GetField<uint32_t>(VT_MODE, 0)); } bool Verify(::flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_SCALE) && - verifier.VerifyVector(scale()) && - VerifyOffset(verifier, VT_OFFSET) && - verifier.VerifyVector(offset()) && - VerifyOffset(verifier, VT_BORDER) && - verifier.VerifyVector(border()) && VerifyField<uint32_t>(verifier, VT_MODE, 4) && verifier.EndTable(); } @@ -1121,15 +1103,6 @@ struct ResizeAttributeBuilder { typedef ResizeAttribute Table; ::flatbuffers::FlatBufferBuilder &fbb_; ::flatbuffers::uoffset_t start_; - void add_scale(::flatbuffers::Offset<::flatbuffers::Vector<int16_t>> scale) { - fbb_.AddOffset(ResizeAttribute::VT_SCALE, scale); - } - void add_offset(::flatbuffers::Offset<::flatbuffers::Vector<int16_t>> offset) { - fbb_.AddOffset(ResizeAttribute::VT_OFFSET, offset); - } - void add_border(::flatbuffers::Offset<::flatbuffers::Vector<int16_t>> border) { - fbb_.AddOffset(ResizeAttribute::VT_BORDER, border); - } void add_mode(tosa::ResizeMode mode) { fbb_.AddElement<uint32_t>(ResizeAttribute::VT_MODE, static_cast<uint32_t>(mode), 0); } @@ -1146,35 +1119,12 @@ struct ResizeAttributeBuilder { inline ::flatbuffers::Offset<ResizeAttribute> CreateResizeAttribute( ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::Vector<int16_t>> scale = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<int16_t>> offset = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<int16_t>> border = 0, tosa::ResizeMode mode = tosa::ResizeMode_UNKNOWN) { ResizeAttributeBuilder builder_(_fbb); builder_.add_mode(mode); - builder_.add_border(border); - builder_.add_offset(offset); - builder_.add_scale(scale); return builder_.Finish(); } -inline ::flatbuffers::Offset<ResizeAttribute> CreateResizeAttributeDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const std::vector<int16_t> *scale = nullptr, - const std::vector<int16_t> *offset = nullptr, - const std::vector<int16_t> *border = nullptr, - tosa::ResizeMode mode = tosa::ResizeMode_UNKNOWN) { - auto scale__ = scale ? _fbb.CreateVector<int16_t>(*scale) : 0; - auto offset__ = offset ? _fbb.CreateVector<int16_t>(*offset) : 0; - auto border__ = border ? _fbb.CreateVector<int16_t>(*border) : 0; - return tosa::CreateResizeAttribute( - _fbb, - scale__, - offset__, - border__, - mode); -} - struct ClampAttribute FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { typedef ClampAttributeBuilder Builder; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { diff --git a/python/serializer/tosa_serializer.py b/python/serializer/tosa_serializer.py index 7122216..c417fce 100644 --- a/python/serializer/tosa_serializer.py +++ b/python/serializer/tosa_serializer.py @@ -225,15 +225,12 @@ class TosaSerializerAttribute(TosaSerializerUnion): self.ints.append((a.AddAxis, axis)) - def ResizeAttribute(self, scale, offset, border, mode): + def ResizeAttribute(self, mode): from tosa import ResizeAttribute as a, Attribute self.utype = Attribute.Attribute().ResizeAttribute self.optFcns = (a.Start, a.End) - self.int16vecs.append((a.AddScale, scale)) - self.int16vecs.append((a.AddOffset, offset)) - self.int16vecs.append((a.AddBorder, border)) self.ints.append((a.AddMode, mode)) def ClampAttribute(self, serializer_builder, min_val_as_bytes, max_val_as_bytes): @@ -947,9 +944,8 @@ class TosaSerializer: np_arr = np.array(data, dtype=np.float32) u8_data.extend(np_arr.view(np.uint8)) elif dtype == DType.BF16: - for val in data: - np_arr = np.array(data, dtype=bfloat16) - u8_data.extend(np_arr.view(np.uint8)) + np_arr = np.array(data, dtype=bfloat16) + u8_data.extend(np_arr.view(np.uint8)) elif dtype == DType.FP8E4M3: for val in data: val_f8 = np.array(val).astype(float8_e4m3fn).view(np.uint8) diff --git a/python/tosa/ResizeAttribute.py b/python/tosa/ResizeAttribute.py index 44f7d31..f2a6992 100644 --- a/python/tosa/ResizeAttribute.py +++ b/python/tosa/ResizeAttribute.py @@ -29,87 +29,6 @@ class ResizeAttribute(object): self._tab = flatbuffers.table.Table(buf, pos) # ResizeAttribute - def Scale(self, j): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) - if o != 0: - a = self._tab.Vector(o) - return self._tab.Get(flatbuffers.number_types.Int16Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 2)) - return 0 - - # ResizeAttribute - def ScaleAsNumpy(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) - if o != 0: - return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int16Flags, o) - return 0 - - # ResizeAttribute - def ScaleLength(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) - if o != 0: - return self._tab.VectorLen(o) - return 0 - - # ResizeAttribute - def ScaleIsNone(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) - return o == 0 - - # ResizeAttribute - def Offset(self, j): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6)) - if o != 0: - a = self._tab.Vector(o) - return self._tab.Get(flatbuffers.number_types.Int16Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 2)) - return 0 - - # ResizeAttribute - def OffsetAsNumpy(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6)) - if o != 0: - return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int16Flags, o) - return 0 - - # ResizeAttribute - def OffsetLength(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6)) - if o != 0: - return self._tab.VectorLen(o) - return 0 - - # ResizeAttribute - def OffsetIsNone(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6)) - return o == 0 - - # ResizeAttribute - def Border(self, j): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) - if o != 0: - a = self._tab.Vector(o) - return self._tab.Get(flatbuffers.number_types.Int16Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 2)) - return 0 - - # ResizeAttribute - def BorderAsNumpy(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) - if o != 0: - return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int16Flags, o) - return 0 - - # ResizeAttribute - def BorderLength(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) - if o != 0: - return self._tab.VectorLen(o) - return 0 - - # ResizeAttribute - def BorderIsNone(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) - return o == 0 - - # ResizeAttribute def Mode(self): o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10)) if o != 0: @@ -122,42 +41,6 @@ def ResizeAttributeStart(builder): def Start(builder): ResizeAttributeStart(builder) -def ResizeAttributeAddScale(builder, scale): - builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(scale), 0) - -def AddScale(builder, scale): - ResizeAttributeAddScale(builder, scale) - -def ResizeAttributeStartScaleVector(builder, numElems): - return builder.StartVector(2, numElems, 2) - -def StartScaleVector(builder, numElems): - return ResizeAttributeStartScaleVector(builder, numElems) - -def ResizeAttributeAddOffset(builder, offset): - builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(offset), 0) - -def AddOffset(builder, offset): - ResizeAttributeAddOffset(builder, offset) - -def ResizeAttributeStartOffsetVector(builder, numElems): - return builder.StartVector(2, numElems, 2) - -def StartOffsetVector(builder, numElems): - return ResizeAttributeStartOffsetVector(builder, numElems) - -def ResizeAttributeAddBorder(builder, border): - builder.PrependUOffsetTRelativeSlot(2, flatbuffers.number_types.UOffsetTFlags.py_type(border), 0) - -def AddBorder(builder, border): - ResizeAttributeAddBorder(builder, border) - -def ResizeAttributeStartBorderVector(builder, numElems): - return builder.StartVector(2, numElems, 2) - -def StartBorderVector(builder, numElems): - return ResizeAttributeStartBorderVector(builder, numElems) - def ResizeAttributeAddMode(builder, mode): builder.PrependUint32Slot(3, mode, 0) diff --git a/schema/tosa.fbs b/schema/tosa.fbs index cad6db7..1a2d952 100644 --- a/schema/tosa.fbs +++ b/schema/tosa.fbs @@ -191,9 +191,9 @@ table AxisAttribute { } table ResizeAttribute { - scale: [int16]; - offset: [int16]; - border: [int16]; + scale: [int16] (deprecated); + offset: [int16] (deprecated); + border: [int16] (deprecated); mode: ResizeMode; } diff --git a/src/tosa_serialization_handler.cpp b/src/tosa_serialization_handler.cpp index 76b2198..74f66d8 100644 --- a/src/tosa_serialization_handler.cpp +++ b/src/tosa_serialization_handler.cpp @@ -940,7 +940,6 @@ tosa_err_t TosaSerializationHandler::ConvertBooltoU8(const std::vector<bool>& in tosa_err_t TosaSerializationHandler::ConvertU8toBF16(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<bf16>& out) { - // Note: bf16 values returned in fp32 type out.clear(); if (in.size() < out_size * sizeof(int16_t)) { @@ -951,13 +950,12 @@ tosa_err_t for (uint32_t i = 0; i < out_size; i++) { - uint32_t f32_byte2 = in[i * sizeof(int16_t)]; - uint32_t f32_byte3 = in[i * sizeof(int16_t) + 1]; - uint32_t val_u32 = (f32_byte2 << 16) + (f32_byte3 << 24); + uint8_t bf16_byte0 = in[i * sizeof(int16_t)]; + uint8_t bf16_byte1 = in[i * sizeof(int16_t) + 1]; + uint16_t val_u16 = (bf16_byte0) + (bf16_byte1 << 8); - // Reinterpret u32 bytes as fp32 - float val_f32 = *(float*)&val_u32; - float val_bf16 = static_cast<bf16>(val_f32); + // Reinterpret u16 bytes as bf16 + bf16 val_bf16 = *(bf16*)&val_u16; out.push_back(val_bf16); } return TOSA_OK; @@ -1021,9 +1019,9 @@ tosa_err_t TosaSerializationHandler::ConvertU8toF16(const std::vector<uint8_t>& for (uint32_t i = 0; i < out_size; i++) { - uint16_t f16_byte0 = in[i * sizeof(int16_t)]; - uint16_t f16_byte1 = in[i * sizeof(int16_t) + 1]; - uint16_t val_u16 = f16_byte0 + (f16_byte1 << 8); + uint8_t f16_byte0 = in[i * sizeof(int16_t)]; + uint8_t f16_byte1 = in[i * sizeof(int16_t) + 1]; + uint16_t val_u16 = f16_byte0 + (f16_byte1 << 8); // Reinterpret u16 byte as fp16 then convert to fp32 half_float::half val_f16 = *(half_float::half*)&val_u16; diff --git a/third_party/flatbuffers b/third_party/flatbuffers -Subproject 6ff9e90e7e399f3977e99a315856b57c8afe5b4 +Subproject 595bf0007ab1929570c7671f091313c8fc20644 |