@@ -50,15 +50,19 @@ Status SaveInitializerOrtFormat(flatbuffers::FlatBufferBuilder& builder,
5050 string_data = builder.CreateVectorOfStrings (string_data_vec);
5151 } else {
5252 std::vector<uint8_t > unpacked_tensor;
53- // We can not convert this in place, because the session may be used
54- // after the model was saved in ort format. If the session is continued to be used, then
55- // we continue with initializers in memory with wrong endianess
53+ ORT_RETURN_IF_ERROR (onnxruntime::utils::UnpackInitializerData (initializer, model_path, unpacked_tensor));
54+
55+ // We cannot convert data before unpacking due to
56+ // external data not getting converted by ConvertRawDataInTensorProto function.
57+ // Instead convert data after unpacking it
5658 if constexpr (endian::native != endian::little) {
57- auto be_copy{initializer};
58- onnxruntime::utils::ConvertRawDataInTensorProto (be_copy);
59- ORT_RETURN_IF_ERROR (onnxruntime::utils::UnpackInitializerData (be_copy, model_path, unpacked_tensor));
60- } else {
61- ORT_RETURN_IF_ERROR (onnxruntime::utils::UnpackInitializerData (initializer, model_path, unpacked_tensor));
59+ size_t element_size = onnxruntime::utils::GetElementSizeOfTensor (static_cast <ONNX_NAMESPACE::TensorProto_DataType>(initializer.data_type ()));
60+
61+ if (element_size > 1 ) {
62+ onnxruntime::utils::SwapByteOrderInplace (
63+ element_size,
64+ gsl::make_span (reinterpret_cast <std::byte*>(unpacked_tensor.data ()), unpacked_tensor.size ()));
65+ }
6266 }
6367
6468 if (external_writer && unpacked_tensor.size () >= kMinimumSizeForExternalData ) {
@@ -316,7 +320,7 @@ Status LoadInitializerOrtFormat(const fbs::Tensor& fbs_tensor, TensorProto& init
316320 // high bit, but that should be unlikely in a scenario where we care about memory usage enough to use this path.
317321 auto offset = narrow<ExternalDataInfo::OFFSET_TYPE>(reinterpret_cast <intptr_t >(data_offset));
318322
319- ExternalDataInfo::SetExternalLocationToProto (onnxruntime::utils::kTensorProtoMemoryAddressTag ,
323+ ExternalDataInfo::SetExternalLocationToProto (onnxruntime::utils::kTensorProtoLittleEndianMemoryAddressTag ,
320324 offset, fbs_raw_data->size (), initializer);
321325
322326 } else {
@@ -473,9 +477,31 @@ Status SaveOrtTensorOrtFormat(
473477 // To avoid issues with vtable offsets, raw_data fbs::vector must be constructed before the TensorBuilder begins
474478 // building the tensor. See flatbuffer_builder.h's NotNested() function for more details.
475479 flatbuffers::Offset<flatbuffers::Vector<uint8_t >> raw_data;
480+
481+ auto unpack_tensor_data_be = [&ort_tensor](std::vector<uint8_t >& unpacked_tensor_data) -> Status {
482+ unpacked_tensor_data.resize (ort_tensor.SizeInBytes ());
483+
484+ size_t element_size = onnxruntime::utils::GetElementSizeOfTensor (static_cast <ONNX_NAMESPACE::TensorProto_DataType>(ort_tensor.GetElementType ()));
485+ auto src_span = gsl::make_span (reinterpret_cast <const unsigned char *>(ort_tensor.DataRaw ()), ort_tensor.SizeInBytes ());
486+ auto dst_span = gsl::make_span (reinterpret_cast <unsigned char *>(unpacked_tensor_data.data ()), unpacked_tensor_data.size ());
487+
488+ // If element size is unknown, set it to 1 to disable byteswapping
489+ if (element_size < 1 ) element_size = 1 ;
490+
491+ return onnxruntime::utils::WriteLittleEndian (element_size, src_span, dst_span);
492+ };
493+
476494 if (!external_data_writer) {
477- raw_data = builder.CreateVector (static_cast <const uint8_t *>(ort_tensor.DataRaw ()),
478- ort_tensor.SizeInBytes ());
495+ if constexpr (endian::native != endian::little) {
496+ std::vector<uint8_t > unpacked_tensor;
497+
498+ ORT_RETURN_IF_ERROR (unpack_tensor_data_be (unpacked_tensor));
499+
500+ raw_data = builder.CreateVector (unpacked_tensor.data (), unpacked_tensor.size ());
501+ } else {
502+ raw_data = builder.CreateVector (static_cast <const uint8_t *>(ort_tensor.DataRaw ()),
503+ ort_tensor.SizeInBytes ());
504+ }
479505 }
480506
481507 fbs::TensorBuilder tb (builder);
@@ -485,8 +511,17 @@ Status SaveOrtTensorOrtFormat(
485511 tb.add_data_type (static_cast <fbs::TensorDataType>(ort_tensor.GetElementType ()));
486512 if (external_data_writer) {
487513 uint64_t offset = 0 ;
488- gsl::span<const uint8_t > ort_tensor_data_span (static_cast <const uint8_t *>(ort_tensor.DataRaw ()), ort_tensor.SizeInBytes ());
489- ORT_RETURN_IF_ERROR (external_data_writer (ort_tensor.GetElementType (), ort_tensor_data_span, offset));
514+ if constexpr (endian::native != endian::little) {
515+ std::vector<uint8_t > unpacked_tensor;
516+
517+ ORT_RETURN_IF_ERROR (unpack_tensor_data_be (unpacked_tensor));
518+
519+ gsl::span<const uint8_t > ort_tensor_data_span (static_cast <const uint8_t *>(unpacked_tensor.data ()), unpacked_tensor.size ());
520+ ORT_RETURN_IF_ERROR (external_data_writer (ort_tensor.GetElementType (), ort_tensor_data_span, offset));
521+ } else {
522+ gsl::span<const uint8_t > ort_tensor_data_span (static_cast <const uint8_t *>(ort_tensor.DataRaw ()), ort_tensor.SizeInBytes ());
523+ ORT_RETURN_IF_ERROR (external_data_writer (ort_tensor.GetElementType (), ort_tensor_data_span, offset));
524+ }
490525 int64_t external_data_offset = onnxruntime::narrow<int64_t >(offset);
491526 tb.add_external_data_offset (external_data_offset);
492527 } else {
@@ -546,8 +581,21 @@ Status LoadOrtTensorOrtFormat(const fbs::Tensor& fbs_tensor, const AllocatorPtr
546581 const DataTypeImpl* tensor_dtype = DataTypeImpl::TensorTypeFromONNXEnum (
547582 tensor_data_type)
548583 ->GetElementType ();
549- ort_tensor = onnxruntime::Tensor (
550- tensor_dtype, TensorShape (tensor_dims->data (), tensor_dims->size ()), allocator);
584+
585+ if constexpr (endian::native != endian::little) {
586+ std::vector<typename std::remove_reference_t <decltype (*tensor_dims)>::return_type> byteswapped_data;
587+ byteswapped_data.resize (tensor_dims->size ());
588+
589+ for (size_t i = 0 ; i < tensor_dims->size (); ++i) {
590+ byteswapped_data[i] = tensor_dims->Get (i);
591+ }
592+
593+ ort_tensor = onnxruntime::Tensor (
594+ tensor_dtype, TensorShape (byteswapped_data.data (), byteswapped_data.size ()), allocator);
595+ } else {
596+ ort_tensor = onnxruntime::Tensor (
597+ tensor_dtype, TensorShape (tensor_dims->data (), tensor_dims->size ()), allocator);
598+ }
551599
552600 if (fbs_tensor.raw_data () && fbs_tensor.raw_data ()->size () == 0U ) {
553601 // Empty tensor. Nothing to unpack.
0 commit comments