ADD file via upload

This commit is contained in:
zyf1234 2023-08-27 15:04:13 +08:00
parent 26ecc29329
commit dab0e8e7ff
1 changed files with 392 additions and 0 deletions

392
op_adapter_util.cc Normal file
View File

@ -0,0 +1,392 @@
/**
* Copyright 2019 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 "transform/graph_ir/op_adapter_util.h"
#include <string>
#include <vector>
#include <algorithm>
#include "include/common/utils/utils.h"
#include "utils/check_convert_utils.h"
#include "transform/graph_ir/op_adapter_base.h"
#include "transform/graph_ir/io_format_map.h"
namespace mindspore {
namespace transform {
// ConvertAnyUtil 函数用于将 MindSpore 中的 Tensormindspore::tensor::Tensor转换为 GEGraphEngine中的TensorGeTensor
GeTensor ConvertAnyUtil(const ValuePtr &value, const AnyTraits<mindspore::tensor::Tensor> &) {
// To-DO the format may read from ME tensor
// TODO可能需要从 MEMindSpore Execution Tensor 读取格式信息format
MS_EXCEPTION_IF_NULL(value);
//// 将 value 强制转换为 MeTensorPtr 类型MeTensorPtr 是一个智能指针,表示 ME TensorMindSpore Execution Tensor
auto me_tensor = value->cast<MeTensorPtr>();
// 调用 TransformUtil::ConvertTensor 函数将 ME Tensor 转换为 GE Tensor。
// 这里的 kOpFormat_ND 是指定转换后的 GE Tensor 使用的格式,可能是 ND 格式N-Dimensional
auto ge_tensor = TransformUtil::ConvertTensor(me_tensor, kOpFormat_ND);
// 如果转换后的 GE Tensor 为空,则返回一个空的 GeTensor 对象,否则返回转换后的 GE Tensor。
return ge_tensor == nullptr ? GeTensor() : *ge_tensor;
}
// ConvertAnyUtil 函数用于将一个 ValuePtr 类型的值转换为 std::vector<int64_t> 类型。
// 转换的方式取决于传入的 name 参数和数据类型 AnyTraits<std::vector<int64_t>>。
std::vector<int64_t> ConvertAnyUtil(const ValuePtr &value, const std::string &name,
const AnyTraits<std::vector<int64_t>>) {
MS_EXCEPTION_IF_NULL(value);
std::vector<int64_t> list; // 创建一个 int64_t 类型的 vector用于存储转换后的结果。
if (name == "pad") { // 如果传入的 name 是 "pad",则执行特定的转换逻辑。
if (!value->isa<ValueSequence>()) { // 确保 value 是 ValueSequence 类型。
MS_LOG(EXCEPTION) << "Value should be ValueTuple, but got" << value->type_name();
}
auto vec = value->cast<ValueSequencePtr>(); // 将 value 转换为 ValueSequencePtr 类型。
// 调整 vector 的大小以容纳转换后的结果。
// 由于结果包含两个额外的元素1和1因此比 ValueSequence 的大小大2。
list.resize(vec->value().size() + 2);
// 将额外的两个元素设置为 1。
list[0] = 1;
list[1] = 1;
// 使用 std::transform 将 ValueSequence 中的元素转换为 int64_t并存储到 vector 中。
(void)std::transform(vec->value().begin(), vec->value().end(), list.begin() + 2,
[](const ValuePtr &val) { return static_cast<int64_t>(GetValue<int64_t>(val)); });
} else { // 如果 name 不是 "pad",则执行通用的转换逻辑。
int64_t data = GetValue<int64_t>(value); // 从 value 中获取 int64_t 类型的数据。
int size = 2; // 2 int in list // 设置 vector 的大小为2以容纳两个 int64_t 类型的元素。
// 调用 TransformUtil::ConvertIntToList 函数将 int64_t 转换为 std::vector<int64_t>。
list = TransformUtil::ConvertIntToList(data, size);
}
return list; // 返回转换后的 std::vector<int64_t> 对象。
}
// ConvertAnyUtil 函数用于将一个 ValuePtr 类型的值转换为 std::string 类型。
// 转换的方式取决于传入的数据类型 AnyTraits<std::vector<int64_t>> 和 AnyTraits<std::string>。
std::string ConvertAnyUtil(const ValuePtr &value, const AnyTraits<std::vector<int64_t>>, const AnyTraits<std::string>) {
MS_EXCEPTION_IF_NULL(value);
auto vec = value->cast<ValueTuplePtr>(); // 将 value 转换为 ValueTuplePtr 类型。
if (vec == nullptr) { // 如果 vec 为空指针,则抛出异常,说明传入的 value 不是 ValueTuplePtr 类型。
MS_LOG(EXCEPTION) << "not ValueTuplePtr";
}
std::ostringstream buffer; // 创建一个 ostringstream 对象,用于构建字符串。
int i = 0; // 用于辅助构建字符串的计数器。
for (auto &it : vec->value()) { // 遍历 value 中的元素。
if (i != 0) { // 在每个元素之前加入逗号(除了第一个元素)。
buffer << ",";
}
buffer << GetValue<int64_t>(it); // 将元素的值转换为 int64_t并添加到字符串流中。
i++; // 增加计数器。
}
return buffer.str(); // 返回构建的字符串。
}
// ConvertAnyUtil 函数用于将一个 ValuePtr 类型的值转换为 std::vector<float> 类型。
// 转换的方式取决于传入的数据类型 AnyTraits<std::vector<float>> 和 AnyTraits<float>。
std::vector<float> ConvertAnyUtil(const ValuePtr &value, const AnyTraits<std::vector<float>>, const AnyTraits<float>) {
MS_EXCEPTION_IF_NULL(value);
auto vec = value->cast<ValueTuplePtr>(); // 将 value 转换为 ValueTuplePtr 类型。
if (vec == nullptr) { // 如果 vec 为空指针,则抛出异常,说明传入的 value 不是 ValueTuplePtr 类型。
MS_LOG(EXCEPTION) << "not ValueTuplePtr";
}
std::vector<float> list; // 创建一个 std::vector<float> 对象,用于存储转换后的结果。
list.resize(vec->value().size()); // 调整 vector 的大小以容纳转换后的结果,大小与 ValueTuple 中的元素个数相同。
// 使用 std::transform 将 ValueTuple 中的每个元素转换为 float并存储到 vector 中。
(void)std::transform(vec->value().begin(), vec->value().end(), list.begin(),
[](const ValuePtr &val) { return static_cast<float>(GetValue<float>(val)); });
return list; // 返回转换后的 std::vector<float> 对象。
}
// ConvertAnyUtil 函数用于将一个 ValuePtr 类型的值转换为 std::vector<int64_t> 类型。
// 转换的方式取决于传入的 format 参数和数据类型 AnyTraits<std::vector<int64_t>> 和 AnyTraits<int64_t>。
std::vector<int64_t> ConvertAnyUtil(const ValuePtr &value, const std::string &format,
const AnyTraits<std::vector<int64_t>>, const AnyTraits<int64_t>) {
MS_EXCEPTION_IF_NULL(value);
auto vec = value->cast<ValueTuplePtr>(); // 将 value 转换为 ValueTuplePtr 类型。
if (vec == nullptr) { // 如果 vec 为空指针,则抛出异常,说明传入的 value 不是 ValueTuplePtr 类型。
MS_LOG(EXCEPTION) << "not ValueTuplePtr";
}
std::vector<int64_t> list; // 创建一个 std::vector<int64_t> 对象,用于存储转换后的结果。
list.resize(vec->value().size()); // 调整 vector 的大小以容纳转换后的结果,大小与 ValueTuple 中的元素个数相同。
// 使用 std::transform 将 ValueTuple 中的每个元素转换为 int64_t并存储到 vector 中。
(void)std::transform(vec->value().begin(), vec->value().end(), list.begin(),
[](const ValuePtr &val) { return static_cast<int64_t>(GetValue<int64_t>(val)); });
if (format == kOpFormat_NHWC) { // 根据传入的 format 参数执行特定的格式转换。
if (list.size() < 4) { // 如果格式为 NHWC但列表大小小于4则抛出异常。
MS_LOG(EXCEPTION) << "The size of list is less than 4";
} else { // 如果格式为 NHWC并且列表大小大于等于4则进行格式转换。
// 将列表中的第1个元素和第2个元素交换位置将第3个元素和第4个元素交换位置。
int64_t temp = list[1];
list[1] = list[2];
list[2] = list[3];
list[3] = temp;
}
}
return list; // 返回转换后的 std::vector<int64_t> 对象。
}
// ConvertAnyUtil 函数用于将一个 ValuePtr 类型的值转换为 GeDataTypeGraphEngine 的数据类型)。
// 转换的方式取决于传入的数据类型 AnyTraits<GEType>。
GeDataType ConvertAnyUtil(const ValuePtr &value, const AnyTraits<GEType>) {
MS_EXCEPTION_IF_NULL(value);
if (!value->isa<Type>()) { // 确保 value 是 Type 类型。
MS_LOG(EXCEPTION) << "error convert Value to TypePtr for value: " << value->ToString()
<< ", type: " << value->type_name() << ", value should be a Typeptr";
}
auto type = value->cast<TypePtr>(); // 将 value 转换为 TypePtr 类型。
MS_EXCEPTION_IF_NULL(type); // 确保转换后的 type 不为空指针。
TypeId me_type = type->type_id(); // 获取 TypePtr 对象的 TypeIdMindSpore 中的数据类型标识)。
// 如果 TypePtr 对象的 TypeId 是 kObjectTypeTensorType表示其为 TensorType 类型。
// 需要进一步获取其元素类型的 TypeId以便进行后续的 GraphEngine 数据类型转换。
if (kObjectTypeTensorType == me_type) {
me_type = dyn_cast<TensorType>(type)->element()->type_id();
}
return TransformUtil::ConvertDataType(me_type); // 调用 TransformUtil::ConvertDataType 函数将 MindSpore 的数据类型转换为 GraphEngine 的数据类型。
}
// VectorToTensorUtil 函数用于将一个 ValuePtr 类型的值转换为 GeTensorGraphEngine 的 Tensor
// 该函数支持将 tuple 或 list 转换为 GeTensor目前仅支持一维数据。
GeTensor VectorToTensorUtil(const ValuePtr &value) {
// convert tuple or list to ge tensor, only supported one dim for now
// 转换 tuple 或 list 到 ge tensor目前仅支持一维数据
MS_EXCEPTION_IF_NULL(value);
// 获取 tuple 或 list 中的元素值。
auto vec = value->isa<ValueTuple>() ? value->cast<ValueTuplePtr>()->value() : value->cast<ValueListPtr>()->value();
if (vec.empty()) { // 如果 tuple 或 list 为空,则返回一个空的 GeTensor。
MS_LOG(WARNING) << "Convert a none tuple to an empty ge tensor";
return GeTensor(GeTensorDesc(ge::Shape({0})));
}
MS_EXCEPTION_IF_NULL(vec[0]); // 获取第一个元素,并确保它不为空。
// 根据第一个元素的数据类型执行相应的转换逻辑。
// 如果第一个元素是 Int32Imm 类型,表示需要将数据转换为 int32_t 类型的 GeTensor。
if (vec[0]->isa<Int32Imm>()) {
MS_LOG(INFO) << "convert value to tensor with data type = Int32";
// 将数据转换为 int32_t 类型的 std::vector。
auto data = ConvertAnyUtil(value, AnyTraits<int32_t>(), AnyTraits<std::vector<int32_t>>());
// 获取对应的 GeTensorDesc 描述信息。
auto desc = TransformUtil::GetGeTensorDesc({static_cast<int>(vec.size())}, kNumberTypeInt32, kOpFormat_NCHW);
// 如果获取描述信息失败,则抛出异常。
if (desc == nullptr) {
MS_LOG(EXCEPTION) << "Update conversion descriptor failed!";
}
// 创建 GeTensor并使用 int32_t 类型的数据填充 Tensor 数据。
return GeTensor(*desc, reinterpret_cast<uint8_t *>(data.data()), data.size() * sizeof(int32_t));
// 如果第一个元素是 Int64Imm 类型,表示需要将数据转换为 int64_t 类型的 GeTensor。
} else if (vec[0]->isa<Int64Imm>()) {
MS_LOG(INFO) << "convert value to tensor with data type = Int64";
// 将数据转换为 int64_t 类型的 std::vector。
auto data = ConvertAnyUtil(value, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>());
// 获取对应的 GeTensorDesc 描述信息。
auto desc = TransformUtil::GetGeTensorDesc({static_cast<int>(vec.size())}, kNumberTypeInt64, kOpFormat_NCHW);
if (desc == nullptr) { // 如果获取描述信息失败,则抛出异常。
MS_LOG(EXCEPTION) << "Update conversion descriptor failed!";
}
// 创建 GeTensor并使用 int64_t 类型的数据填充 Tensor 数据。
return GeTensor(*desc, reinterpret_cast<uint8_t *>(data.data()), data.size() * sizeof(int64_t));
// 如果第一个元素是 FP32Imm 类型,表示需要将数据转换为 float 类型的 GeTensor。
} else if (vec[0]->isa<FP32Imm>()) {
MS_LOG(INFO) << "convert value to tensor with data type = Float32";
// 将数据转换为 float 类型的 std::vector。
auto data = ConvertAnyUtil(value, AnyTraits<float>(), AnyTraits<std::vector<float>>());
// 获取对应的 GeTensorDesc 描述信息。
auto desc = TransformUtil::GetGeTensorDesc({static_cast<int>(vec.size())}, kNumberTypeFloat32, kOpFormat_NCHW);
if (desc == nullptr) { // 如果获取描述信息失败,则抛出异常。
MS_LOG(EXCEPTION) << "Update conversion descriptor failed!";
}
// 创建 GeTensor并使用 float 类型的数据填充 Tensor 数据。
return GeTensor(*desc, reinterpret_cast<uint8_t *>(data.data()), data.size() * sizeof(float));
} else if (vec[0]->isa<BoolImm>()) { // 如果第一个元素是 BoolImm 类型,表示需要将数据转换为 bool 类型的 GeTensor。
MS_LOG(INFO) << "convert value to tensor with data type = Bool";
// We use uint8_t to save bool type data
// 将数据转换为 bool 类型的 std::vector。
// 这里使用 uint8_t
auto data = ConvertAnyUtil(value, AnyTraits<bool>(), AnyTraits<std::vector<uint8_t>>());
auto desc = TransformUtil::GetGeTensorDesc({static_cast<int>(vec.size())}, kNumberTypeBool, kOpFormat_NCHW);
if (desc == nullptr) {
MS_LOG(EXCEPTION) << "Update conversion descriptor failed!";
}
return GeTensor(*desc, static_cast<uint8_t *>(data.data()), data.size() * sizeof(uint8_t));
} else {
MS_LOG(EXCEPTION) << "Unsupported data type of tuple or list elements: " << vec[0]->type_name();
}
}
// ConvertAnyUtil 函数用于将一个 ValuePtr 类型的值转换为 GeTensorGraphEngine 的 Tensor
// 转换的方式取决于传入的数据类型 AnyTraits<AnyValue>。
GeTensor ConvertAnyUtil(const ValuePtr &value, const AnyTraits<AnyValue>) {
MS_EXCEPTION_IF_NULL(value);
if (value->isa<MeTensor>()) { // 检查 ValuePtr 是否是 MeTensor 类型,如果是,则执行 MeTensor 到 GeTensor 的转换。
// convert me tensor to ge tensor
// 将 MeTensor 转换为 GeTensor
return ConvertAnyUtil(value, AnyTraits<MeTensor>());
// 检查 ValuePtr 是否是 ValueList 或 ValueTuple 类型,如果是,则执行 List 或 Tuple 到 GeTensor 的转换。
} else if (value->isa<ValueList>() || value->isa<ValueTuple>()) {
return VectorToTensorUtil(value);
// 检查 ValuePtr 是否是 Int32Imm 类型,如果是,则执行 Int32Imm 到 GeTensor 的转换。
} else if (value->isa<Int32Imm>()) {
// convert scalar Int to GeTensor
// 将标量 Int32 转换为 GeTensor
MS_LOG(INFO) << "convert scalar to tensor with data type = Int32";
GeTensorDesc desc(GeShape(), ge::FORMAT_NCHW, ge::DT_INT32); // 创建 GeTensorDesc 描述信息。
auto v = GetValue<int32_t>(value);
desc.SetRealDimCnt(0); // 设置描述信息的实际维度数为0标量
return GeTensor(desc, reinterpret_cast<uint8_t *>(&v), sizeof(int32_t)); // 创建 GeTensor并使用 int32_t 类型的数据填充 Tensor 数据。
}
// 检查 ValuePtr 是否是 Int64Imm 类型,如果是,则执行 Int64Imm 到 GeTensor 的转换。
else if (value->isa<Int64Imm>()) {
// convert scalar Int64 to GeTensor
// 将标量 Int64 转换为 GeTensor
MS_LOG(INFO) << "convert scalar to tensor with data type = Int64";
GeTensorDesc desc(GeShape(), ge::FORMAT_NCHW, ge::DT_INT64); // 创建 GeTensorDesc 描述信息。
auto v = GetValue<int64_t>(value);
desc.SetRealDimCnt(0); // 设置描述信息的实际维度数为0标量
return GeTensor(desc, reinterpret_cast<uint8_t *>(&v), sizeof(int64_t)); // 创建 GeTensor并使用 int64_t 类型的数据填充 Tensor 数据。
}
// 检查 ValuePtr 是否是 FP32Imm 类型,如果是,则执行 FP32Imm 到 GeTensor 的转换。
else if (value->isa<FP32Imm>()) {
// convert scalar FP32 to GeTensor
MS_LOG(INFO) << "convert scalar to tensor with data type = FP32"; // 将标量 FP32 转换为 GeTensor
GeTensorDesc desc(GeShape(), ge::FORMAT_NCHW, ge::DT_FLOAT); // 创建 GeTensorDesc 描述信息。
auto v = GetValue<float>(value);
desc.SetRealDimCnt(0); // 设置描述信息的实际维度数为0标量
return GeTensor(desc, reinterpret_cast<uint8_t *>(&v), sizeof(float)); // 创建 GeTensor并使用 float 类型的数据填充 Tensor 数据。
}
// 检查 ValuePtr 是否是 BoolImm 类型,如果是,则执行 BoolImm 到 GeTensor 的转换。
else if (value->isa<BoolImm>()) {
// convert scalar FP32 to GeTensor
// 将标量 Bool 转换为 GeTensor
MS_LOG(INFO) << "convert scalar to tensor with data type = Bool";
GeTensorDesc desc(GeShape(), ge::FORMAT_NCHW, ge::DT_BOOL); // 创建 GeTensorDesc 描述信息。
auto v = GetValue<bool>(value);
desc.SetRealDimCnt(0); // 设置描述信息的实际维度数为0标量
return GeTensor(desc, reinterpret_cast<uint8_t *>(&v), sizeof(bool)); // 创建 GeTensor并使用 bool 类型的数据填充 Tensor 数据。
}
// 检查 ValuePtr 是否是 StringImm 类型,如果是,则执行 StringImm 到 GeTensor 的转换。
else if (value->isa<StringImm>()) {
// convert String to GeTensor
// 将标量 String 转换为 GeTensor
MS_LOG(INFO) << "convert string to tensor with data type = String";
std::string v = GetValue<std::string>(value); // 获取 string 类型的值。
std::vector<int64_t> ge_shape; // 创建 GeTensorDesc 描述信息。
GeShape shape(ge_shape);
GeTensorDesc desc(shape, ge::FORMAT_NCHW, ge::DT_STRING);
GeTensor str_tensor(desc);
(void)str_tensor.SetData(v);
return str_tensor;
} else {
MS_LOG(WARNING) << "Unsupported value type: " << value->type_name()
<< " to convert to tensor. Value: " << value->ToString();
}
return GeTensor();
}
// IsCustomPrim 函数用于判断给定的 PrimitivePtr 是否为自定义的操作Custom Primitive
bool IsCustomPrim(const PrimitivePtr &prim) {
if (prim == nullptr) { // 如果给定的 PrimitivePtr 为空指针,则返回 false。
return false;
}
// 从 Primitive 的属性中获取名为 "_custom_op_flag" 的属性值。
ValuePtr flag = prim->GetAttr("_custom_op_flag");
if (flag == nullptr) { // 如果获取到的属性值为空指针,则返回 false。
return false;
}
// 将属性值转换为 bool 类型,并存储在变量 is_custom_op 中。
bool is_custom_op = GetValue<bool>(flag);
// 如果 is_custom_op 为 false同时 Primitive 的属性中有名为 "_custom_op_impl_config_path" 的属性,
// 则抛出异常,提示非自定义操作不应该分配 "_custom_op_impl_config_path" 属性。
if (!is_custom_op && prim->GetAttr("_custom_op_impl_config_path") != nullptr) {
MS_LOG(EXCEPTION) << "The custom op flag is false, but the op information config path is not null, non-custom op "
"can not assign the op information config path.";
}
return is_custom_op; // 返回 is_custom_op表示给定的 Primitive 是否为自定义的操作。
}
// IsCustomCNode 函数用于判断给定的 AnfNodePtr 是否为自定义的 CNode。
// 自定义 CNode 是指其第一个输入是 ValueNode而该 ValueNode 包含一个自定义的 PrimitivePtr。
bool IsCustomCNode(const AnfNodePtr &anf) {
if (anf == nullptr) { // 如果给定的 AnfNodePtr 为空指针,则返回 false。
return false;
}
auto node = anf->cast<CNodePtr>(); // 将 AnfNodePtr 转换为 CNodePtr。
if (node == nullptr) { // 如果转换失败,说明给定的 AnfNodePtr 不是 CNode返回 false。
return false;
}
if (node->inputs().empty()) { // 检查 CNode 的输入是否为空,如果为空,抛出异常。
MS_LOG(EXCEPTION) << "Length of node inputs is empty";
}
MS_EXCEPTION_IF_NULL(node->inputs()[0]); // 检查 CNode 的第一个输入是否为空指针,如果是,抛出异常。
// 检查 CNode 的第一个输入是否为 ValueNode如果不是返回 false表示不是自定义 CNode。
if (!node->inputs()[0]->isa<ValueNode>()) {
return false;
}
// 尝试将 CNode 的第一个输入转换为 ValueNode并获取其包含的 PrimitivePtr。
auto cus_prim = GetValueNode<PrimitivePtr>(node->inputs()[0]);
if (cus_prim == nullptr) { // 如果获取的 PrimitivePtr 为空指针,返回 false表示不是自定义 CNode。
return false;
}
return IsCustomPrim(cus_prim); // 调用 IsCustomPrim 函数判断获取的 PrimitivePtr 是否为自定义的操作,返回判断结果。
}
// GetOpIOFormat 函数用于获取给定 AnfNodePtr 对应的操作的输入输出格式IO Format
std::string GetOpIOFormat(const AnfNodePtr &anf) {
std::string ret;
if (anf == nullptr) { // 检查给定的 AnfNodePtr 是否为空指针,如果是,输出错误日志并返回空字符串。
MS_LOG(ERROR) << "The anf is nullptr";
return ret;
}
auto node = anf->cast<CNodePtr>(); // 尝试将 AnfNodePtr 转换为 CNodePtr。
if (node == nullptr) { // 如果转换失败,说明给定的 AnfNodePtr 不是 CNode输出错误日志并返回空字符串。
MS_LOG(ERROR) << "The anf is not a cnode.";
return ret;
}
if (node->inputs().empty()) { // 检查 CNode 的输入是否为空,如果为空,抛出异常。
MS_LOG(EXCEPTION) << "Length of node inputs is empty.";
}
MS_EXCEPTION_IF_NULL(node->inputs()[0]); // 检查 CNode 的第一个输入是否为空指针,如果是,抛出异常。
if (!node->inputs()[0]->isa<ValueNode>()) { // 检查 CNode 的第一个输入是否为 ValueNode如果不是输出错误日志并返回空字符串。
MS_LOG(ERROR) << "The anf is not a value node.";
return ret;
}
auto prim = GetValueNode<PrimitivePtr>(node->inputs()[0]); // 尝试将 CNode 的第一个输入转换为 ValueNode并获取其包含的 PrimitivePtr。
if (prim == nullptr) { // 如果获取的 PrimitivePtr 为空指针,输出错误日志并返回空字符串。
MS_LOG(ERROR) << "The anf is not a Primitive.";
return ret;
}
if (prim->HasAttr("io_format")) { // 检查 PrimitivePtr 是否有名为 "io_format" 的属性,如果有,则返回其属性值作为 IO Format。
return GetValue<std::string>(prim->GetAttr("io_format"));
}
// 如果 PrimitivePtr 没有名为 "io_format" 的属性,则从 IOFormatMap 中查找操作名对应的 IO Format。
auto io_format_map = IOFormatMap::get();
auto iter = io_format_map.find(prim->name());
if (iter == io_format_map.end()) { // 如果在 IOFormatMap 中没有找到对应的 IO Format则默认返回 "NCHW"。
return "NCHW";
}
// 检查该 IO Format 是否是 "format" 类型的属性,如果是,进一步处理后返回具体的格式值。
if (iter->second == "format") {
ValuePtr format = prim->GetAttr("format");
MS_EXCEPTION_IF_NULL(format);
if (format->isa<Int64Imm>()) {
bool converted = CheckAndConvertUtils::ConvertAttrValueToString(prim->name(), "format", &format);
if (converted) {
return GetValue<std::string>(format);
}
} else {
return GetValue<std::string>(format);
}
}
return iter->second; // 如果不是 "format" 类型的属性,直接返回 IO Format。
}
} // namespace transform
} // namespace mindspore