diff --git a/onnxruntime/core/framework/data_transfer.cc b/onnxruntime/core/framework/data_transfer.cc index 2c97750e81..3818b43e6c 100644 --- a/onnxruntime/core/framework/data_transfer.cc +++ b/onnxruntime/core/framework/data_transfer.cc @@ -62,7 +62,14 @@ common::Status CPUDataTransfer::CopyTensor(const Tensor& src, Tensor& dst, int / #endif // Copying only happens between two same size tensors. ORT_ENFORCE(src.SizeInBytes() == dst.SizeInBytes()); - memcpy(dst_data, src_data, src.SizeInBytes()); + if (!src.IsDataTypeString()) { + memcpy(dst_data, src_data, src.SizeInBytes()); + } else { + const auto* src_strings = src.Data(); + auto* dst_strings = dst.MutableData(); + std::copy(src_strings, src_strings + src.Shape().Size(), dst_strings); + } + return Status::OK(); #ifdef ENABLE_TRAINING } diff --git a/onnxruntime/core/framework/tensorprotoutils.cc b/onnxruntime/core/framework/tensorprotoutils.cc index 08e86d815f..5b5b542643 100644 --- a/onnxruntime/core/framework/tensorprotoutils.cc +++ b/onnxruntime/core/framework/tensorprotoutils.cc @@ -228,7 +228,7 @@ Status UnpackTensorWithExternalData(const ONNX_NAMESPACE::TensorProto& /*tensor* /*out*/ std::string* /*p_data*/) { return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "External data type cannot be STRING."); } -#endif //!defined(ORT_MINIMAL_BUILD) +#endif //! defined(ORT_MINIMAL_BUILD) // implementation of type specific unpack of data contained within the TensorProto template @@ -637,10 +637,10 @@ Status TensorProtoToTensor(const Env& env, const ORTCHAR_T* model_path, raw_data = const_cast(tensor_proto.raw_data().data()); // TODO The line above has const-correctness issues. Below is a possible fix which copies the tensor_proto data // into a writeable buffer. However, it requires extra memory which may exceed the limit for certain tests. - //auto buffer = std::make_unique(tensor_proto.raw_data().size()); - //std::memcpy(buffer.get(), tensor_proto.raw_data().data(), tensor_proto.raw_data().size()); - //deleter_for_file_data.d = OrtCallback{DeleteCharArray, buffer.get()}; - //raw_data = buffer.release(); + // auto buffer = std::make_unique(tensor_proto.raw_data().size()); + // std::memcpy(buffer.get(), tensor_proto.raw_data().data(), tensor_proto.raw_data().size()); + // deleter_for_file_data.d = OrtCallback{DeleteCharArray, buffer.get()}; + // raw_data = buffer.release(); raw_data_len = tensor_proto.raw_data().size(); } @@ -807,6 +807,7 @@ common::Status ConstantNodeProtoToTensorProto(const ONNX_NAMESPACE::NodeProto& n case AttributeProto_AttributeType_FLOATS: tensor.set_data_type(TensorProto_DataType_FLOAT); *tensor.mutable_float_data() = constant_attribute.floats(); + tensor.add_dims(constant_attribute.floats().size()); break; case AttributeProto_AttributeType_INT: tensor.set_data_type(TensorProto_DataType_INT64); @@ -815,6 +816,7 @@ common::Status ConstantNodeProtoToTensorProto(const ONNX_NAMESPACE::NodeProto& n case AttributeProto_AttributeType_INTS: tensor.set_data_type(TensorProto_DataType_INT64); *tensor.mutable_int64_data() = constant_attribute.ints(); + tensor.add_dims(constant_attribute.ints().size()); break; case AttributeProto_AttributeType_STRING: tensor.set_data_type(TensorProto_DataType_STRING); @@ -823,6 +825,7 @@ common::Status ConstantNodeProtoToTensorProto(const ONNX_NAMESPACE::NodeProto& n case AttributeProto_AttributeType_STRINGS: { tensor.set_data_type(TensorProto_DataType_STRING); *tensor.mutable_string_data() = constant_attribute.strings(); + tensor.add_dims(constant_attribute.strings().size()); break; } #if !defined(DISABLE_SPARSE_TENSORS) diff --git a/onnxruntime/test/providers/cpu/tensor/constant_test.cc b/onnxruntime/test/providers/cpu/tensor/constant_test.cc new file mode 100644 index 0000000000..5622e1e3db --- /dev/null +++ b/onnxruntime/test/providers/cpu/tensor/constant_test.cc @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/session/inference_session.h" +#include "core/util/math.h" +#include "test/providers/provider_test_utils.h" +#include "gtest/gtest.h" + +namespace onnxruntime { +namespace test { + +// test that a multi value constant has the correct shape +TEST(ConstantOpTest, MultiValueConstant_floats) { + OpTester test("Constant", 14, kOnnxDomain); + test.AddAttribute("value_floats", std::vector{0.f, 1.f, 2.f, 3.f}); + test.AddOutput("Y", {4}, {0.f, 1.f, 2.f, 3.f}); + test.Run(); +} + +TEST(ConstantOpTest, MultiValueConstant_ints) { + OpTester test("Constant", 14, kOnnxDomain); + test.AddAttribute("value_ints", std::vector{0, 1, 2, 3}); + test.AddOutput("Y", {4}, {0, 1, 2, 3}); + test.Run(); +} + +TEST(ConstantOpTest, MultiValueConstant_strings) { + OpTester test("Constant", 14, kOnnxDomain); + test.AddAttribute("value_strings", std::vector{"zero", "one", "two", "three"}); + test.AddOutput("Y", {4}, {"zero", "one", "two", "three"}); + test.Run(); +} + +// regression test - https://github.com/microsoft/onnxruntime/issues/11091 +TEST(ConstantOpTest, GH11091) { + auto model_uri = ORT_TSTR("testdata/constant_floats.onnx"); + SessionOptions so; + so.session_logid = "ConstantOpTest.GH11091"; + InferenceSession session_object{so, GetEnvironment()}; + ASSERT_STATUS_OK(session_object.Load(model_uri)); + ASSERT_STATUS_OK(session_object.Initialize()); +} +} // namespace test +} // namespace onnxruntime diff --git a/onnxruntime/test/providers/provider_test_utils.cc b/onnxruntime/test/providers/provider_test_utils.cc index 094ec955fe..cf26ca2da9 100644 --- a/onnxruntime/test/providers/provider_test_utils.cc +++ b/onnxruntime/test/providers/provider_test_utils.cc @@ -330,7 +330,7 @@ struct TensorCheck { /// XXX: May need to adjust threshold as BFloat is coarse float threshold = 0.001f; #if defined(USE_TENSORRT) || defined(ENABLE_TRAINING) || defined(USE_CUDA) || defined(USE_ROCM) - threshold = 0.05f; // expect at least 95% close + threshold = 0.05f; // expect at least 95% close #endif for (int i = 0; i < size; ++i) { if (std::isnan(f_expected[i])) { @@ -653,7 +653,7 @@ void OpTester::AddSparseCsrTensorData(std::vector& data, void OpTester::AddSparseCsrTensorStrings(std::vector& data, const char* name, - gsl::span dims, + gsl::span dims, gsl::span values, gsl::span inner_indices, gsl::span outer_indices, diff --git a/onnxruntime/test/testdata/constant_floats.onnx b/onnxruntime/test/testdata/constant_floats.onnx new file mode 100644 index 0000000000..576b0bb487 Binary files /dev/null and b/onnxruntime/test/testdata/constant_floats.onnx differ