Set dims for constant with multiple values (#11116)

* Also fix issue with data transfer not handling Tensor<std::string> correctly.
This commit is contained in:
Scott McKay 2022-04-06 07:39:07 +10:00 committed by GitHub
parent 91c940b619
commit 58d97691ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 62 additions and 8 deletions

View file

@ -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<std::string>();
auto* dst_strings = dst.MutableData<std::string>();
std::copy(src_strings, src_strings + src.Shape().Size(), dst_strings);
}
return Status::OK();
#ifdef ENABLE_TRAINING
}

View file

@ -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 <typename T>
@ -637,10 +637,10 @@ Status TensorProtoToTensor(const Env& env, const ORTCHAR_T* model_path,
raw_data = const_cast<char*>(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<char[]>(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<char[]>(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)

View file

@ -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<float>{0.f, 1.f, 2.f, 3.f});
test.AddOutput<float>("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<int64_t>{0, 1, 2, 3});
test.AddOutput<int64_t>("Y", {4}, {0, 1, 2, 3});
test.Run();
}
TEST(ConstantOpTest, MultiValueConstant_strings) {
OpTester test("Constant", 14, kOnnxDomain);
test.AddAttribute("value_strings", std::vector<std::string>{"zero", "one", "two", "three"});
test.AddOutput<std::string>("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

View file

@ -330,7 +330,7 @@ struct TensorCheck<BFloat16> {
/// 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>& data,
void OpTester::AddSparseCsrTensorStrings(std::vector<Data>& data,
const char* name,
gsl::span<const int64_t> dims,
gsl::span<const int64_t> dims,
gsl::span<const std::string> values,
gsl::span<const int64_t> inner_indices,
gsl::span<const int64_t> outer_indices,

Binary file not shown.