ADD file via upload
This commit is contained in:
parent
26ecc29329
commit
dab0e8e7ff
|
|
@ -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 中的 Tensor(mindspore::tensor::Tensor)转换为 GE(GraphEngine)中的Tensor(GeTensor)。
|
||||
GeTensor ConvertAnyUtil(const ValuePtr &value, const AnyTraits<mindspore::tensor::Tensor> &) {
|
||||
// To-DO the format may read from ME tensor
|
||||
// TODO:可能需要从 ME(MindSpore Execution) Tensor 读取格式信息(format)
|
||||
MS_EXCEPTION_IF_NULL(value);
|
||||
//// 将 value 强制转换为 MeTensorPtr 类型,MeTensorPtr 是一个智能指针,表示 ME Tensor(MindSpore 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 类型的值转换为 GeDataType(GraphEngine 的数据类型)。
|
||||
// 转换的方式取决于传入的数据类型 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 对象的 TypeId(MindSpore 中的数据类型标识)。
|
||||
// 如果 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 类型的值转换为 GeTensor(GraphEngine 的 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 类型的值转换为 GeTensor(GraphEngine 的 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
|
||||
Loading…
Reference in New Issue