diff options
-rw-r--r-- | include/attribute.h | 30 | ||||
-rw-r--r-- | include/tosa_generated.h | 63 | ||||
-rw-r--r-- | python/serializer/tosa_serializer.py | 38 | ||||
-rw-r--r-- | python/tosa/ClampAttribute.py | 62 | ||||
-rw-r--r-- | python/tosa/PadAttribute.py | 31 | ||||
-rw-r--r-- | schema/tosa.fbs | 6 | ||||
-rw-r--r-- | src/tosa_serialization_handler.cpp | 12 |
7 files changed, 196 insertions, 46 deletions
diff --git a/include/attribute.h b/include/attribute.h index 1178ee4..5371130 100644 --- a/include/attribute.h +++ b/include/attribute.h @@ -40,11 +40,39 @@ public: {} }; +inline int convertFlatbuffersU8toF32(const flatbuffers::Vector<uint8_t>& in, uint32_t out_size, std::vector<float>& out) +{ + out.clear(); + if (in.size() < out_size * sizeof(float)) + { + printf("convertFlatbuffersU8toF32(): uint8 Flatbuffers buffer size %u must be >= target size %ld\n", in.size(), + out_size * sizeof(float)); + return 1; + } + for (uint32_t i = 0; i < out_size; i++) + { + uint32_t byte0 = in[i * sizeof(float)]; + uint32_t byte1 = in[i * sizeof(float) + 1]; + uint32_t byte2 = in[i * sizeof(float) + 2]; + uint32_t byte3 = in[i * sizeof(float) + 3]; + uint32_t val_u32 = byte0 + (byte1 << 8) + (byte2 << 16) + (byte3 << 24); + float* val_fp32 = reinterpret_cast<float*>(&val_u32); + out.push_back(*val_fp32); + } + return 0; +} + #define DEF_ARGS_VER0_S_STR(V) _##V = p->V()->str(); #define DEF_ARGS_VER0_S_DEFAULT(V) _##V = p->V(); +#define DEF_ARGS_VER0_S_float_as_bytes(V) \ + { \ + std::vector<float> attr_vec; \ + assert(!convertFlatbuffersU8toF32(*(p->V()), 1, attr_vec)); \ + _##V = attr_vec[0]; \ + } #define DEF_ARGS_VER0_S_int32_t(V) DEF_ARGS_VER0_S_DEFAULT(V) -#define DEF_ARGS_VER0_S_float(V) DEF_ARGS_VER0_S_DEFAULT(V) +#define DEF_ARGS_VER0_S_float(V) DEF_ARGS_VER0_S_float_as_bytes(V) #define DEF_ARGS_VER0_S_bool(V) DEF_ARGS_VER0_S_DEFAULT(V) #define DEF_ARGS_VER0_S_ResizeMode(V) DEF_ARGS_VER0_S_DEFAULT(V) #define DEF_ARGS_VER0_S_DType(V) DEF_ARGS_VER0_S_DEFAULT(V) diff --git a/include/tosa_generated.h b/include/tosa_generated.h index 1a79453..b34875f 100644 --- a/include/tosa_generated.h +++ b/include/tosa_generated.h @@ -968,15 +968,16 @@ struct PadAttribute FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { int32_t pad_const_int() const { return GetField<int32_t>(VT_PAD_CONST_INT, 0); } - float pad_const_fp() const { - return GetField<float>(VT_PAD_CONST_FP, 0.0f); + const flatbuffers::Vector<uint8_t> *pad_const_fp() const { + return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_PAD_CONST_FP); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_PADDING) && verifier.VerifyVector(padding()) && VerifyField<int32_t>(verifier, VT_PAD_CONST_INT, 4) && - VerifyField<float>(verifier, VT_PAD_CONST_FP, 4) && + VerifyOffset(verifier, VT_PAD_CONST_FP) && + verifier.VerifyVector(pad_const_fp()) && verifier.EndTable(); } }; @@ -991,8 +992,8 @@ struct PadAttributeBuilder { void add_pad_const_int(int32_t pad_const_int) { fbb_.AddElement<int32_t>(PadAttribute::VT_PAD_CONST_INT, pad_const_int, 0); } - void add_pad_const_fp(float pad_const_fp) { - fbb_.AddElement<float>(PadAttribute::VT_PAD_CONST_FP, pad_const_fp, 0.0f); + void add_pad_const_fp(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> pad_const_fp) { + fbb_.AddOffset(PadAttribute::VT_PAD_CONST_FP, pad_const_fp); } explicit PadAttributeBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { @@ -1009,7 +1010,7 @@ inline flatbuffers::Offset<PadAttribute> CreatePadAttribute( flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<flatbuffers::Vector<int32_t>> padding = 0, int32_t pad_const_int = 0, - float pad_const_fp = 0.0f) { + flatbuffers::Offset<flatbuffers::Vector<uint8_t>> pad_const_fp = 0) { PadAttributeBuilder builder_(_fbb); builder_.add_pad_const_fp(pad_const_fp); builder_.add_pad_const_int(pad_const_int); @@ -1021,13 +1022,15 @@ inline flatbuffers::Offset<PadAttribute> CreatePadAttributeDirect( flatbuffers::FlatBufferBuilder &_fbb, const std::vector<int32_t> *padding = nullptr, int32_t pad_const_int = 0, - float pad_const_fp = 0.0f) { + const std::vector<uint8_t> *pad_const_fp = nullptr) { auto padding__ = padding ? _fbb.CreateVector<int32_t>(*padding) : 0; + if (pad_const_fp) { _fbb.ForceVectorAlignment(pad_const_fp->size(), sizeof(uint8_t), 8); } + auto pad_const_fp__ = pad_const_fp ? _fbb.CreateVector<uint8_t>(*pad_const_fp) : 0; return tosa::CreatePadAttribute( _fbb, padding__, pad_const_int, - pad_const_fp); + pad_const_fp__); } struct AxisAttribute FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { @@ -1343,18 +1346,20 @@ struct ClampAttribute FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { int32_t max_int() const { return GetField<int32_t>(VT_MAX_INT, 0); } - float min_fp() const { - return GetField<float>(VT_MIN_FP, 0.0f); + const flatbuffers::Vector<uint8_t> *min_fp() const { + return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_MIN_FP); } - float max_fp() const { - return GetField<float>(VT_MAX_FP, 0.0f); + const flatbuffers::Vector<uint8_t> *max_fp() const { + return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_MAX_FP); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_MIN_INT, 4) && VerifyField<int32_t>(verifier, VT_MAX_INT, 4) && - VerifyField<float>(verifier, VT_MIN_FP, 4) && - VerifyField<float>(verifier, VT_MAX_FP, 4) && + VerifyOffset(verifier, VT_MIN_FP) && + verifier.VerifyVector(min_fp()) && + VerifyOffset(verifier, VT_MAX_FP) && + verifier.VerifyVector(max_fp()) && verifier.EndTable(); } }; @@ -1369,11 +1374,11 @@ struct ClampAttributeBuilder { void add_max_int(int32_t max_int) { fbb_.AddElement<int32_t>(ClampAttribute::VT_MAX_INT, max_int, 0); } - void add_min_fp(float min_fp) { - fbb_.AddElement<float>(ClampAttribute::VT_MIN_FP, min_fp, 0.0f); + void add_min_fp(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> min_fp) { + fbb_.AddOffset(ClampAttribute::VT_MIN_FP, min_fp); } - void add_max_fp(float max_fp) { - fbb_.AddElement<float>(ClampAttribute::VT_MAX_FP, max_fp, 0.0f); + void add_max_fp(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> max_fp) { + fbb_.AddOffset(ClampAttribute::VT_MAX_FP, max_fp); } explicit ClampAttributeBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { @@ -1390,8 +1395,8 @@ inline flatbuffers::Offset<ClampAttribute> CreateClampAttribute( flatbuffers::FlatBufferBuilder &_fbb, int32_t min_int = 0, int32_t max_int = 0, - float min_fp = 0.0f, - float max_fp = 0.0f) { + flatbuffers::Offset<flatbuffers::Vector<uint8_t>> min_fp = 0, + flatbuffers::Offset<flatbuffers::Vector<uint8_t>> max_fp = 0) { ClampAttributeBuilder builder_(_fbb); builder_.add_max_fp(max_fp); builder_.add_min_fp(min_fp); @@ -1400,6 +1405,24 @@ inline flatbuffers::Offset<ClampAttribute> CreateClampAttribute( return builder_.Finish(); } +inline flatbuffers::Offset<ClampAttribute> CreateClampAttributeDirect( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t min_int = 0, + int32_t max_int = 0, + const std::vector<uint8_t> *min_fp = nullptr, + const std::vector<uint8_t> *max_fp = nullptr) { + if (min_fp) { _fbb.ForceVectorAlignment(min_fp->size(), sizeof(uint8_t), 8); } + auto min_fp__ = min_fp ? _fbb.CreateVector<uint8_t>(*min_fp) : 0; + if (max_fp) { _fbb.ForceVectorAlignment(max_fp->size(), sizeof(uint8_t), 8); } + auto max_fp__ = max_fp ? _fbb.CreateVector<uint8_t>(*max_fp) : 0; + return tosa::CreateClampAttribute( + _fbb, + min_int, + max_int, + min_fp__, + max_fp__); +} + struct RescaleAttribute FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { typedef RescaleAttributeBuilder Builder; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { diff --git a/python/serializer/tosa_serializer.py b/python/serializer/tosa_serializer.py index e8311ce..f579df2 100644 --- a/python/serializer/tosa_serializer.py +++ b/python/serializer/tosa_serializer.py @@ -13,10 +13,11 @@ # limitations under the License. import os +import struct +import serializer.tosa_serializer as ts import json import flatbuffers import numpy as np -import struct from enum import IntEnum, unique from tosa import ( TosaGraph, @@ -197,7 +198,7 @@ class TosaSerializerAttribute(TosaSerializerUnion): self.ints.append((a.AddWeightZp, weight_zp)) self.ints.append((a.AddAccumDtype, accum_dtype)) - def PadAttribute(self, padding, pad_const_int, pad_const_fp): + def PadAttribute(self, serializer_builder, padding, pad_const_int, pad_const_fp): from tosa import PadAttribute as a, Attribute self.utype = Attribute.Attribute().PadAttribute @@ -205,7 +206,14 @@ class TosaSerializerAttribute(TosaSerializerUnion): self.intvecs.append((a.AddPadding, padding)) self.ints.append((a.AddPadConstInt, pad_const_int)) - self.floats.append((a.AddPadConstFp, pad_const_fp)) + + # pad_const_fp attribute serialized as uint8 vector + pad_const_float_as_bytes = struct.pack("<f", pad_const_fp) + serialized_pad_const_fp = ts.TosaSerializer.serializeUint8Vec( + serializer_builder, pad_const_float_as_bytes + ) + + self.floats.append((a.AddPadConstFp, serialized_pad_const_fp)) def AxisAttribute(self, axis): from tosa import AxisAttribute as a, Attribute @@ -251,7 +259,7 @@ class TosaSerializerAttribute(TosaSerializerUnion): self.int16vecs.append((a.AddBorder, border)) self.ints.append((a.AddMode, mode)) - def ClampAttribute(self, minint, maxint, minfp, maxfp): + def ClampAttribute(self, serializer_builder, minint, maxint, minfp, maxfp): from tosa import ClampAttribute as a, Attribute self.utype = Attribute.Attribute().ClampAttribute @@ -260,8 +268,18 @@ class TosaSerializerAttribute(TosaSerializerUnion): self.ints.append((a.AddMinInt, minint)) self.ints.append((a.AddMaxInt, maxint)) - self.ints.append((a.AddMinFp, minfp)) - self.ints.append((a.AddMaxFp, maxfp)) + # min/max float attributes serialized as uint8 vectors + minfp_bytes = struct.pack("<f", minfp) + maxfp_bytes = struct.pack("<f", maxfp) + serialized_minfp_bytes = ts.TosaSerializer.serializeUint8Vec( + serializer_builder, minfp_bytes + ) + serialized_maxfp_bytes = ts.TosaSerializer.serializeUint8Vec( + serializer_builder, maxfp_bytes + ) + + self.floats.append((a.AddMinFp, serialized_minfp_bytes)) + self.floats.append((a.AddMaxFp, serialized_maxfp_bytes)) def RescaleAttribute( self, input_zp, output_zp, multiplier, shift, scale32, double_round, per_channel @@ -477,9 +495,11 @@ class TosaSerializerTensor: np_arr = np.array(self.data, dtype=np.float16) u8_data.extend(np_arr.view(np.uint8)) elif self.dtype == DType.FP32 or self.dtype == DType.BF16: - for val in self.data: - b = struct.pack("!f", val) - u8_data.extend([b[3], b[2], b[1], b[0]]) + # for val in self.data: + # b = struct.pack("!f", val) + # u8_data.extend([b[3], b[2], b[1], b[0]]) + np_arr = np.array(self.data, dtype=np.float32) + u8_data.extend(np_arr.view(np.uint8)) elif self.dtype == TosaDType.DType: # Serialize DType enum data as uint8 bytes for val in self.data: diff --git a/python/tosa/ClampAttribute.py b/python/tosa/ClampAttribute.py index 58d1f0a..7937944 100644 --- a/python/tosa/ClampAttribute.py +++ b/python/tosa/ClampAttribute.py @@ -43,18 +43,58 @@ class ClampAttribute(object): return 0 # ClampAttribute - def MinFp(self): + def MinFp(self, j): o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) if o != 0: - return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) - return 0.0 + a = self._tab.Vector(o) + return self._tab.Get(flatbuffers.number_types.Uint8Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1)) + return 0 + + # ClampAttribute + def MinFpAsNumpy(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) + if o != 0: + return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint8Flags, o) + return 0 + + # ClampAttribute + def MinFpLength(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) + if o != 0: + return self._tab.VectorLen(o) + return 0 + + # ClampAttribute + def MinFpIsNone(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) + return o == 0 # ClampAttribute - def MaxFp(self): + def MaxFp(self, j): o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10)) if o != 0: - return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) - return 0.0 + a = self._tab.Vector(o) + return self._tab.Get(flatbuffers.number_types.Uint8Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1)) + return 0 + + # ClampAttribute + def MaxFpAsNumpy(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10)) + if o != 0: + return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint8Flags, o) + return 0 + + # ClampAttribute + def MaxFpLength(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10)) + if o != 0: + return self._tab.VectorLen(o) + return 0 + + # ClampAttribute + def MaxFpIsNone(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10)) + return o == 0 def ClampAttributeStart(builder): builder.StartObject(4) def Start(builder): @@ -65,12 +105,18 @@ def AddMinInt(builder, minInt): def ClampAttributeAddMaxInt(builder, maxInt): builder.PrependInt32Slot(1, maxInt, 0) def AddMaxInt(builder, maxInt): return ClampAttributeAddMaxInt(builder, maxInt) -def ClampAttributeAddMinFp(builder, minFp): builder.PrependFloat32Slot(2, minFp, 0.0) +def ClampAttributeAddMinFp(builder, minFp): builder.PrependUOffsetTRelativeSlot(2, flatbuffers.number_types.UOffsetTFlags.py_type(minFp), 0) def AddMinFp(builder, minFp): return ClampAttributeAddMinFp(builder, minFp) -def ClampAttributeAddMaxFp(builder, maxFp): builder.PrependFloat32Slot(3, maxFp, 0.0) +def ClampAttributeStartMinFpVector(builder, numElems): return builder.StartVector(1, numElems, 1) +def StartMinFpVector(builder, numElems): + return ClampAttributeStartMinFpVector(builder, numElems) +def ClampAttributeAddMaxFp(builder, maxFp): builder.PrependUOffsetTRelativeSlot(3, flatbuffers.number_types.UOffsetTFlags.py_type(maxFp), 0) def AddMaxFp(builder, maxFp): return ClampAttributeAddMaxFp(builder, maxFp) +def ClampAttributeStartMaxFpVector(builder, numElems): return builder.StartVector(1, numElems, 1) +def StartMaxFpVector(builder, numElems): + return ClampAttributeStartMaxFpVector(builder, numElems) def ClampAttributeEnd(builder): return builder.EndObject() def End(builder): return ClampAttributeEnd(builder)
\ No newline at end of file diff --git a/python/tosa/PadAttribute.py b/python/tosa/PadAttribute.py index 8d49d5a..23698d1 100644 --- a/python/tosa/PadAttribute.py +++ b/python/tosa/PadAttribute.py @@ -63,11 +63,31 @@ class PadAttribute(object): return 0 # PadAttribute - def PadConstFp(self): + def PadConstFp(self, j): o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) if o != 0: - return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) - return 0.0 + a = self._tab.Vector(o) + return self._tab.Get(flatbuffers.number_types.Uint8Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1)) + return 0 + + # PadAttribute + def PadConstFpAsNumpy(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) + if o != 0: + return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint8Flags, o) + return 0 + + # PadAttribute + def PadConstFpLength(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) + if o != 0: + return self._tab.VectorLen(o) + return 0 + + # PadAttribute + def PadConstFpIsNone(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) + return o == 0 def PadAttributeStart(builder): builder.StartObject(3) def Start(builder): @@ -81,9 +101,12 @@ def StartPaddingVector(builder, numElems): def PadAttributeAddPadConstInt(builder, padConstInt): builder.PrependInt32Slot(1, padConstInt, 0) def AddPadConstInt(builder, padConstInt): return PadAttributeAddPadConstInt(builder, padConstInt) -def PadAttributeAddPadConstFp(builder, padConstFp): builder.PrependFloat32Slot(2, padConstFp, 0.0) +def PadAttributeAddPadConstFp(builder, padConstFp): builder.PrependUOffsetTRelativeSlot(2, flatbuffers.number_types.UOffsetTFlags.py_type(padConstFp), 0) def AddPadConstFp(builder, padConstFp): return PadAttributeAddPadConstFp(builder, padConstFp) +def PadAttributeStartPadConstFpVector(builder, numElems): return builder.StartVector(1, numElems, 1) +def StartPadConstFpVector(builder, numElems): + return PadAttributeStartPadConstFpVector(builder, numElems) def PadAttributeEnd(builder): return builder.EndObject() def End(builder): return PadAttributeEnd(builder)
\ No newline at end of file diff --git a/schema/tosa.fbs b/schema/tosa.fbs index ff8697b..e4a2498 100644 --- a/schema/tosa.fbs +++ b/schema/tosa.fbs @@ -173,7 +173,7 @@ table TransposeConvAttribute { table PadAttribute { padding: [int32]; pad_const_int: int32; - pad_const_fp: float; + pad_const_fp: [ubyte] (force_align: 8); } table AxisAttribute { @@ -203,8 +203,8 @@ table ResizeAttribute { table ClampAttribute { min_int: int32; max_int: int32; - min_fp: float; - max_fp: float; + min_fp: [ubyte] (force_align: 8); + max_fp: [ubyte] (force_align: 8); } table RescaleAttribute { diff --git a/src/tosa_serialization_handler.cpp b/src/tosa_serialization_handler.cpp index a4410f2..2062522 100644 --- a/src/tosa_serialization_handler.cpp +++ b/src/tosa_serialization_handler.cpp @@ -619,6 +619,14 @@ tosa_err_t TosaSerializationHandler::Deserialize(const uint8_t* buf) return TOSA_OK; } +std::vector<uint8_t> float_to_u8_wrapper(float f_in) +{ + const std::vector<float> f_vec{ f_in }; + std::vector<uint8_t> u8_out; + TosaSerializationHandler::ConvertF32toU8(f_vec, u8_out); + return u8_out; +} + tosa_err_t TosaSerializationHandler::Serialize() { // regions @@ -682,9 +690,11 @@ tosa_err_t TosaSerializationHandler::Serialize() fb_attribute = 0; break; #define DEF_ARGS_S_STR(NAME, V) , _builder.CreateString(reinterpret_cast<Tosa##NAME*>(op->GetAttribute())->V().c_str()) +#define DEF_ARGS_S_FP_as_U8(NAME, V) \ + , _builder.CreateVector<uint8_t>(float_to_u8_wrapper(reinterpret_cast<Tosa##NAME*>(op->GetAttribute())->V())) #define DEF_ARGS_S_DEFAULT(NAME, V) , reinterpret_cast<Tosa##NAME*>(op->GetAttribute())->V() #define DEF_ARGS_S_int32_t(NAME, V) DEF_ARGS_S_DEFAULT(NAME, V) -#define DEF_ARGS_S_float(NAME, V) DEF_ARGS_S_DEFAULT(NAME, V) +#define DEF_ARGS_S_float(NAME, V) DEF_ARGS_S_FP_as_U8(NAME, V) #define DEF_ARGS_S_bool(NAME, V) DEF_ARGS_S_DEFAULT(NAME, V) #define DEF_ARGS_S_ResizeMode(NAME, V) DEF_ARGS_S_DEFAULT(NAME, V) #define DEF_ARGS_S_DType(NAME, V) DEF_ARGS_S_DEFAULT(NAME, V) |