Merge remote-tracking branch 'upstream/master' into DmlDev

This commit is contained in:
ISS Build Account 2020-07-17 12:25:12 +00:00
commit 5b7050321f
30 changed files with 305 additions and 164 deletions

View file

@ -432,8 +432,12 @@ struct SetMapTypes {
TensorElementTypeSetter<K>::SetMapKeyType(proto);
MLDataType dt = GetMLDataType<V, IsTensorContainedType<V>::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<T, IsTensorContainedType<T>::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);
}
};

View file

@ -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,

View file

@ -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;
}

View file

@ -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);

View file

@ -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 <typename... Args>
PathString MakePathString(const Args&... args) {
const std::string str = onnxruntime::MakeString(args...);
return ToPathString(str);
}
}
}

View file

@ -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;
}

View file

@ -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<size_t> clen(strlen(msg));
SafeInt<size_t> clen(nullptr == msg ? 0 : strlen(msg));
OrtStatus* p = reinterpret_cast<OrtStatus*>(::malloc(sizeof(OrtStatus) + clen));
if (p == nullptr) return nullptr; // OOM. What we can do here? abort()?
p->code = code;

View file

@ -233,9 +233,8 @@ Status KernelRegistry::TryCreateKernel(const onnxruntime::Node& node,
const FuncManager& funcs_mgr,
const DataTransferManager& data_transfer_mgr,
/*out*/ std::unique_ptr<OpKernel>& 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,

View file

@ -698,7 +698,7 @@ common::Status SparseTensorProtoToDenseTensorProto(const ONNX_NAMESPACE::SparseT
auto dims = gsl::make_span<const int64_t>(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) {

View file

@ -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]);

View file

@ -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<MLFloat16>() &&
casted) {

View file

@ -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);

View file

@ -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<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, int32_t,
MatMul)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, uint32_t,
MatMul)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, int64_t,
MatMul)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, uint64_t,
MatMul)>,
// Opset 10
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, StringNormalizer)>,

View file

@ -144,7 +144,7 @@ Status CumSum<T>::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

View file

