diff --git a/include/onnxruntime/core/framework/data_types.h b/include/onnxruntime/core/framework/data_types.h index fab910f23b..d89bdc555f 100644 --- a/include/onnxruntime/core/framework/data_types.h +++ b/include/onnxruntime/core/framework/data_types.h @@ -432,8 +432,12 @@ struct SetMapTypes { TensorElementTypeSetter::SetMapKeyType(proto); MLDataType dt = GetMLDataType::value>::Get(); const auto* value_proto = dt->GetTypeProto(); +#ifdef ORT_NO_RTTI + ORT_ENFORCE(value_proto != nullptr, "expected a registered ONNX type"); +#else ORT_ENFORCE(value_proto != nullptr, typeid(V).name(), " expected to be a registered ONNX type"); +#endif CopyMutableMapValue(*value_proto, proto); } }; @@ -449,8 +453,12 @@ struct SetSequenceType { static void Set(ONNX_NAMESPACE::TypeProto& proto) { MLDataType dt = GetMLDataType::value>::Get(); const auto* elem_proto = dt->GetTypeProto(); +#ifdef ORT_NO_RTTI + ORT_ENFORCE(elem_proto != nullptr, "expected a registered ONNX type"); +#else ORT_ENFORCE(elem_proto != nullptr, typeid(T).name(), " expected to be a registered ONNX type"); +#endif CopyMutableSeqElement(*elem_proto, proto); } }; diff --git a/onnxruntime/contrib_ops/cpu/crop.h b/onnxruntime/contrib_ops/cpu/crop.h index 7d6e2566a2..d06be5645c 100644 --- a/onnxruntime/contrib_ops/cpu/crop.h +++ b/onnxruntime/contrib_ops/cpu/crop.h @@ -48,13 +48,10 @@ class CropBase { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Input's width (", W, ") needs to be greater than or equal to the leftBorder (", leftBorder, ") + rightBorder (", rightBorder, ")"); } - int64_t bottomLimit = H - bottomBorder; - int64_t rightLimit = W - rightBorder; - // scale = (height, width) if (!scale_.empty()) { - bottomLimit = topBorder + scale_[0]; - rightLimit = leftBorder + scale_[1]; + int64_t bottomLimit = topBorder + scale_[0]; + int64_t rightLimit = leftBorder + scale_[1]; if (H < bottomLimit) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, diff --git a/onnxruntime/core/common/path.cc b/onnxruntime/core/common/path.cc index 0d60e884d1..1050f096a4 100644 --- a/onnxruntime/core/common/path.cc +++ b/onnxruntime/core/common/path.cc @@ -253,18 +253,22 @@ Path& Path::Append(const Path& other) { return *this; } -Path& Path::Concat(const PathString& string) { - components_.back() += string; - return *this; -} +Path& Path::Concat(const PathString& value) { + auto first_separator = std::find_if(value.begin(), value.end(), + [](PathChar c) { + return std::find( + k_valid_path_separators.begin(), + k_valid_path_separators.end(), + c) != k_valid_path_separators.end(); + }); + ORT_ENFORCE(first_separator == value.end(), + "Cannot concatenate with a string containing a path separator. String: ", ToMBString(value)); -Path& Path::ConcatIndex(const int index) { -#ifdef _WIN32 - auto index_str = std::to_wstring(index); -#else - auto index_str = std::to_string(index); -#endif - components_.back() += index_str; + if (components_.empty()) { + components_.push_back(value); + } else { + components_.back() += value; + } return *this; } diff --git a/onnxruntime/core/common/path.h b/onnxruntime/core/common/path.h index 9dac03b725..514a636033 100644 --- a/onnxruntime/core/common/path.h +++ b/onnxruntime/core/common/path.h @@ -68,12 +68,6 @@ class Path { */ Path& Concat(const PathString& string); - /** - * Concatenates an index by the end of current path. - * Similar to Concat() except the argument is an index. - */ - Path& ConcatIndex(const int index); - /** Equivalent to this->Append(other). */ Path& operator/=(const Path& other) { return Append(other); diff --git a/onnxruntime/core/common/path_utils.h b/onnxruntime/core/common/path_utils.h new file mode 100644 index 0000000000..4e133a0dd5 --- /dev/null +++ b/onnxruntime/core/common/path_utils.h @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/common/common.h" +#include "core/common/path_string.h" + +namespace onnxruntime { + +namespace path_utils { + +/** Return a PathString with concatenated args. + * TODO: add support for arguments of type std::wstring. Currently it is not supported as the underneath + * MakeString doesn't support this type. +*/ +template +PathString MakePathString(const Args&... args) { + const std::string str = onnxruntime::MakeString(args...); + return ToPathString(str); +} +} +} diff --git a/onnxruntime/core/common/threadpool.cc b/onnxruntime/core/common/threadpool.cc index 3e053ce9f4..374a882dc7 100644 --- a/onnxruntime/core/common/threadpool.cc +++ b/onnxruntime/core/common/threadpool.cc @@ -312,7 +312,6 @@ static ptrdiff_t CalculateParallelForBlock(const ptrdiff_t n, const Eigen::Tenso if (coarser_efficiency + 0.01 >= max_efficiency) { // Taking it. block_size = coarser_block_size; - block_count = coarser_block_count; if (max_efficiency < coarser_efficiency) { max_efficiency = coarser_efficiency; } diff --git a/onnxruntime/core/framework/error_code.cc b/onnxruntime/core/framework/error_code.cc index 4c6f73f915..02d5c4a1d3 100644 --- a/onnxruntime/core/framework/error_code.cc +++ b/onnxruntime/core/framework/error_code.cc @@ -23,7 +23,7 @@ struct OrtStatus { _Check_return_ _Ret_notnull_ OrtStatus* ORT_API_CALL OrtApis::CreateStatus(OrtErrorCode code, _In_z_ const char* msg) NO_EXCEPTION { assert(!(code == 0 && msg != nullptr)); - SafeInt clen(strlen(msg)); + SafeInt clen(nullptr == msg ? 0 : strlen(msg)); OrtStatus* p = reinterpret_cast(::malloc(sizeof(OrtStatus) + clen)); if (p == nullptr) return nullptr; // OOM. What we can do here? abort()? p->code = code; diff --git a/onnxruntime/core/framework/kernel_registry.cc b/onnxruntime/core/framework/kernel_registry.cc index 081031c343..844c2a0d9d 100644 --- a/onnxruntime/core/framework/kernel_registry.cc +++ b/onnxruntime/core/framework/kernel_registry.cc @@ -233,9 +233,8 @@ Status KernelRegistry::TryCreateKernel(const onnxruntime::Node& node, const FuncManager& funcs_mgr, const DataTransferManager& data_transfer_mgr, /*out*/ std::unique_ptr& op_kernel) const { - const KernelCreateInfo* kernel_create_info; + const KernelCreateInfo* kernel_create_info = nullptr; ORT_RETURN_IF_ERROR(TryFindKernel(node, execution_provider.Type(), &kernel_create_info)); - OpKernelInfo kernel_info(node, *kernel_create_info->kernel_def, execution_provider, diff --git a/onnxruntime/core/framework/tensorprotoutils.cc b/onnxruntime/core/framework/tensorprotoutils.cc index 4021be3c2d..d7346fb702 100644 --- a/onnxruntime/core/framework/tensorprotoutils.cc +++ b/onnxruntime/core/framework/tensorprotoutils.cc @@ -698,7 +698,7 @@ common::Status SparseTensorProtoToDenseTensorProto(const ONNX_NAMESPACE::SparseT auto dims = gsl::make_span(dense.dims().data(), dense.dims().size()); // need to read in sparse data first as it could be in a type specific field, in raw data, or in external data - size_t sparse_bytes; + size_t sparse_bytes = 0; ORT_RETURN_IF_ERROR(GetSizeInBytesFromTensorProto<0>(sparse_values, &sparse_bytes)); if (type != TensorProto_DataType_STRING) { diff --git a/onnxruntime/core/mlas/lib/pooling.cpp b/onnxruntime/core/mlas/lib/pooling.cpp index 805b6e243f..dfe87578d6 100644 --- a/onnxruntime/core/mlas/lib/pooling.cpp +++ b/onnxruntime/core/mlas/lib/pooling.cpp @@ -1196,6 +1196,10 @@ Return Value: bool AllPaddingIsZero = true; bool AllKernelsAreSmall = true; + if (Dimensions > 3) { + throw std::runtime_error("bad dimensions"); + } + for (size_t dim = 0; dim < Dimensions; dim++) { WorkBlock.InputShape[dim] = size_t(InputShape[dim]); diff --git a/onnxruntime/core/optimizer/insert_cast_transformer.cc b/onnxruntime/core/optimizer/insert_cast_transformer.cc index 1aa4899153..069bc0678b 100644 --- a/onnxruntime/core/optimizer/insert_cast_transformer.cc +++ b/onnxruntime/core/optimizer/insert_cast_transformer.cc @@ -237,17 +237,34 @@ Status InsertCastTransformer::ApplyImpl(onnxruntime::Graph& graph, bool& modifie } } - if (casted && node->GetExecutionProviderType().empty()) { - //set current node to CPU execution provider + if (casted) { + // Set current node to run on the CPU execution provider + // Keep in mind that the EP will be empty because NeedInsertCast() already insures that node->SetExecutionProviderType(kCpuExecutionProvider); + + // Some ONNX operators have an attribute `dtype` which define the output type for these operators + // (mostly Generator ops like RandomNormal, RandomNormalLike, EyeLike, etc.). + // Update that so that `dtype` is now Float. Otherwise there could be a mis-match between the actual + // type of the NodeArg and the ONNX inferred type of the NodeArg and Graph Resolve() will complain. + auto& attributes = node->GetMutableAttributes(); + auto dtype_attribute = attributes.find("dtype"); + + if (dtype_attribute != attributes.end()) { + // Simple sanity check + ORT_ENFORCE(dtype_attribute->second.has_i(), + "InsertCastTransformer works on the assumption that `dtype` attribute holds an integer."); + + dtype_attribute->second.set_i(TensorProto_DataType_FLOAT); + } } auto& outputs = node->MutableOutputDefs(); for (auto output : outputs) { - // todo: check is the kernel available - // here is based on the assumption that if we cast a cpu op's input from float16 to float - // then this cpu op's output will become float. - // not sure is it always correct... + // TODO 1: Check if the kernel available + // TODO 2: There is an inherent assumption that if we cast a cpu op's input from float16 to float + // then this cpu op's output will be float (if it was inferred to be float16 previously). + // Not sure if this is always true. Handle any corner case if it does exist. + if (output->Type() && DataTypeImpl::TypeFromProto(*output->TypeAsProto()) == DataTypeImpl::GetTensorType() && casted) { diff --git a/onnxruntime/core/platform/posix/env.cc b/onnxruntime/core/platform/posix/env.cc index 35f7b1db40..3db54352c7 100644 --- a/onnxruntime/core/platform/posix/env.cc +++ b/onnxruntime/core/platform/posix/env.cc @@ -423,9 +423,9 @@ class PosixEnv : public Env { } common::Status LoadDynamicLibrary(const std::string& library_filename, void** handle) const override { - char* error_str = dlerror(); // clear any old error_str + dlerror(); // clear any old error_str *handle = dlopen(library_filename.c_str(), RTLD_NOW | RTLD_LOCAL); - error_str = dlerror(); + char* error_str = dlerror(); if (!*handle) { return common::Status(common::ONNXRUNTIME, common::FAIL, "Failed to load library " + library_filename + " with error: " + error_str); @@ -437,9 +437,9 @@ class PosixEnv : public Env { if (!handle) { return common::Status(common::ONNXRUNTIME, common::FAIL, "Got null library handle"); } - char* error_str = dlerror(); // clear any old error_str + dlerror(); // clear any old error_str int retval = dlclose(handle); - error_str = dlerror(); + char* error_str = dlerror(); if (retval != 0) { return common::Status(common::ONNXRUNTIME, common::FAIL, "Failed to unload library with error: " + std::string(error_str)); @@ -448,9 +448,9 @@ class PosixEnv : public Env { } common::Status GetSymbolFromLibrary(void* handle, const std::string& symbol_name, void** symbol) const override { - char* error_str = dlerror(); // clear any old error str + dlerror(); // clear any old error str *symbol = dlsym(handle, symbol_name.c_str()); - error_str = dlerror(); + char* error_str = dlerror(); if (error_str) { return common::Status(common::ONNXRUNTIME, common::FAIL, "Failed to get symbol " + symbol_name + " with error: " + error_str); diff --git a/onnxruntime/core/providers/cpu/cpu_execution_provider.cc b/onnxruntime/core/providers/cpu/cpu_execution_provider.cc index 4bc6d526ad..7a8b947a51 100644 --- a/onnxruntime/core/providers/cpu/cpu_execution_provider.cc +++ b/onnxruntime/core/providers/cpu/cpu_execution_provider.cc @@ -278,9 +278,7 @@ class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDoma class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, float, MatMul); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, double, MatMul); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, int32_t, MatMul); -class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, uint32_t, MatMul); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, int64_t, MatMul); -class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, uint64_t, MatMul); // Opset 10 class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, StringNormalizer); @@ -898,12 +896,8 @@ Status RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) { MatMul)>, BuildKernelCreateInfo, - BuildKernelCreateInfo, BuildKernelCreateInfo, - BuildKernelCreateInfo, // Opset 10 BuildKernelCreateInfo, diff --git a/onnxruntime/core/providers/cpu/math/cumsum.cc b/onnxruntime/core/providers/cpu/math/cumsum.cc index 9370b6942b..0371d18ddc 100644 --- a/onnxruntime/core/providers/cpu/math/cumsum.cc +++ b/onnxruntime/core/providers/cpu/math/cumsum.cc @@ -144,7 +144,7 @@ Status CumSum::Compute(OpKernelContext* ctx) const { if (output_shape.Size() == 0) return Status::OK(); - int64_t axis; + int64_t axis = 0; ORT_THROW_IF_ERROR(cumsum_op::GetAxis(axis_tensor, rank, axis)); auto dim(output_tensor.Shape()[axis]); // dimension size for the axis diff --git a/onnxruntime/core/providers/cpu/math/matmul.cc b/onnxruntime/core/providers/cpu/math/matmul.cc index 8a7d26fc13..6a66fd609f 100644 --- a/onnxruntime/core/providers/cpu/math/matmul.cc +++ b/onnxruntime/core/providers/cpu/math/matmul.cc @@ -1,13 +1,21 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/providers/cpu/math/matmul.h" +#include "core/framework/op_kernel.h" +#include "core/providers/cpu/math/matmul_helper.h" #include "core/util/math.h" #include "core/util/math_cpuonly.h" -#include "matmul_helper.h" namespace onnxruntime { +template +class MatMul final : public OpKernel { + public: + MatMul(const OpKernelInfo& info) : OpKernel(info) {} + + Status Compute(OpKernelContext* context) const override; +}; + ONNX_CPU_OPERATOR_VERSIONED_TYPED_KERNEL( MatMul, 1, 8, @@ -41,41 +49,34 @@ ONNX_CPU_OPERATOR_TYPED_KERNEL( MatMul, 9, int32_t, - KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType()), + KernelDefBuilder() + .TypeConstraint("T", {DataTypeImpl::GetTensorType(), DataTypeImpl::GetTensorType()}), MatMul); -ONNX_CPU_OPERATOR_TYPED_KERNEL( - MatMul, - 9, - uint32_t, - KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType()), - MatMul); - ONNX_CPU_OPERATOR_TYPED_KERNEL( MatMul, 9, int64_t, - KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType()), + KernelDefBuilder() + .TypeConstraint("T", {DataTypeImpl::GetTensorType(), DataTypeImpl::GetTensorType()}), MatMul); -ONNX_CPU_OPERATOR_TYPED_KERNEL( - MatMul, - 9, - uint64_t, - KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType()), - MatMul); - template Status MatMul::Compute(OpKernelContext* ctx) const { concurrency::ThreadPool* thread_pool = ctx->GetOperatorThreadPool(); - const auto* left_X = ctx->Input(0); - const auto* right_X = ctx->Input(1); + const auto* a = ctx->Input(0); + const auto* b = ctx->Input(1); MatMulComputeHelper helper; - ORT_RETURN_IF_ERROR(helper.Compute(left_X->Shape(), right_X->Shape())); + ORT_RETURN_IF_ERROR(helper.Compute(a->Shape(), b->Shape())); + Tensor* y = ctx->Output(0, helper.OutputShape()); - Tensor* Y = ctx->Output(0, helper.OutputShape()); + // Using DataRaw as int32_t/uint32_t and int64_t/uint64_t share a common + // operator body. + const auto* a_data = reinterpret_cast(a->DataRaw()); + const auto* b_data = reinterpret_cast(b->DataRaw()); + auto* y_data = reinterpret_cast(y->MutableDataRaw()); // TODO: replace it with GemmBatch for performance, it's OK for now as GemmBatch unrolls as well size_t max_len = helper.OutputOffsets().size(); @@ -84,9 +85,10 @@ Status MatMul::Compute(OpKernelContext* ctx) const { static_cast(helper.M()), static_cast(helper.N()), static_cast(helper.K()), - left_X->template Data() + helper.LeftOffsets()[i], - right_X->template Data() + helper.RightOffsets()[i], - Y->template MutableData() + helper.OutputOffsets()[i], thread_pool); + a_data + helper.LeftOffsets()[i], + b_data + helper.RightOffsets()[i], + y_data + helper.OutputOffsets()[i], + thread_pool); } return Status::OK(); diff --git a/onnxruntime/core/providers/cpu/math/matmul.h b/onnxruntime/core/providers/cpu/math/matmul.h deleted file mode 100644 index 02a42aa3ef..0000000000 --- a/onnxruntime/core/providers/cpu/math/matmul.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#include "core/common/common.h" -#include "core/framework/op_kernel.h" - -namespace onnxruntime { - -template -class MatMul final : public OpKernel { - public: - MatMul(const OpKernelInfo& info) - : OpKernel(info) { - } - - Status Compute(OpKernelContext* context) const override; -}; - -} // namespace onnxruntime diff --git a/onnxruntime/core/providers/cpu/reduction/reduction_ops.cc b/onnxruntime/core/providers/cpu/reduction/reduction_ops.cc index f89e368e3b..b37872b8ae 100644 --- a/onnxruntime/core/providers/cpu/reduction/reduction_ops.cc +++ b/onnxruntime/core/providers/cpu/reduction/reduction_ops.cc @@ -286,6 +286,10 @@ bool PrepareForReduce(const Tensor* input_tensor_ptr, return true; } + if (0 == first_dim) { + return false; + } + block_size = num_elements / first_dim; blocks = first_dim; diff --git a/onnxruntime/core/providers/cpu/tensor/cast_op.cc b/onnxruntime/core/providers/cpu/tensor/cast_op.cc index 7d74e1db25..8400cfe339 100644 --- a/onnxruntime/core/providers/cpu/tensor/cast_op.cc +++ b/onnxruntime/core/providers/cpu/tensor/cast_op.cc @@ -157,7 +157,11 @@ inline void CastFromStringData(const Tensor* in, Tensor* out, const TensorShape& mutable_data[i] = std::stoull(in->Data()[i]); } } else { +#ifdef ORT_NO_RTTI + ORT_THROW("Unsupported type in cast op"); +#else ORT_THROW("Unsupported type in cast op: from String to ", typeid(DstType).name()); +#endif } } // namespace onnxruntime diff --git a/onnxruntime/core/providers/cpu/tensor/unsqueeze.cc b/onnxruntime/core/providers/cpu/tensor/unsqueeze.cc index 58a7caeaa4..39be162f0b 100644 --- a/onnxruntime/core/providers/cpu/tensor/unsqueeze.cc +++ b/onnxruntime/core/providers/cpu/tensor/unsqueeze.cc @@ -58,6 +58,7 @@ Status UnsqueezeBase::PrepareCompute(OpKernelContext* ctx, Prepare& p) const { TensorShape output_shape(output_dims); p.output_tensor = ctx->Output(0, output_shape); + ORT_ENFORCE(nullptr != p.output_tensor); p.input_tensor = &input_tensor; return Status::OK(); } @@ -65,9 +66,7 @@ Status UnsqueezeBase::PrepareCompute(OpKernelContext* ctx, Prepare& p) const { Status Unsqueeze::Compute(OpKernelContext* ctx) const { Prepare p; ORT_RETURN_IF_ERROR(PrepareCompute(ctx, p)); - CopyCpuTensor(p.input_tensor, p.output_tensor); - return Status::OK(); } } // namespace onnxruntime diff --git a/onnxruntime/test/common/path_test.cc b/onnxruntime/test/common/path_test.cc index ea8908affc..dbd9990c0d 100644 --- a/onnxruntime/test/common/path_test.cc +++ b/onnxruntime/test/common/path_test.cc @@ -5,6 +5,7 @@ #include "gtest/gtest.h" +#include "core/common/optional.h" #include "test/util/include/asserts.h" namespace onnxruntime { @@ -224,31 +225,29 @@ TEST(PathTest, RelativePathFailure) { TEST(PathTest, Concat) { auto check_concat = - [](const std::string& a, const std::string& b, const std::string& expected_a) { + [](const optional& a, const std::string& b, const std::string& expected_a, bool expect_throw = false) { Path p_a{}, p_expected_a{}; - ASSERT_STATUS_OK(Path::Parse(ToPathString(a), p_a)); + if (a.has_value()) { + ASSERT_STATUS_OK(Path::Parse(ToPathString(a.value()), p_a)); + } ASSERT_STATUS_OK(Path::Parse(ToPathString(expected_a), p_expected_a)); - EXPECT_EQ(p_a.Concat(ToPathString(b)).ToPathString(), p_expected_a.ToPathString()); + if (expect_throw) { + EXPECT_THROW(p_a.Concat(ToPathString(b)).ToPathString(), OnnxRuntimeException); + } else { + EXPECT_EQ(p_a.Concat(ToPathString(b)).ToPathString(), p_expected_a.ToPathString()); + } }; - check_concat("/a/b", "c", "/a/bc"); - check_concat("a/b", "cd", "a/bcd"); -} - -TEST(PathTest, ConcatIndex) { - auto check_concat_index = - [](const std::string& a, const int i, const std::string& expected_a) { - Path p_a{}, p_expected_a{}; - ASSERT_STATUS_OK(Path::Parse(ToPathString(a), p_a)); - ASSERT_STATUS_OK(Path::Parse(ToPathString(expected_a), p_expected_a)); - - EXPECT_EQ(p_a.ConcatIndex(i).ToPathString(), p_expected_a.ToPathString()); - }; - - check_concat_index("/a/b", 0, "/a/b0"); - check_concat_index("a/b", 123, "a/b123"); - check_concat_index("a/b", -1, "a/b-1"); + check_concat({"/a/b"}, "c", "/a/bc"); + check_concat({"a/b"}, "cd", "a/bcd"); + check_concat({""}, "cd", "cd"); + check_concat({}, "c", "c"); +#ifdef _WIN32 + check_concat({"a/b"}, R"(c\d)", "", true /* expect_throw */); +#else + check_concat({"a/b"}, "c/d", "", true /* expect_throw */); +#endif } } // namespace test diff --git a/onnxruntime/test/framework/insert_cast_transformer_test.cc b/onnxruntime/test/framework/insert_cast_transformer_test.cc index dc9a1d8bf4..152a407e85 100644 --- a/onnxruntime/test/framework/insert_cast_transformer_test.cc +++ b/onnxruntime/test/framework/insert_cast_transformer_test.cc @@ -134,5 +134,24 @@ TEST(TransformerTest, ThreeInARowRemoval) { ASSERT_TRUE(op_to_count["Cast"] == 2); } +// test a case where the ONNX inferred type (float16) is different from the type bound +// to the output NodeArg of the "RandomNormalLike" node because of the InsertCaseTransformer +TEST(TransformerTest, RandomNormalLikeWithFloat16Inputs) { + auto model_uri = MODEL_FOLDER ORT_TSTR("random_normal_like_float16.onnx"); + std::shared_ptr model; + auto status = Model::Load(model_uri, model, nullptr, DefaultLoggingManager().DefaultLogger()); + ASSERT_TRUE(status.IsOK()) << status; + + Graph& graph = model->MainGraph(); + InsertCastTransformer transformer("Test"); + + bool modified = false; + status = transformer.Apply(graph, modified, DefaultLoggingManager().DefaultLogger()); + EXPECT_TRUE(status.IsOK()) << status; + EXPECT_TRUE(modified) << "Transformer should have added some Cast nodes"; + status = graph.Resolve(); + EXPECT_TRUE(status.IsOK()) << status; +} + } // namespace test } // namespace onnxruntime diff --git a/onnxruntime/test/onnx/tensorprotoutils.cc b/onnxruntime/test/onnx/tensorprotoutils.cc index c0a1fdd612..6b3df28b94 100644 --- a/onnxruntime/test/onnx/tensorprotoutils.cc +++ b/onnxruntime/test/onnx/tensorprotoutils.cc @@ -401,7 +401,7 @@ Status TensorProtoToMLValue(const onnx::TensorProto& tensor_proto, const MemBuff if (static_cast(tensor_size) > SIZE_MAX) { return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT, "Size overflow"); } - size_t size_to_allocate; + size_t size_to_allocate = 0; ORT_RETURN_IF_ERROR(GetSizeInBytesFromTensorProto<0>(tensor_proto, &size_to_allocate)); if (preallocated && preallocated_size < size_to_allocate) diff --git a/onnxruntime/test/testdata/bert_toy_optimized.onnx b/onnxruntime/test/testdata/bert_toy_optimized.onnx index 0b99357470..f2d6b241bd 100644 Binary files a/onnxruntime/test/testdata/bert_toy_optimized.onnx and b/onnxruntime/test/testdata/bert_toy_optimized.onnx differ diff --git a/onnxruntime/test/testdata/transform/random_normal_like_float16.onnx b/onnxruntime/test/testdata/transform/random_normal_like_float16.onnx new file mode 100644 index 0000000000..17e0271b53 --- /dev/null +++ b/onnxruntime/test/testdata/transform/random_normal_like_float16.onnx @@ -0,0 +1,17 @@ +:Ð +F +input_0output_0RandomNormalLike1"RandomNormalLike* +dtype +  +G +output_0output_1RandomNormalLike2"RandomNormalLike* +dtype Reshape_FusionZ +input_0 + + + +b +output_1 + + +B \ No newline at end of file diff --git a/orttraining/orttraining/core/graph/loss_func/bert_loss.cc b/orttraining/orttraining/core/graph/loss_func/bert_loss.cc index b3237c2405..02f6fc933a 100644 --- a/orttraining/orttraining/core/graph/loss_func/bert_loss.cc +++ b/orttraining/orttraining/core/graph/loss_func/bert_loss.cc @@ -47,6 +47,49 @@ TypeProto* BertLoss::GetGatheredPredictionTypeProto(const NodeArg* prediction_ar return type_proto; } +TypeProto* BertLoss::GetTransposedTypeProto(const NodeArg* prediction_arg, + GraphAugmenter::GraphDefs& graph_defs) { + ORT_ENFORCE(prediction_arg != nullptr, "GetTransposedTypeProto's prediction_arg is nullptr"); + const auto* logits_type_proto = prediction_arg->TypeAsProto(); + const auto& dims = logits_type_proto->tensor_type().shape().dim(); + + TypeProto* type_proto = graph_defs.CreateTypeProto(); + type_proto->mutable_tensor_type()->set_elem_type(ONNX_NAMESPACE::TensorProto_DataType_FLOAT); + + auto* target_shape = type_proto->mutable_tensor_type()->mutable_shape(); + // Batch size. + target_shape->add_dim()->CopyFrom(dims[0]); + + // Class. + target_shape->add_dim()->CopyFrom(dims[dims.size() - 1]); + + for (int i = 1; i < dims.size() - 1; i++) { + target_shape->add_dim()->CopyFrom(dims[i]); + } + + return type_proto; +} + +TypeProto* BertLoss::GetGatheredPredictionTransposedTypeProto(const NodeArg* prediction_arg, + GraphAugmenter::GraphDefs& graph_defs) { + ORT_ENFORCE(prediction_arg != nullptr, "GetGatheredPredictionTransposedTypeProto's prediction_arg is nullptr"); + const auto* logits_type_proto = prediction_arg->TypeAsProto(); + const auto& dims = logits_type_proto->tensor_type().shape().dim(); + + TypeProto* type_proto = graph_defs.CreateTypeProto(); + type_proto->mutable_tensor_type()->set_elem_type(ONNX_NAMESPACE::TensorProto_DataType_FLOAT); + + auto* target_shape = type_proto->mutable_tensor_type()->mutable_shape(); + // Batch size. + target_shape->add_dim()->CopyFrom(dims[0]); + // Vocab size. + target_shape->add_dim()->CopyFrom(dims[2]); + // Prediction count. + target_shape->add_dim()->set_dim_param("dynamic_prediction_count"); + + return type_proto; +} + TypeProto* BertLoss::GetLossTypeProto(GraphAugmenter::GraphDefs& graph_defs) { return graph_defs.CreateTypeProto({}, ONNX_NAMESPACE::TensorProto_DataType_FLOAT); } @@ -54,15 +97,14 @@ TypeProto* BertLoss::GetLossTypeProto(GraphAugmenter::GraphDefs& graph_defs) { GraphAugmenter::GraphDefs BertLoss::operator()(const Graph& graph, const LossFunctionInfo& loss_func_info) { const std::string& total_loss = loss_func_info.loss_name; const VectorString& args = loss_func_info.loss_builder_args; - ORT_ENFORCE(args.size() == 8, " Invalid loss_func_info for BertLoss."); + ORT_ENFORCE(args.size() == 7, " Invalid loss_func_info for BertLoss."); const std::string& prediction_masked_lm = args[0]; const std::string& prediction_next_sentence = args[1]; const std::string& masked_lm_positions = args[2]; const std::string& masked_lm_ids = args[3]; - const std::string& masked_lm_weights = args[4]; - const std::string& next_sentence_labels = args[5]; - const std::string& mlm_loss = args[6]; - const std::string& nsp_loss = args[7]; + const std::string& next_sentence_labels = args[4]; + const std::string& mlm_loss = args[5]; + const std::string& nsp_loss = args[6]; std::vector new_nodes; GraphAugmenter::GraphDefs graph_defs; @@ -89,16 +131,30 @@ GraphAugmenter::GraphDefs BertLoss::operator()(const Graph& graph, const LossFun {ONNX_NAMESPACE::MakeAttribute("batch_dims", static_cast(1))}, "GATHERED_LM")); - TypeProto* masked_lm_float_type_proto = GetMaskedLMTypeProto(prediction_arg, - ONNX_NAMESPACE::TensorProto_DataType_FLOAT, - graph_defs); - new_nodes.emplace_back(NodeDef("SparseSoftmaxCrossEntropy", - {ArgDef("gathered_prediction", gathered_prediction_type_proto), - ArgDef(masked_lm_ids, masked_lm_int64_type_proto), - ArgDef(masked_lm_weights, masked_lm_float_type_proto)}, // Inputs - {ArgDef(mlm_loss, GetLossTypeProto(graph_defs)), // Outputs - ArgDef("probability_lm", gathered_prediction_type_proto)}, - {ONNX_NAMESPACE::MakeAttribute("reduction", "mean")}, + // Transpose gathered_predictions with the following permutation: {0, 2, 1} because SoftmaxCrossEntropyLoss accepts + // scores of the shape {N, C, D1, D2...Dk}. + TypeProto* gathered_prediction_transposed_type_proto = GetGatheredPredictionTransposedTypeProto(prediction_arg, + graph_defs); + + new_nodes.emplace_back(NodeDef("Transpose", + {ArgDef("gathered_prediction", gathered_prediction_type_proto)}, // Inputs + {ArgDef("gathered_prediction_transposed", + gathered_prediction_transposed_type_proto)}, // Outputs + {ONNX_NAMESPACE::MakeAttribute("perm", std::vector{static_cast(0), + static_cast(2), static_cast(1)})}, + + "Transpose_gathered_prediction")); + + std::vector attrs; + attrs.push_back(ONNX_NAMESPACE::MakeAttribute("ignore_index", static_cast(-1))); + attrs.push_back(ONNX_NAMESPACE::MakeAttribute("reduction", "mean")); + + new_nodes.emplace_back(NodeDef("SoftmaxCrossEntropyLoss", + {ArgDef("gathered_prediction_transposed", gathered_prediction_transposed_type_proto), + ArgDef(masked_lm_ids, masked_lm_int64_type_proto)}, // Inputs + {ArgDef(mlm_loss, GetLossTypeProto(graph_defs)), // Outputs + ArgDef("probability_lm", gathered_prediction_transposed_type_proto)}, + attrs, "Masked_LM_Loss")); } @@ -111,11 +167,33 @@ GraphAugmenter::GraphDefs BertLoss::operator()(const Graph& graph, const LossFun ONNX_NAMESPACE::TensorProto_DataType_INT64, graph_defs); - new_nodes.emplace_back(NodeDef("SparseSoftmaxCrossEntropy", - {ArgDef(prediction_next_sentence), + // Transpose prediction_next_sentence with the following permutation: {0, n-1, 1, 2....n-2} because + // SoftmaxCrossEntropyLoss accepts scores of the shape {N, C, D1, D2...Dk}. + + TypeProto* prediction_next_sentence_transposed_type_proto = GetTransposedTypeProto(ns_prediction_arg, graph_defs); + const auto* logits_type_proto = ns_prediction_arg->TypeAsProto(); + const auto& dims = logits_type_proto->tensor_type().shape().dim(); + std::vector prediction_next_sentence_transposed_perm; + prediction_next_sentence_transposed_perm.emplace_back(static_cast(0)); + prediction_next_sentence_transposed_perm.emplace_back(static_cast(dims.size() - 1)); + + for (int i = 1; i < dims.size() - 1; i++) { + prediction_next_sentence_transposed_perm.emplace_back(static_cast(i)); + } + + new_nodes.emplace_back(NodeDef("Transpose", + {ArgDef(prediction_next_sentence)}, // Inputs + {ArgDef("prediction_next_sentence_transposed", + prediction_next_sentence_transposed_type_proto)}, // Outputs + {ONNX_NAMESPACE::MakeAttribute("perm", prediction_next_sentence_transposed_perm)}, + + "Transpose_prediction_next_sentence")); + + new_nodes.emplace_back(NodeDef("SoftmaxCrossEntropyLoss", + {ArgDef("prediction_next_sentence_transposed", prediction_next_sentence_transposed_type_proto), ArgDef(next_sentence_labels, next_sentence_labels_type_proto)}, // Inputs {ArgDef(nsp_loss, GetLossTypeProto(graph_defs)), - ArgDef("probability_ns", ns_prediction_arg->TypeAsProto())}, // Outputs + ArgDef("probability_ns", prediction_next_sentence_transposed_type_proto)}, // Outputs {ONNX_NAMESPACE::MakeAttribute("reduction", "mean")}, "Next_Sentence_Loss")); } @@ -136,7 +214,7 @@ GraphAugmenter::GraphDefs BertLoss::operator()(const Graph& graph, const LossFun } graph_defs.AddNodeDefs(new_nodes); - graph_defs.AddGraphInputs({masked_lm_positions, masked_lm_ids, masked_lm_weights, next_sentence_labels}); + graph_defs.AddGraphInputs({masked_lm_positions, masked_lm_ids, next_sentence_labels}); graph_defs.AddGraphOutputs({mlm_loss, nsp_loss, total_loss}); return graph_defs; diff --git a/orttraining/orttraining/core/graph/loss_func/bert_loss.h b/orttraining/orttraining/core/graph/loss_func/bert_loss.h index 787564baac..2a76a46b3a 100644 --- a/orttraining/orttraining/core/graph/loss_func/bert_loss.h +++ b/orttraining/orttraining/core/graph/loss_func/bert_loss.h @@ -15,8 +15,16 @@ struct BertLoss : public ILossFunction { static TypeProto* GetMaskedLMTypeProto(const NodeArg* prediction_arg, ONNX_NAMESPACE::TensorProto_DataType data_type, GraphAugmenter::GraphDefs& graph_defs); + static TypeProto* GetGatheredPredictionTypeProto(const NodeArg* prediction_arg, GraphAugmenter::GraphDefs& graph_defs); + + static TypeProto* GetGatheredPredictionTransposedTypeProto(const NodeArg* prediction_arg, + GraphAugmenter::GraphDefs& graph_defs); + + static TypeProto* GetTransposedTypeProto(const NodeArg* prediction_arg, + GraphAugmenter::GraphDefs& graph_defs); + static TypeProto* GetLossTypeProto(GraphAugmenter::GraphDefs& graph_defs); }; diff --git a/orttraining/orttraining/models/bert/main.cc b/orttraining/orttraining/models/bert/main.cc index bbde1866b9..752211e640 100644 --- a/orttraining/orttraining/models/bert/main.cc +++ b/orttraining/orttraining/models/bert/main.cc @@ -566,7 +566,6 @@ void setup_training_params(BertParameters& params) { /*prediction_next_sentence*/ "output2", /*masked_lm_positions*/ "masked_lm_positions", /*masked_lm_ids*/ "masked_lm_ids", - /*masked_lm_weights*/ "masked_lm_weights", /*next_sentence_labels*/ "next_sentence_labels", /*mlm_loss*/ "mlm_loss", /*nsp_loss*/ "nsp_loss"}); @@ -593,7 +592,6 @@ void setup_training_params(BertParameters& params) { {"input_mask", "input3"}, {"masked_lm_positions", "masked_lm_positions"}, {"masked_lm_ids", "masked_lm_ids"}, - {"masked_lm_weights", "masked_lm_weights"}, {"next_sentence_label", "next_sentence_labels"}}; params.model_type = "bert"; @@ -696,7 +694,6 @@ static Status RunPerformanceTest(const BertParameters& params, const Environment "input3", /*input_mask*/ "masked_lm_positions", "masked_lm_ids", - "masked_lm_weights", "next_sentence_labels"}; std::vector tensor_shapes = {{batch_size, params.max_sequence_length}, {batch_size, params.max_sequence_length}, diff --git a/orttraining/orttraining/test/graph/gradient_graph_builder_test.cc b/orttraining/orttraining/test/graph/gradient_graph_builder_test.cc index d8810ab73a..2e7ae8ffe9 100644 --- a/orttraining/orttraining/test/graph/gradient_graph_builder_test.cc +++ b/orttraining/orttraining/test/graph/gradient_graph_builder_test.cc @@ -5,6 +5,7 @@ #include "gtest/gtest.h" #include "orttraining/core/optimizer/gist_encode_decode.h" #include "test/providers/provider_test_utils.h" +#include "core/common/path_utils.h" #include "core/providers/cpu/cpu_execution_provider.h" #include "core/session/environment.h" #include "orttraining/models/runner/training_runner.h" @@ -19,6 +20,7 @@ using namespace onnxruntime::logging; using namespace onnxruntime::training; using namespace google::protobuf::util; +using namespace onnxruntime::path_utils; namespace onnxruntime { namespace test { @@ -330,7 +332,6 @@ static void RunBertTrainingWithChecks( "masked_lm_ids", "next_sentence_labels", "masked_lm_positions", - "masked_lm_weights", }; std::vector tensor_shapes = { {batch_size, max_seq_len_in_batch}, @@ -414,13 +415,11 @@ static void RunBertTrainingWithChecks( 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6}}; - std::vector masked_lm_weights(13 * 7, 1.0f); std::vector feeds(feed_names.size()); for (size_t i = 0; i < 6; ++i) { TrainingUtil::CreateCpuMLValue(tensor_shapes[i].GetDims(), tensor_values[i], &feeds[i]); } - TrainingUtil::CreateCpuMLValue(tensor_shapes[6].GetDims(), masked_lm_weights, &feeds[6]); auto output_names_include_gradients = GetModelOutputNames(*training_session); std::vector fetch_names(output_names_include_gradients.begin(), output_names_include_gradients.end()); @@ -475,7 +474,6 @@ TEST(GradientGraphBuilderTest, TrainingSession_BertToy) { /*prediction_next_sentence*/ "seq_relationship_score", /*masked_lm_positions*/ "masked_lm_positions", /*masked_lm_ids*/ "masked_lm_ids", - /*masked_lm_weights*/ "masked_lm_weights", /*next_sentence_labels*/ "next_sentence_labels", /*mlm_loss*/ "mlm_loss", /*nsp_loss*/ "nsp_loss"}); @@ -1117,10 +1115,8 @@ void RetrieveSendRecvOperators( } } -PathString GenerateFileNameWithIndex(const PathString& base_str, int index, const PathString& file_suffix) { - Path p; - ORT_ENFORCE(Path::Parse(base_str, p).IsOK()); - return p.ConcatIndex(index).Concat(file_suffix).ToPathString(); +PathString GenerateFileNameWithIndex(const std::string& base_str, int index, const std::string& file_suffix) { + return path_utils::MakePathString(base_str, index, file_suffix); } TEST(GradientGraphBuilderTest, PipelineOnlinePartition_bert_tiny) { @@ -1151,7 +1147,7 @@ TEST(GradientGraphBuilderTest, PipelineOnlinePartition_bert_tiny) { // graph is partitioned into 3 parts. for (int i = 0; i < static_cast(total_partition_count); ++i) { - PathString output_file = GenerateFileNameWithIndex(ORT_TSTR("pipeline_partition_"), i, ORT_TSTR("_back.onnx")); + PathString output_file = GenerateFileNameWithIndex("pipeline_partition_", i, "_back.onnx"); auto config = MakeBasicTrainingConfig(); if (i == static_cast(total_partition_count - 1)) { @@ -1163,7 +1159,6 @@ TEST(GradientGraphBuilderTest, PipelineOnlinePartition_bert_tiny) { /*prediction_next_sentence*/ "seq_relationship_score", /*masked_lm_positions*/ "masked_lm_positions", /*masked_lm_ids*/ "masked_lm_ids", - /*masked_lm_weights*/ "masked_lm_weights", /*next_sentence_labels*/ "next_sentence_labels", /*mlm_loss*/ "mlm_loss", /*nsp_loss*/ "nsp_loss"}); @@ -1244,7 +1239,7 @@ TEST(GradientGraphBuilderTest, PipelineOnlinePartition_MLP) { for(auto is_fp32 : test_with_fp32) { // graph is partitioned into 3 parts. for (int i = 0; i < 3; ++i) { - PathString output_file = GenerateFileNameWithIndex(ORT_TSTR("pipeline_partition_"), i, ORT_TSTR("_back.onnx")); + PathString output_file = GenerateFileNameWithIndex("pipeline_partition_", i, "_back.onnx"); auto config = MakeBasicTrainingConfig(); @@ -1291,7 +1286,7 @@ Status RunOnlinePartition(const std::vector sub_model_files(num_subs); for (size_t sub_id = 0; sub_id < num_subs; ++sub_id) { - sub_model_files[sub_id] = GenerateFileNameWithIndex(ORT_TSTR("sub_"), static_cast(sub_id), ORT_TSTR(".onnx")); + sub_model_files[sub_id] = GenerateFileNameWithIndex("sub_", static_cast(sub_id), ".onnx"); } PipelineSplitter splitter; @@ -1530,7 +1525,7 @@ TEST(GradientGraphBuilderTest, TrainingSession_WithPipeline) { for (size_t sub_id = 0; sub_id < num_subs; ++sub_id) { auto& sub_sess = subs[sub_id]; sub_sess.so.enable_profiling = true; - sub_sess.so.profile_file_prefix = GenerateFileNameWithIndex(ORT_TSTR("pipeline"), static_cast(sub_id), ORT_TSTR("")); + sub_sess.so.profile_file_prefix = GenerateFileNameWithIndex("pipeline", static_cast(sub_id), ""); sub_sess.run_options.run_log_verbosity_level = sub_sess.so.session_log_verbosity_level; sub_sess.run_options.run_tag = sub_sess.so.session_logid; diff --git a/tools/ci_build/github/azure-pipelines/templates/win-ci-2019.yml b/tools/ci_build/github/azure-pipelines/templates/win-ci-2019.yml index 7ab140b5e6..afce749d2a 100644 --- a/tools/ci_build/github/azure-pipelines/templates/win-ci-2019.yml +++ b/tools/ci_build/github/azure-pipelines/templates/win-ci-2019.yml @@ -151,15 +151,16 @@ jobs: arguments: '--configuration $(BuildConfig) -p:Platform="Any CPU" -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=${{ parameters.OrtPackageId }}' workingDirectory: '$(Build.SourcesDirectory)\csharp' - - ${{ if and(eq(parameters.BuildCSharp, true), in(parameters['sln_platform'], 'Win32', 'x64')) }}: - - task: DotNetCoreCLI@2 - displayName: 'Test C#' - inputs: - command: test - projects: '$(Build.SourcesDirectory)\csharp\test\Microsoft.ML.OnnxRuntime.Tests\Microsoft.ML.OnnxRuntime.Tests.csproj' - configuration: '$(BuildConfig)' - arguments: '--configuration $(BuildConfig) -p:Platform="Any CPU" -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=${{ parameters.OrtPackageId }}' - workingDirectory: '$(Build.SourcesDirectory)\csharp' + - ${{ if in(parameters['sln_platform'], 'Win32', 'x64') }}: + - ${{ if eq(parameters.BuildCSharp, true) }}: + - task: DotNetCoreCLI@2 + displayName: 'Test C#' + inputs: + command: test + projects: '$(Build.SourcesDirectory)\csharp\test\Microsoft.ML.OnnxRuntime.Tests\Microsoft.ML.OnnxRuntime.Tests.csproj' + configuration: '$(BuildConfig)' + arguments: '--configuration $(BuildConfig) -p:Platform="Any CPU" -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=${{ parameters.OrtPackageId }}' + workingDirectory: '$(Build.SourcesDirectory)\csharp' - ${{ if eq(parameters.RunTests, true) }}: - script: | diff --git a/winml/lib/Common/inc/WinMLTelemetryHelper.h b/winml/lib/Common/inc/WinMLTelemetryHelper.h index 8809082478..a4bac4c788 100644 --- a/winml/lib/Common/inc/WinMLTelemetryHelper.h +++ b/winml/lib/Common/inc/WinMLTelemetryHelper.h @@ -44,7 +44,7 @@ class Profiler; // WinMLRuntime Telemetry Support // // {BCAD6AEE-C08D-4F66-828C-4C43461A033D} -#define WINML_PROVIDER_DESC "Windows AI Machine Learning" +#define WINML_PROVIDER_DESC "Microsoft.Windows.AI.MachineLearning" #define WINML_PROVIDER_GUID (0xbcad6aee, 0xc08d, 0x4f66, 0x82, 0x8c, 0x4c, 0x43, 0x46, 0x1a, 0x3, 0x3d) #define WINML_PROVIDER_KEYWORD_DEFAULT 0x1 #define WINML_PROVIDER_KEYWORD_LOTUS_PROFILING 0x2