diff --git a/.jenkins/check/config/whitelizard.txt b/.jenkins/check/config/whitelizard.txt index 7edf88646bb..52eea23b2ce 100644 --- a/.jenkins/check/config/whitelizard.txt +++ b/.jenkins/check/config/whitelizard.txt @@ -11,6 +11,7 @@ mindspore/mindspore/lite/providers/nnie_proposal/src/proposal.cc:mindspore::prop mindspore/mindspore/core/abstract/ops/primitive_infer_map.cc:mindspore::abstract::GetPrimitiveToEvalImplMap mindspore/mindspore/core/abstract/ops/primitive_infer_map.cc:mindspore::abstract::GetHostDependsMap mindspore/mindspore/core/ir/tensor.cc:mindspore::tensor::MakeTensorData +mindspore/mindspore/ccsrc/kernel/common_utils.cc:mindspore::kernel::UnitSizeInBytes mindspore/mindspore/ccsrc/frontend/optimizer/irpass.cc:mindspore::opt::irpass::OptimizeIRPassLib::OptimizeIRPassLib mindspore/mindspore/ccsrc/frontend/parallel/ops_info/gather_v2_p_info.cc:mindspore::parallel::GatherV2PInfo::CheckStrategy mindspore/mindspore/ccsrc/plugin/device/gpu/hal/device/gpu_kernel_runtime.cc:mindspore::device::gpu::GPUKernelRuntime::LaunchKernelDynamic diff --git a/mindspore/ccsrc/kernel/common_utils.cc b/mindspore/ccsrc/kernel/common_utils.cc index d2c7c9e2a78..6f21677b445 100644 --- a/mindspore/ccsrc/kernel/common_utils.cc +++ b/mindspore/ccsrc/kernel/common_utils.cc @@ -1113,6 +1113,9 @@ size_t UnitSizeInBytes(const mindspore::TypeId &t) { case kNumberTypeComplex128: bytes = sizeof(double) * complex_factor; break; + case kObjectTypeString: + bytes = sizeof(std::string); + break; case kNumberTypeInt4: default: MS_LOG(EXCEPTION) << "Invalid types for UnitSizeInBytes : " << TypeIdToString(t); diff --git a/mindspore/ccsrc/plugin/device/cpu/hal/hardware/cpu_device_context.cc b/mindspore/ccsrc/plugin/device/cpu/hal/hardware/cpu_device_context.cc index 09d5ada957f..6d5c8a7d702 100644 --- a/mindspore/ccsrc/plugin/device/cpu/hal/hardware/cpu_device_context.cc +++ b/mindspore/ccsrc/plugin/device/cpu/hal/hardware/cpu_device_context.cc @@ -20,6 +20,7 @@ #include "plugin/device/cpu/hal/device/cpu_device_address.h" #include "plugin/device/cpu/hal/device/cpu_memory_manager.h" #include "plugin/device/cpu/optimizer/reg_cpu_const_input_to_attr.h" +#include "plugin/device/cpu/optimizer/print_value_type.h" #include "plugin/device/cpu/hal/hardware/cpu_somas.h" #ifdef ENABLE_AKG #include "plugin/device/cpu/kernel/akg/akg_cpu_kernel_build.h" @@ -182,6 +183,7 @@ void CPUKernelExecutor::OptimizeGraphImpl(const KernelGraphPtr &graph) const { pm->AddPass(std::make_shared()); pm->AddPass(std::make_shared()); pm->AddPass(std::make_shared()); + pm->AddPass(std::make_shared("print_value_type")); optimizer->AddPassManager(pm); (void)optimizer->Optimize(graph); graph->SetExecOrderByDefault(); diff --git a/mindspore/ccsrc/plugin/device/cpu/hal/hardware/cpu_session.cc b/mindspore/ccsrc/plugin/device/cpu/hal/hardware/cpu_session.cc index 581c2faed65..54b6bb21bcd 100644 --- a/mindspore/ccsrc/plugin/device/cpu/hal/hardware/cpu_session.cc +++ b/mindspore/ccsrc/plugin/device/cpu/hal/hardware/cpu_session.cc @@ -27,6 +27,7 @@ #include "plugin/factory/ms_factory.h" #include "runtime/device/kernel_runtime.h" #include "plugin/device/cpu/kernel/cpu_kernel.h" +#include "plugin/device/cpu/optimizer/print_value_type.h" #ifdef ENABLE_AKG #include "plugin/device/cpu/kernel/akg/akg_cpu_kernel_build.h" #endif @@ -105,6 +106,7 @@ void CPUSession::Optimize(const std::shared_ptr &kernel_graph) { pm->AddPass(std::make_shared("insert_format_transform_op_cpu")); pm->AddPass(std::make_shared("insert_cast")); pm->AddPass(std::make_shared()); + pm->AddPass(std::make_shared("print_value_type")); optimizer->AddPassManager(pm); (void)optimizer->Optimize(kernel_graph); kernel_graph->SetExecOrderByDefault(); diff --git a/mindspore/ccsrc/plugin/device/cpu/kernel/print_cpu_kernel.cc b/mindspore/ccsrc/plugin/device/cpu/kernel/print_cpu_kernel.cc index 1bf25b60b17..3abd0ebab1a 100644 --- a/mindspore/ccsrc/plugin/device/cpu/kernel/print_cpu_kernel.cc +++ b/mindspore/ccsrc/plugin/device/cpu/kernel/print_cpu_kernel.cc @@ -15,11 +15,13 @@ */ #include "plugin/device/cpu/kernel/print_cpu_kernel.h" +#include #include #include #include #include #include "ir/tensor.h" +#include "ops/print.h" #include "plugin/device/cpu/hal/device/cpu_device_address.h" namespace mindspore { @@ -36,6 +38,14 @@ bool PrintCpuKernelMod::Init(const BaseOperatorPtr &base_operator, const std::ve TypeId type = inputs[i]->GetDtype(); (void)data_types_.emplace_back(type); } + auto kernel_ptr = std::dynamic_pointer_cast(base_operator); + if (kernel_ptr->HasAttr("value_type")) { + auto value_type = kernel_ptr->get_value_type(); + auto value_type_pos = kernel_ptr->get_value_type_pos(); + for (size_t i = 0; i < value_type.size(); i++) { + value_type_[value_type_pos[i]] = value_type[i]; + } + } return true; } @@ -46,9 +56,9 @@ int PrintCpuKernelMod::Resize(const BaseOperatorPtr &base_operator, const std::v if (ret != KRET_OK) { return ret; } - input_sizes_.clear(); input_shapes_.clear(); + input_info_.clear(); for (size_t i = 0; i < inputs.size(); ++i) { MS_EXCEPTION_IF_NULL(inputs[i]); auto input_shape = inputs[i]->GetShapeVector(); @@ -57,7 +67,11 @@ int PrintCpuKernelMod::Resize(const BaseOperatorPtr &base_operator, const std::v for (size_t j = 0; j < input_shape.size(); ++j) { size *= input_shape[j]; } + auto type_id = inputs[i]->GetDtype(); + size_t unit_size = UnitSizeInBytes(type_id); + auto size_in_byte = std::accumulate(input_shape.begin(), input_shape.end(), unit_size, std::multiplies()); (void)input_sizes_.emplace_back(LongToSize(size)); + input_info_.push_back(std::make_tuple(size_in_byte, type_id)); } return ret; } @@ -91,8 +105,20 @@ void PrintCpuKernelMod::LaunchKernel(size_t index, const std::vector(input_info_[index]); Tensor tensor(data_types_[index], input_shapes_[index], inputs[index]->addr, input_sizes_[index] * sizeof(T)); - std::cout << tensor.ToStringNoLimit() << std::endl; + if (value_type_.count(index) > 0) { + // not a tensor + auto out = tensor.data().ToString(type_id, input_shapes_[index], true); + if (value_type_[index] != 0) { + // tuple, not scalar + (void)std::replace(out.begin(), out.end(), '[', '('); + (void)std::replace(out.begin(), out.end(), ']', ')'); + } + std::cout << out << std::endl; + } else { + std::cout << tensor.ToStringNoLimit() << std::endl; + } } } diff --git a/mindspore/ccsrc/plugin/device/cpu/kernel/print_cpu_kernel.h b/mindspore/ccsrc/plugin/device/cpu/kernel/print_cpu_kernel.h index 92982137e73..d1a74be19df 100644 --- a/mindspore/ccsrc/plugin/device/cpu/kernel/print_cpu_kernel.h +++ b/mindspore/ccsrc/plugin/device/cpu/kernel/print_cpu_kernel.h @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "plugin/device/cpu/kernel/cpu_kernel.h" #include "plugin/factory/ms_factory.h" @@ -54,6 +56,9 @@ class PrintCpuKernelMod : public NativeCpuKernelMod { std::vector input_shapes_; std::vector input_sizes_; std::vector data_types_; + + std::unordered_map value_type_; + std::vector> input_info_; }; } // namespace kernel } // namespace mindspore diff --git a/mindspore/ccsrc/plugin/device/cpu/optimizer/print_value_type.cc b/mindspore/ccsrc/plugin/device/cpu/optimizer/print_value_type.cc new file mode 100644 index 00000000000..cbef795c72e --- /dev/null +++ b/mindspore/ccsrc/plugin/device/cpu/optimizer/print_value_type.cc @@ -0,0 +1,144 @@ +/** + * Copyright 2022 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "plugin/device/cpu/optimizer/print_value_type.h" + +#include +#include +#include +#include +#include +#include "backend/common/session/anf_runtime_algorithm.h" +#include "include/common/utils/anfalgo.h" +#include "ir/primitive.h" +#include "include/common/utils/utils.h" +#include "backend/common/optimizer/helper.h" + +namespace mindspore { +namespace opt { +kernel::KernelBuildInfoPtr GenerateKernelBuildInfo(CNodePtr node) { + std::vector inputs_format; + std::vector outputs_format; + std::vector inputs_type; + std::vector outputs_type; + kernel::KernelBuildInfo::KernelBuildInfoBuilder builder; + + size_t input_num = common::AnfAlgo::GetInputTensorNum(node); + for (size_t input_index = 0; input_index < input_num; input_index++) { + inputs_format.push_back(kOpFormat_DEFAULT); + inputs_type.push_back(common::AnfAlgo::GetPrevNodeOutputInferDataType(node, input_index)); + } + size_t output_num = common::AnfAlgo::GetOutputTensorNum(node); + for (size_t output_index = 0; output_index < output_num; output_index++) { + outputs_format.push_back(kOpFormat_DEFAULT); + outputs_type.push_back(common::AnfAlgo::GetOutputInferDataType(node, output_index)); + } + + builder.SetInputsFormat(inputs_format); + builder.SetOutputsFormat(outputs_format); + builder.SetInputsDeviceType(inputs_type); + builder.SetOutputsDeviceType(outputs_type); + return builder.Build(); +} + +bool GetOptList(const std::vector &node_list, std::vector *opt_list, + std::vector>> *not_tensor_pos_vec) { + MS_EXCEPTION_IF_NULL(opt_list); + + for (auto &node : node_list) { + // {prim::kPrimPrint} reduction only applies on print with string, tensor(scalar or tuple) + MS_EXCEPTION_IF_NULL(node); + std::vector> value_type; + if (!IsPrimitiveCNode(node, prim::kPrimPrint)) { + continue; + } + size_t input_num = common::AnfAlgo::GetInputTensorNum(node); + for (size_t i = 0; i < input_num; i++) { + auto current_node = common::AnfAlgo::GetInputNode(utils::cast(node), i); + // not tensor(tuple, scalar, string) + if (current_node->cast() == nullptr) { + continue; + } + + auto value_node = current_node->cast(); + MS_EXCEPTION_IF_NULL(value_node); + auto shape = value_node->abstract(); + MS_EXCEPTION_IF_NULL(shape); + auto shape_node = dyn_cast(shape->GetShapeTrack()); + if (shape_node != nullptr) { + // a scalar or tuple + auto shape_size = shape_node->shape().size(); + if (shape_size != 0) { + value_type.push_back(std::make_pair(i, 1)); + } else { + value_type.push_back(std::make_pair(i, 0)); + } + } + } + if (value_type.size() != 0) { + opt_list->push_back(node); + not_tensor_pos_vec->push_back(value_type); + } + } + if (opt_list->size() == 0) { + return false; + } + return true; +} + +bool PrintValueType::Run(const FuncGraphPtr &graph) { + MS_EXCEPTION_IF_NULL(graph); + auto manager = graph->manager(); + MS_EXCEPTION_IF_NULL(manager); + std::vector node_list = TopoSort(graph->get_return()); + std::vector opt_list; + // first is pos, second is type: 0 is Scalar, 1 is ValueTuple + std::vector>> not_tensor_pos_vec; + if (!GetOptList(node_list, &opt_list, ¬_tensor_pos_vec)) { + return false; + } + for (size_t idx = 0; idx < opt_list.size(); idx++) { + auto node = opt_list[idx]; + CNodePtr cnode = utils::cast(node); + MS_EXCEPTION_IF_NULL(cnode); + auto value_type_vec = not_tensor_pos_vec[idx]; + // split value type and pos + std::vector value_type_pos; + std::vector value_type; + (void)std::transform(value_type_vec.begin(), value_type_vec.end(), std::back_inserter(value_type_pos), + [](const std::pair &value) { return value.first; }); + (void)std::transform(value_type_vec.begin(), value_type_vec.end(), std::back_inserter(value_type), + [](const std::pair &value) { return value.second; }); + + // hand over the attrs to new print + common::AnfAlgo::SetNodeAttr("value_type", MakeValue>(value_type), cnode); + common::AnfAlgo::SetNodeAttr("value_type_pos", MakeValue>(value_type_pos), cnode); + // set output type and shape + std::vector types; + std::vector shapes; + size_t output_num = common::AnfAlgo::GetOutputTensorNum(cnode); + for (size_t i = 0; i < output_num; i++) { + types.push_back(common::AnfAlgo::GetOutputInferDataType(cnode, i)); + shapes.push_back(common::AnfAlgo::GetOutputDetailShape(cnode, i)); + } + common::AnfAlgo::SetOutputTypeAndDetailShape(types, shapes, cnode.get()); + // add build info + auto build_info = GenerateKernelBuildInfo(cnode); + AnfAlgo::SetSelectKernelBuildInfo(build_info, cnode.get()); + } + return true; +} +} // namespace opt +} // namespace mindspore diff --git a/mindspore/ccsrc/plugin/device/cpu/optimizer/print_value_type.h b/mindspore/ccsrc/plugin/device/cpu/optimizer/print_value_type.h new file mode 100644 index 00000000000..f6e10296d1f --- /dev/null +++ b/mindspore/ccsrc/plugin/device/cpu/optimizer/print_value_type.h @@ -0,0 +1,32 @@ +/** + * Copyright 2022 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MINDSPORE_CCSRC_PLUGIN_DEVICE_CPU_OPTIMIZER_PRINT_VALUE_TYPE_H_ +#define MINDSPORE_CCSRC_PLUGIN_DEVICE_CPU_OPTIMIZER_PRINT_VALUE_TYPE_H_ + +#include +#include "backend/common/optimizer/optimizer.h" + +namespace mindspore { +namespace opt { +class PrintValueType : public Pass { + public: + explicit PrintValueType(const std::string &name) : Pass("print_value_type") {} + ~PrintValueType() override = default; + bool Run(const FuncGraphPtr &graph) override; +}; +} // namespace opt +} // namespace mindspore +#endif // MINDSPORE_CCSRC_PLUGIN_DEVICE_CPU_OPTIMIZER_PRINT_VALUE_TYPE_H_ diff --git a/tests/st/ops/cpu/test_print_op.py b/tests/st/ops/cpu/test_print_op.py index ec7b5a4ac7d..4a8de8d095b 100644 --- a/tests/st/ops/cpu/test_print_op.py +++ b/tests/st/ops/cpu/test_print_op.py @@ -91,3 +91,24 @@ def test_print_op_functional(mode): net = PrintFunc() x = Tensor(np.random.randn(3, 4, 5).astype(np.float32)) net(x) + + +@pytest.mark.level0 +@pytest.mark.env_onecard +@pytest.mark.platform_x86_cpu +def test_print_op_tuple(): + """ + Feature: cpu Print op. + Description: test Print with tuple input. + Expectation: success. + """ + class PrintTupleNet(nn.Cell): + def construct(self, x): + tuple_x = tuple((1, 2, 3, 4, 5)) + ops.print_("tuple_x:", tuple_x, x, "print success!") + return x + + context.set_context(mode=context.GRAPH_MODE, device_target="CPU") + net = PrintTupleNet() + x = Tensor([6, 7, 8, 9, 10]) + net(x) diff --git a/tests/st/ops/gpu/test_print_op.py b/tests/st/ops/gpu/test_print_op.py index be10913cc2b..b045fee3895 100644 --- a/tests/st/ops/gpu/test_print_op.py +++ b/tests/st/ops/gpu/test_print_op.py @@ -177,3 +177,25 @@ def test_print_dynamic_shape(mode): x_dyn = Tensor(shape=[None, None, None], dtype=ms.float32) net.set_inputs(x_dyn) net(x) + + +@security_off_wrap +@pytest.mark.level1 +@pytest.mark.env_onecard +@pytest.mark.platform_x86_gpu_training +def test_print_op_tuple(): + """ + Feature: cpu Print op. + Description: test Print with tuple input. + Expectation: success. + """ + class PrintTupleNet(nn.Cell): + def construct(self, x): + tuple_x = tuple((1, 2, 3, 4, 5)) + print("tuple_x:", tuple_x, x, "print success!") + return x + + context.set_context(mode=context.GRAPH_MODE, device_target="GPU") + net = PrintTupleNet() + x = Tensor([6, 7, 8, 9, 10]) + net(x)