@ -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 <typename T>
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<int32_t>()),
KernelDefBuilder()
.TypeConstraint("T", {DataTypeImpl::GetTensorType<int32_t>(), DataTypeImpl::GetTensorType<uint32_t>()}),
MatMul<int32_t>);
ONNX_CPU_OPERATOR_TYPED_KERNEL(
MatMul,
9,
uint32_t,
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<uint32_t>()),
MatMul<uint32_t>);
ONNX_CPU_OPERATOR_TYPED_KERNEL(
MatMul,
9,
int64_t,
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<int64_t>()),
KernelDefBuilder()
.TypeConstraint("T", {DataTypeImpl::GetTensorType<int64_t>(), DataTypeImpl::GetTensorType<uint64_t>()}),
MatMul<int64_t>);
ONNX_CPU_OPERATOR_TYPED_KERNEL(
MatMul,
9,
uint64_t,
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<uint64_t>()),
MatMul<uint64_t>);
template <typename T>
Status MatMul<T>::Compute(OpKernelContext* ctx) const {
concurrency::ThreadPool* thread_pool = ctx->GetOperatorThreadPool();
const auto* left_X = ctx->Input<Tensor>(0);
const auto* right_X = ctx->Input<Tensor>(1);
const auto* a = ctx->Input<Tensor>(0);
const auto* b = ctx->Input<Tensor>(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<const T*>(a->DataRaw());
const auto* b_data = reinterpret_cast<const T*>(b->DataRaw());
auto* y_data = reinterpret_cast<T*>(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<T>::Compute(OpKernelContext* ctx) const {
static_cast<int>(helper.M()),
static_cast<int>(helper.N()),
static_cast<int>(helper.K()),
left_X->template Data<T>() + helper.LeftOffsets()[i],
right_X->template Data<T>() + helper.RightOffsets()[i],
Y->template MutableData<T>() + 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();

View file

@ -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 <typename T>
class MatMul final : public OpKernel {
public:
MatMul(const OpKernelInfo& info)
: OpKernel(info) {
}
Status Compute(OpKernelContext* context) const override;
};
} // namespace onnxruntime

View file

@ -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;

View file

@ -157,7 +157,11 @@ inline void CastFromStringData(const Tensor* in, Tensor* out, const TensorShape&
mutable_data[i] = std::stoull(in->Data<std::string>()[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

View file

@ -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

View file

@ -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<std::string>& 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

View file

@ -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> 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

View file

@ -401,7 +401,7 @@ Status TensorProtoToMLValue(const onnx::TensorProto& tensor_proto, const MemBuff
if (static_cast<uint64_t>(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)

Binary file not shown.

View file

@ -0,0 +1,17 @@

F
input_0output_0RandomNormalLike1"RandomNormalLike*
dtype
 
G
output_0output_1RandomNormalLike2"RandomNormalLike*
dtype Reshape_FusionZ
input_0


b
output_1

B

View file

@ -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<NodeDef> 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<int64_t>(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<int64_t>{static_cast<int64_t>(0),
static_cast<int64_t>(2), static_cast<int64_t>(1)})},
"Transpose_gathered_prediction"));
std::vector<AttributeProto> attrs;
attrs.push_back(ONNX_NAMESPACE::MakeAttribute("ignore_index", static_cast<int64_t>(-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<int64_t> prediction_next_sentence_transposed_perm;
prediction_next_sentence_transposed_perm.emplace_back(static_cast<int64_t>(0));
prediction_next_sentence_transposed_perm.emplace_back(static_cast<int64_t>(dims.size() - 1));
for (int i = 1; i < dims.size() - 1; i++) {
prediction_next_sentence_transposed_perm.emplace_back(static_cast<int64_t>(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;

View file

@ -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);
};

View file

@ -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<TensorShape> tensor_shapes = {{batch_size, params.max_sequence_length},
{batch_size, params.max_sequence_length},

View file

@ -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<TensorShape> 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<float> masked_lm_weights(13 * 7, 1.0f);
std::vector<OrtValue> 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<std::string> 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<int>(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<int>(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<TrainingSession::TrainingConfigurati
pipe.cut_list = cut_list;
for (int i = 0; i < pipeline_stage_size; ++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();
config.pipeline_config = pipe;
@ -1336,7 +1331,7 @@ TEST(GradientGraphBuilderTest, PipelineOnlinePartition_Invalid_Input) {
// verify pipeline config can load and gradient graph can construct.
TEST(GradientGraphBuilderTest, TrainingSession_PipelineTransform_base) {
PathString filename_base = ORT_TSTR("testdata/test_training_model_");
std::string filename_base = "testdata/test_training_model_";
auto load_and_check_gradient_graph = [](int stageIdx, PathString& input_file, PathString& output_file) {
auto config = MakeBasicTrainingConfig();
@ -1442,8 +1437,8 @@ TEST(GradientGraphBuilderTest, TrainingSession_PipelineTransform_base) {
};
for (int i = 0; i < 3; ++i) {
PathString input_file = GenerateFileNameWithIndex(filename_base, i, ORT_TSTR(".onnx"));
PathString output_file = GenerateFileNameWithIndex(filename_base, i, ORT_TSTR("_back.onnx"));
PathString input_file = GenerateFileNameWithIndex(filename_base, i, ".onnx");
PathString output_file = GenerateFileNameWithIndex(filename_base, i, "_back.onnx");
load_and_check_gradient_graph(i, input_file, output_file);
}
@ -1510,7 +1505,7 @@ TEST(GradientGraphBuilderTest, TrainingSession_WithPipeline) {
std::vector<PathString> 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<int>(sub_id), ORT_TSTR(".onnx"));
sub_model_files[sub_id] = GenerateFileNameWithIndex("sub_", static_cast<int>(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<int>(sub_id), ORT_TSTR(""));
sub_sess.so.profile_file_prefix = GenerateFileNameWithIndex("pipeline", static_cast<int>(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;

View file

@ -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: |

View file

@ -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