diff --git a/onnxruntime/core/optimizer/nchwc_transformer.cc b/onnxruntime/core/optimizer/nchwc_transformer.cc index 1fc98e3e98..b19f167c54 100644 --- a/onnxruntime/core/optimizer/nchwc_transformer.cc +++ b/onnxruntime/core/optimizer/nchwc_transformer.cc @@ -684,7 +684,7 @@ void NchwcTransformerImpl::Transform(Node& node) { if (graph_utils::IsSupportedOptypeVersionAndDomain(node, "Add", {7}) || graph_utils::IsSupportedOptypeVersionAndDomain(node, "Sum", {6, 8})) { TransformAdd(node); - } else if (graph_utils::IsSupportedOptypeVersionAndDomain(node, "Concat", {4})) { + } else if (graph_utils::IsSupportedOptypeVersionAndDomain(node, "Concat", {4, 11})) { TransformConcat(node); } else if (graph_utils::IsSupportedOptypeVersionAndDomain(node, "Relu", {6})) { TransformActivation(node); diff --git a/onnxruntime/test/optimizer/nchwc_optimizer_test.cc b/onnxruntime/test/optimizer/nchwc_optimizer_test.cc index 69f3e8be1a..0fd8746075 100644 --- a/onnxruntime/test/optimizer/nchwc_optimizer_test.cc +++ b/onnxruntime/test/optimizer/nchwc_optimizer_test.cc @@ -79,27 +79,29 @@ struct NchwcTestHelper { return &graph_.GetOrCreateNodeArg(name, nullptr); } - NodeArg* MakeInitializer(const std::vector& shape) { + NodeArg* MakeInitializer(const std::vector& shape, const std::vector& data) { std::string name = graph_.GenerateNodeArgName("constant"); ONNX_NAMESPACE::TensorProto tensor_proto; tensor_proto.set_name(name); tensor_proto.set_data_type(ONNX_NAMESPACE::TensorProto_DataType_FLOAT); - int64_t num_elements = 1; for (auto& dim : shape) { tensor_proto.add_dims(dim); - num_elements *= dim; } - auto random_data = FillRandomData(static_cast(num_elements)); - tensor_proto.mutable_float_data()->Resize(static_cast(num_elements), 0.0f); - memcpy(tensor_proto.mutable_float_data()->mutable_data(), random_data.data(), random_data.size() * sizeof(float)); + tensor_proto.mutable_float_data()->Resize(static_cast(data.size()), 0.0f); + memcpy(tensor_proto.mutable_float_data()->mutable_data(), data.data(), data.size() * sizeof(float)); graph_.AddInitializedTensor(tensor_proto); return &graph_.GetOrCreateNodeArg(name, nullptr); } + NodeArg* MakeInitializer(const std::vector& shape) { + int64_t num_elements = std::accumulate(shape.begin(), shape.end(), int64_t(1), std::multiplies{}); + return MakeInitializer(shape, FillRandomData(static_cast(num_elements))); + } + Node& AddNode(const std::string& op_type, const std::vector& input_args, const std::vector& output_args) { @@ -120,6 +122,21 @@ struct NchwcTestHelper { return AddNode("Conv", input_args, {output_arg}); } + Node& AddClipNode(NodeArg* input_arg, NodeArg* output_arg, float min, float max) { + int opset_version = graph_.DomainToVersionMap().find(kOnnxDomain)->second; + std::vector input_args = {input_arg}; + if (opset_version >= 11) { + input_args.push_back(MakeInitializer({1}, {min})); + input_args.push_back(MakeInitializer({1}, {max})); + } + auto& node = AddNode("Clip", input_args, {output_arg}); + if (opset_version < 11) { + node.AddAttribute("min", min); + node.AddAttribute("max", max); + } + return node; + } + std::vector FillRandomData(size_t count) { constexpr int min_fill_value = -23; constexpr int max_fill_value = 23; @@ -144,7 +161,7 @@ struct NchwcTestHelper { void NchwcOptimizerTester(const std::function& build_test_case, const std::function& check_nchwc_graph, - int opset_version = 10) { + int opset_version = 11) { // Ignore the test if NCHWc is not supported by the platform. if (MlasNchwcGetBlockSize() <= 1) { return; @@ -215,10 +232,10 @@ TEST(NchwcOptimizerTests, ConvNchw) { auto* conv_output_arg = output_arg; if (!activation_op_type.empty()) { conv_output_arg = helper.MakeIntermediate(); - auto& act_node = helper.AddNode(activation_op_type, {conv_output_arg}, {output_arg}); if (activation_op_type == "Clip") { - act_node.AddAttribute("min", 0.0f); - act_node.AddAttribute("max", 6.0f); + helper.AddClipNode(conv_output_arg, output_arg, 0.0f, 6.0f); + } else { + helper.AddNode(activation_op_type, {conv_output_arg}, {output_arg}); } } @@ -255,10 +272,10 @@ TEST(NchwcOptimizerTests, ConvNchwc) { auto* conv_output_arg = output_arg; if (!activation_op_type.empty()) { conv_output_arg = helper.MakeIntermediate(); - auto& act_node = helper.AddNode(activation_op_type, {conv_output_arg}, {output_arg}); if (activation_op_type == "Clip") { - act_node.AddAttribute("min", -6.0f); - act_node.AddAttribute("max", 6.0f); + helper.AddClipNode(conv_output_arg, output_arg, -6.0f, 6.0f); + } else { + helper.AddNode(activation_op_type, {conv_output_arg}, {output_arg}); } } @@ -533,7 +550,7 @@ TEST(NchwcOptimizerTests, ConvAddFusion) { // Verify that Add or Sum can be fused into a preceding NCHWc Conv node, // with an optional Relu node following. std::vector op_types = {"Add", "Sum"}; - static const int opset_versions[] = {7, 10}; + static const int opset_versions[] = {7, 10, 11}; for (auto& op_type : op_types) { for (auto opset_version : opset_versions) { test_case(op_type, opset_version, false);