力争自助餐队代码评注 #11

Open
zyf1234 wants to merge 72 commits from zyf1234/mindspore2022:master into master
68 changed files with 28091 additions and 0 deletions

BIN
ccsrc/transform-update.zip Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,16 @@
# 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.
# ============================================================================
"""Transformers for optimizing ast."""
from .flatten_recursive_stmt import FlattenRecursiveStmt

View File

@ -0,0 +1,330 @@
# Copyright 2021 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.
# ============================================================================
"""adasum"""
import copy
import hashlib
import math
from mindspore.nn.cell import Cell
from mindspore.communication.management import create_group
from mindspore.ops import composite as C
from mindspore.ops import functional as F
from mindspore.ops import operations as P
from mindspore.ops.operations._inner_ops import Send, Receive
__all__ = ["AdaSum"]
MAX_NUM_HASH = 2 ** 31
_update_parameters = C.MultitypeFuncGraph("update_parameters")
@_update_parameters.register("Tensor", "Tensor", "Tensor", "Tensor")
#定义一个名为 _update_parameters_after_broadcast 的函数,用于更新参数
def _update_parameters_after_broadcast(delta_weight, update_delta_weight, parameter, old_parameter):
shape = F.shape(delta_weight) # 获取 delta_weight 的形状
update_delta_weight = P.Reshape()(update_delta_weight, shape) # 将 update_delta_weight 重塑成与 delta_weight 相同的形状
new_parameter = old_parameter - update_delta_weight # 计算新的参数值,通过从旧参数中减去 update_delta_weight
return P.Assign()(parameter, new_parameter) # 使用 P.Assign() 函数将新参数值分配给 parameter
# 定义一个名为 _send_before_receive 的函数,用于发送数据并接收响应
def _send_before_receive(send_part, send, recv):
send_ok = send(send_part) # 通过调用 send 函数发送数据 send_part并将返回结果存储在 send_ok 中
return recv(send_ok) # 调用 recv 函数,将 send_ok 作为参数传递,用于接收响应
# 定义一个名为 _receive_before_send 的函数,用于先接收数据后发送数据
def _receive_before_send(send_part, send, recv):
receive_ok = recv(send_part) # 通过调用 recv 函数,将 send_part 作为参数传递,用于接收数据,并将接收结果存储在 receive_ok 中
send_part = F.depend(send_part, receive_ok) # 使用 F.depend() 函数建立依赖关系,确保在 send_part 发送之前先执行接收操作
return F.depend(receive_ok, send(send_part)) # 通过调用 send 函数,将 send_part 作为参数传递,用于发送数据,并将发送结果返回
# 定义一个名为 _send_recv_res 的函数,用于发送和接收数据,并根据条件进行数学计算和处理
def _send_recv_res(left_send, recv_part, local_part, allreduce, parameter_divisibility, allreduce_node_num):
"""send result and receive result."""
if parameter_divisibility: # 如果参数可分割,执行以下操作
recv_part = P.Squeeze()(recv_part) # 去除 recv_part 中的冗余维度
local_part = F.depend(local_part, recv_part) # 建立依赖关系,确保在 local_part 使用前 recv_part 已被计算
eps = 1e-12
# 计算一些值,这些值将用于后续的计算
value_0 = P.ReduceSum()(local_part * recv_part) + eps
if left_send:
value_1 = P.ReduceSum()(local_part * local_part) + eps
value_2 = P.ReduceSum()(recv_part * recv_part) + eps
else:
value_1 = P.ReduceSum()(recv_part * recv_part) + eps
value_2 = P.ReduceSum()(local_part * local_part) + eps
# 对计算的值进行全局归约allreduce
value_0 = allreduce(value_0)
value_1 = F.depend(allreduce(value_1), value_0)
value_2 = F.depend(allreduce(value_2), value_1)
# 根据左右发送left_send的条件计算最终的结果 res
if left_send:
res = (1 - (value_0 / (2 * value_1))) * local_part + (1 - (value_0 / (2 * value_2))) * recv_part
else:
res = (1 - (value_0 / (2 * value_1))) * recv_part + (1 - (value_0 / (2 * value_2))) * local_part
else:
res = allreduce(local_part) # 如果参数不可分割直接执行全局归约allreduce操作
res /= allreduce_node_num
return res
_adasum_opt_forward = C.MultitypeFuncGraph("adasum_opt_forward")
@_adasum_opt_forward.register("Bool", "Function", "Bool", "Int64", "Function", "Function", "Tensor")
# 定义一个名为 _adasum_opt_forward_process 的函数,用于 Adasum 优化器的前向处理
def _adasum_opt_forward_process(left_send, allreduce, parameter_divisibility, allreduce_node_num, send, recv, delta_w):
"""adasum optimizer process."""
if parameter_divisibility: # 如果参数可分割,执行以下操作
delta_w = P.Squeeze()(delta_w) # 去除 delta_w 中的冗余维度
ori_len = F.shape(delta_w)[0] # 获取 delta_w 的原始长度
divide_len = ori_len / 2 # 计算分割点的位置
left_part = delta_w[:divide_len] # 将 delta_w 划分为左半部分
right_part = delta_w[divide_len:] # 将 delta_w 划分为右半部分
else: # 如果参数不可分割,直接将 delta_w 复制到左半部分和右半部分
left_part = delta_w
right_part = delta_w
if left_send: # 如果左边发送数据
if parameter_divisibility: # 如果参数可分割,执行发送操作,并接收数据部分
recv_part = _send_before_receive(left_part, send, recv)
else: # 如果参数不可分割,将右半部分视为接收数据部分
recv_part = right_part
# 计算更新的 delta_w
update_delta_w = _send_recv_res(left_send, recv_part, right_part, allreduce, parameter_divisibility,
allreduce_node_num)
else: # 如果右边发送数据
if parameter_divisibility: # 如果参数可分割,执行接收操作,并接收数据部分
recv_part = _receive_before_send(right_part, send, recv)
else: # 如果参数不可分割,将左半部分视为接收数据部分
recv_part = left_part
# 计算更新的 delta_w
update_delta_w = _send_recv_res(left_send, recv_part, left_part, allreduce, parameter_divisibility,
allreduce_node_num)
return update_delta_w
_adasum_opt_rollback = C.MultitypeFuncGraph("adasum_opt_rollback")
@_adasum_opt_rollback.register("Bool", "Bool", "Tensor", "Function", "Function")
# 定义一个名为 _adasum_opt_rollback_process 的函数,用于 Adasum 优化器的回滚处理
def _adasum_opt_rollback_process(left_send, parameter_divisibility, delta_w, send, recv):
"""adasum optimizer rollback process."""
if parameter_divisibility: # 如果参数可分割,执行以下操作
if left_send: # 如果左边发送数据,执行发送操作,并接收数据部分
recv_part = _send_before_receive(delta_w, send, recv)
else: # 如果右边发送数据,执行接收操作,并接收数据部分
recv_part = _receive_before_send(delta_w, send, recv)
recv_part = P.Squeeze()(recv_part) # 去除接收数据部分的冗余维度
recv_part = P.Reshape()(recv_part, (-1,)) # 重塑接收数据部分和 delta_w 为一维张量
delta_w = P.Reshape()(delta_w, (-1,))
# 根据左右发送的条件,将接收数据部分和 delta_w 进行拼接
if left_send:
res = P.Concat()((recv_part, delta_w))
else:
res = P.Concat()((delta_w, recv_part))
else:
res = delta_w # 如果参数不可分割,直接返回 delta_w
return res
#定义了一个名为 AdaSum 的类一个自定义的神经网络层Cell用于执行Adasum算法
#该算法用于分布式数据并行训练深度学习模型。
class AdaSum(Cell):
r"""
The Adaptive Summation, or AdaSum, is a novel algorithm for improving distributed data
parallel training of Deep Learning models.
Args:
rank (int): Rank number.
device_number (int): Device number.
group_number (int): Group number.
parameter_tuple (Tuple(Parameter)): Tuple of parameters.
Inputs:
- **delta_weights** (Tuple(Tensor)) - Tuple of gradients.
- **parameters** (Tuple(Parameter)) - Tuple of current parameters.
- **old_parameters** (Tuple(Parameter)) - Tuple of last parameters.
Outputs:
- **adasum_parameters** (Tuple(Tensor)) - Tuple of parameters after adasum process.
"""
def __init__(self, rank, device_number, group_number, parameter_tuple):
super(AdaSum, self).__init__()
self.rank = rank
self.device_number = device_number
self.group_number = group_number
self.parameter_tuple = parameter_tuple
self._generate_communication_op()
self.hyper_map = C.HyperMap()
# 生成通信操作
# 该方法用于创建Adasum算法所需的通信操作包括发送、接收、全局归约等操作。
def _generate_communication_op(self):
"""generate communication op."""
self.calc_times = int(math.log(self.group_number, 2))
self.send_node = []
self.send_list_forward = []
self.recv_list_forward = []
self.send_list_rollback = []
self.recv_list_rollback = []
self.allreduce_list = []
self.broadcast_list = []
self.parameter_divisibility_list = []
self.allreduce_node_num_list = []
last_delta_weights = []
group_start_rank = (self.rank // self.device_number) * self.device_number
for step in range(self.calc_times):
current_group = self.device_number * (2 ** step)
sr_target = self.rank
if (sr_target // current_group) % 2 == 0:
dest_target = sr_target + current_group
self.send_node.append(True)
else:
dest_target = sr_target - current_group
self.send_node.append(False)
neighbor_ids = []
group_name_last = 0
for index in range(2 ** (step + 1)):
node_rank = self.rank // self.device_number
double_d = 2 ** (step + 1)
neighbor_id = (node_rank // double_d * double_d + index) * self.device_number + \
self.rank % self.device_number
neighbor_ids.append(neighbor_id)
group_name_last += neighbor_id
group_name = "adasum_" + str(step) + "_" + str(group_name_last)
create_group(group_name, neighbor_ids)
send_left = []
send_right = []
recv_left = []
recv_right = []
allreduce_node_num = ()
left_delta_weights, right_delta_weights, delta_weights_divisibility = \
self._get_delta_weights_info(last_delta_weights)
self.parameter_divisibility_list.append(delta_weights_divisibility)
weights_index = 0
fusion_id = (step + 1) * 3
for shape, dtype in left_delta_weights:
send_tag = self._hash(step, sr_target, weights_index)
send = Send(sr_tag=send_tag, dest_rank=dest_target, group="hccl_world_group")
send.add_prim_attr("fusion", fusion_id)
recv_tag = self._hash(step, dest_target, weights_index)
recv = Receive(sr_tag=recv_tag, src_rank=dest_target, shape=shape, dtype=dtype,
group="hccl_world_group")
recv.add_prim_attr("fusion", fusion_id)
send_left.append(send)
recv_left.append(recv)
weights_index += 1
for shape, dtype in right_delta_weights:
send_tag = self._hash(step, sr_target, weights_index)
send = Send(sr_tag=send_tag, dest_rank=dest_target, group="hccl_world_group")
send.add_prim_attr("fusion", fusion_id + 1)
recv_tag = self._hash(step, dest_target, weights_index)
recv = Receive(sr_tag=recv_tag, src_rank=dest_target, shape=shape, dtype=dtype,
group="hccl_world_group")
recv.add_prim_attr("fusion", fusion_id + 1)
send_right.append(send)
recv_right.append(recv)
weights_index += 1
if self.send_node and self.send_node[-1]:
self.send_list_forward.append(send_left)
self.send_list_rollback.append(send_right)
self.recv_list_forward.append(recv_right)
self.recv_list_rollback.append(recv_left)
last_delta_weights = right_delta_weights
else:
self.send_list_forward.append(send_right)
self.send_list_rollback.append(send_left)
self.recv_list_forward.append(recv_left)
self.recv_list_rollback.append(recv_right)
last_delta_weights = left_delta_weights
server_all_reduce = P.AllReduce("sum", group_name)
server_all_reduce.add_prim_attr("fusion", fusion_id + 2)
self.allreduce_list.append(server_all_reduce)
for param_divisibility in delta_weights_divisibility:
if param_divisibility:
allreduce_node_num += (0,)
else:
allreduce_node_num += (2 ** (step + 1),)
self.allreduce_node_num_list.append(allreduce_node_num)
broadcast_group = [x for x in range(group_start_rank, group_start_rank + self.device_number)]
broadcast_group_name = "broadcast_group_" + str(group_start_rank)
create_group(broadcast_group_name, broadcast_group)
for b_rank in range(len(broadcast_group)):
self.broadcast_list.append(P.Broadcast(b_rank, group=broadcast_group_name))
self.sync_barrier = P.AllReduce("sum", group=broadcast_group_name)
# 获取梯度信息
# 该方法用于获取梯度信息,将梯度划分为左右部分,并判断是否可分割。
def _get_delta_weights_info(self, last_delta_weights):
"""get delta weights info."""
half_delta_weights = []
if last_delta_weights:
half_delta_weights = last_delta_weights
else:
for parameter in self.parameter_tuple:
new_shape = [int(x) for x in parameter.shape]
half_delta_weights.append((new_shape, parameter.dtype))
left_delta_weights = []
right_delta_weights = []
delta_weights_divisibility = ()
for shape, dtype in half_delta_weights:
left_shape = copy.deepcopy(shape)
right_shape = copy.deepcopy(shape)
divisibility_flag = False
for i in range(len(shape)):
if shape[i] > 1:
left_shape[i] = int(shape[i] // 2)
right_shape[i] = shape[i] - int(shape[i] // 2)
divisibility_flag = True
break
left_delta_weights.append((left_shape, dtype))
right_delta_weights.append((right_shape, dtype))
delta_weights_divisibility += (divisibility_flag,)
return left_delta_weights, right_delta_weights, delta_weights_divisibility
# 计算哈希值
# 该方法用于计算哈希值,用于生成通信标签。
def _hash(self, step, target, weights_index):
target = "tag" + str(step) + str(target) + str(weights_index)
target_hash = hashlib.sha1(target.encode()).hexdigest()
hash_res = int(int(target_hash, 16) % MAX_NUM_HASH)
return hash_res
# 执行Adasum前向处理
# 该部分代码执行Adasum算法的前向处理包括数据的发送、接收、计算等。
def construct(self, delta_weights, parameters, old_parameters):
forward_weights = [delta_weights]
for i in range(self.calc_times):
process_weights = self.hyper_map(F.partial(_adasum_opt_forward, self.send_node[i], self.allreduce_list[i]),
self.parameter_divisibility_list[i], self.allreduce_node_num_list[i],
self.send_list_forward[i], self.recv_list_forward[i], forward_weights[-1])
forward_weights.append(process_weights)
for i in range(self.calc_times):
j = self.calc_times - i - 1
process_weights = self.hyper_map(F.partial(_adasum_opt_rollback, self.send_node[j]),
self.parameter_divisibility_list[j], forward_weights[j + 1],
self.send_list_rollback[j], self.recv_list_rollback[j])
forward_weights[j] = process_weights
adasum_parameters = self.hyper_map(F.partial(_update_parameters), delta_weights, forward_weights[0],
parameters, old_parameters)
return adasum_parameters

View File

@ -0,0 +1,204 @@
/**
* 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_declare/array_ops_declare.h"
#include <vector>
#include <string>
namespace mindspore::transform {
// const
INPUT_MAP(Const) = EMPTY_INPUT_MAP;
//输入映射,设为空
ATTR_MAP(Const) = {{"value", ATTR_DESC(value, AnyTraits<AnyValue>())}};
//属性映射属性value类型为AnyValue()
OUTPUT_MAP(Const) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
// Constant
INPUT_MAP(Constant) = EMPTY_INPUT_MAP;
//输入映射,设为空
ATTR_MAP(Constant) = {{"value", ATTR_DESC(value, AnyTraits<AnyValue>())}};
//属性映射属性value类型为AnyValue()
OUTPUT_MAP(Constant) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Constant, kNameConst, ADPT_DESC(Constant, Const))
//注册Constant操作的适配器描述KNameConst
// ScalarSummary
INPUT_MAP(Summary) = {{2, INPUT_DESC(x)}};
//输入映射x索引为2
ATTR_MAP(Summary) = EMPTY_ATTR_MAP
//属性映射,设为空
#ifndef ENABLE_SECURITY
//如果未定义ENABLE_SECURITY宏变量则注册适配器描述信息
//适配器描述用于将特定操作与指定的适配器关联将ScalarSummaryImageSummaryTensorSummaryHistogramSummary和Debug操作与Summary适配器描述关联
//操作的名称和prim空间下的kPrimScalarSummary、kPrimImageSummary、kPrimTensorSummary、kPrimHistogramSummary和kPrimDebug相匹配
REG_ADPT_DESC(ScalarSummary, prim::kPrimScalarSummary->name(), ADPT_DESC(Summary))
REG_ADPT_DESC(ImageSummary, prim::kPrimImageSummary->name(), ADPT_DESC(Summary))
REG_ADPT_DESC(TensorSummary, prim::kPrimTensorSummary->name(), ADPT_DESC(Summary))
REG_ADPT_DESC(HistogramSummary, prim::kPrimHistogramSummary->name(), ADPT_DESC(Summary))
#endif
REG_ADPT_DESC(Debug, prim::kPrimDebug->name(), ADPT_DESC(Summary))
//不论 ENABLE_SECURITY是否定义都将Debug操作与Summary适配器描述关联
// Data
INPUT_MAP(Data) = EMPTY_INPUT_MAP;
//输入映射,设为空
ATTR_MAP(Data) = EMPTY_ATTR_MAP;
//属性映射,设为空
REG_ADPT_DESC(Data, kNameParam, ADPT_DESC(Data))
//注册Data操作的适配器描述KNameParam
// Shape
INPUT_MAP(Shape) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(Shape) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(Shape) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Shape, kNameShape, ADPT_DESC(Shape))
//注册Shape操作的适配器描述KNameShape
// GetShape
INPUT_MAP(GetShape) = EMPTY_INPUT_MAP;
//输入映射,设为空
DYN_INPUT_MAP(GetShape) = {{1, DYN_INPUT_DESC(x)}};
//动态输入映射将索引为1的动态输入与名称为x的动态输入描述关联起来用于后续操作
ATTR_MAP(GetShape) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(GetShape) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(GetShape, kNameGetShape, ADPT_DESC(GetShape));
//注册GetShape操作的适配器描述KNameGetShape
// Reshape
INPUT_MAP(Reshape) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(shape)}};
//输入映射x索引为1sharp索引为2
ATTR_MAP(Reshape) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(Reshape) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Reshape, kNameReshape, ADPT_DESC(Reshape))
//注册ReShape操作的适配器描述KNameReShape
REG_ADPT_DESC(FlattenGrad, kNameFlattenGrad, ADPT_DESC(Reshape))
//注册FlattenGrad操作的适配器描述kNameFlattenGrad
// TransShape
INPUT_MAP(TransShape) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
INPUT_ATTR_MAP(TransShape) = {{2, ATTR_DESC(outShape, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())}};
ATTR_MAP(TransShape) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(TransShape) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(TransShape, kNameTransShape, ADPT_DESC(TransShape))
//注册TransShape操作的适配器描述kNameTransShape
// MirrorPad
INPUT_MAP(MirrorPad) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(paddings)}};
//输入映射x索引为1paddings索引为2
ATTR_MAP(MirrorPad) = {{"mode", ATTR_DESC(mode, AnyTraits<std::string>())}};
//属性映射属性mode类型为string
OUTPUT_MAP(MirrorPad) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(MirrorPad, kNameMirrorPad, ADPT_DESC(MirrorPad))
//注册MirrorPad操作的适配器描述kNameMirrorPad
// MirrorPadGrad
INPUT_MAP(MirrorPadGrad) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(paddings)}};
//输入映射x索引为1paddings索引为2
ATTR_MAP(MirrorPadGrad) = {{"mode", ATTR_DESC(mode, AnyTraits<std::string>())}};
//属性映射属性mode类型为string
OUTPUT_MAP(MirrorPadGrad) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(MirrorPadGrad, kNameMirrorPadGrad, ADPT_DESC(MirrorPadGrad))
//注册MirrorPadGrad操作的适配器描述kNameMirrorPadGrad
// ExpandDims
INPUT_MAP(ExpandDims) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(axis)}};
//输入映射x索引为1axis索引为2
ATTR_MAP(ExpandDims) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(ExpandDims) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(ExpandDims, kNameExpandDims, ADPT_DESC(ExpandDims))
//注册ExpandDims操作的适配器描述kNameExpandDims
// Squeeze
INPUT_MAP(Squeeze) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(Squeeze) = {{"axis", ATTR_DESC(axis, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())}};
//属性映射属性axis类型为int64_t
OUTPUT_MAP(Squeeze) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Squeeze, prim::kPrimSqueeze->name(), ADPT_DESC(Squeeze))
//注册Squeeze操作的适配器描述kNameSqueeze返回的name变量
// ReverseSequence
INPUT_MAP(ReverseSequence) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(seq_lengths)}};
//输入映射x索引为1seq_lengths索引为2
ATTR_MAP(ReverseSequence) = {{"seq_dim", ATTR_DESC(seq_dim, AnyTraits<int64_t>())},
{"batch_dim", ATTR_DESC(batch_dim, AnyTraits<int64_t>())}};
//属性映射属性seq_dim类型为int64_t属性batch_dim类型为int64_t
OUTPUT_MAP(ReverseSequence) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(ReverseSequence, kNameReverseSequence, ADPT_DESC(ReverseSequence))
//注册ReverseSequence操作的适配器描述kNameReverseSequence
// EditDistance
INPUT_MAP(EditDistance) = {{1, INPUT_DESC(hypothesis_indices)}, {2, INPUT_DESC(hypothesis_values)},
{3, INPUT_DESC(hypothesis_shape)}, {4, INPUT_DESC(truth_indices)},
{5, INPUT_DESC(truth_values)}, {6, INPUT_DESC(truth_shape)}};
//输入映射hypothesis_indices索引为1hypothesis_values索引为2hypothesis_shape索引为3
// truth_indices索引为4truth_values索引为5,truth_shape索引为6
ATTR_MAP(EditDistance) = {{"normalize", ATTR_DESC(normalize, AnyTraits<bool>())}};
//属性映射属性normalize类型为int64_t
OUTPUT_MAP(EditDistance) = {{0, OUTPUT_DESC(output)}};
//输出映射y索引为0
REG_ADPT_DESC(EditDistance, kNameEditDistance, ADPT_DESC(EditDistance))
//注册EditDistance操作的适配器描述kNameEditDistance
// NonZeroWithValue
INPUT_MAP(NonZeroWithValue) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(NonZeroWithValue) = {{"transpose", ATTR_DESC(transpose, AnyTraits<bool>())}};
//属性映射属性transpose类型为int64_t
OUTPUT_MAP(NonZeroWithValue) = {{0, OUTPUT_DESC(value)}, {1, OUTPUT_DESC(index)}, {2, OUTPUT_DESC(count)}};
//输出映射value索引为0index索引为1count索引为2
REG_ADPT_DESC(NonZeroWithValue, kNameNonZeroWithValue, ADPT_DESC(NonZeroWithValue))
//注册NonZeroWithValue操作的适配器描述kNameNonZeroWithValue
// NonZeroWithValueShape
INPUT_MAP(NonZeroWithValueShape) = {{1, INPUT_DESC(value)}, {2, INPUT_DESC(index)}, {3, INPUT_DESC(count)}};
//输入映射x索引为1index索引为2count索引为3
ATTR_MAP(NonZeroWithValueShape) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(NonZeroWithValueShape) = {{0, OUTPUT_DESC(out_value)}, {1, OUTPUT_DESC(out_index)}};
//输出映射out_value索引为0out_index索引为1out_count索引为2
REG_ADPT_DESC(NonZeroWithValueShape, kNameNonZeroWithValueShape, ADPT_DESC(NonZeroWithValueShape))
//注册NonZeroWithValueShape操作的适配器描述kNameNonZeroWithValueShape
// Unsqueeze
INPUT_MAP(Unsqueeze) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(Unsqueeze) = {{"axis", ATTR_DESC(axes, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())}};
//属性映射属性axis类型为int64_t
OUTPUT_MAP(Unsqueeze) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Unsqueeze, kNameUnsqueeze, ADPT_DESC(Unsqueeze))
//注册Unsqueeze操作的适配器描述kNameUnsqueeze
} // namespace mindspore::transform

View File

@ -0,0 +1,538 @@
# Copyright 2021 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.
# ============================================================================
"""base process"""
import os
import time
import math
import copy
import numpy as np
from scipy import linalg as la
from mindspore.context import ParallelMode
import mindspore.nn as nn
from mindspore.nn.optim import LARS
from mindspore import log as logger
from mindspore.common import Parameter
from mindspore.communication.management import get_group_size
from mindspore.train.serialization import load_checkpoint
from mindspore.parallel._utils import _get_global_rank
from mindspore.parallel._auto_parallel_context import auto_parallel_context
from .less_batch_normalization import CommonHeadLastFN
__all__ = ["OptimizerProcess", "ParameterProcess"]
#这段代码定义了一个名为 OptimizerProcess 的类,用于处理优化器的一些操作,
#包括添加梯度中心化Gradient Centralization标签和生成新的优化器。
class OptimizerProcess:
r"""
Process optimizer for Boost. Currently, this class supports adding GC(grad centralization) tags
and creating new optimizers.
Args:
opt (Cell): Optimizer used.
Examples:
>>> import numpy as np
>>> from mindspore import Tensor, Parameter, nn
>>> from mindspore import ops
>>> from mindspore.boost import OptimizerProcess
>>>
>>> class Net(nn.Cell):
... def __init__(self, in_features, out_features):
... super(Net, self).__init__()
... self.weight = Parameter(Tensor(np.ones([in_features, out_features]).astype(np.float32)),
... name='weight')
... self.matmul = ops.MatMul()
...
... def construct(self, x):
... output = self.matmul(x, self.weight)
... return output
...
>>> size, in_features, out_features = 16, 16, 10
>>> network = Net(in_features, out_features)
>>> optimizer = nn.Momentum(net.trainable_params(), learning_rate=0.1, momentum=0.9)
>>> optimizer_process = OptimizerProcess(optimizer)
>>> optimizer_process.add_grad_centralization(network)
>>> optimizer = optimizer_process.generate_new_optimizer()
"""
# 初始化 OptimizerProcess
# 根据传入的优化器 opt 初始化 OptimizerProcess 实例,并保存相关参数和优化器类。
def __init__(self, opt):
if isinstance(opt, LARS):
self.is_lars = True
self.single_opt = opt.opt
self.opt_class = type(opt.opt)
self.opt_init_args = opt.opt.init_args
self.lars_init_args = opt.init_args
self.learning_rate = opt.opt.init_learning_rate
else:
self.is_lars = False
self.single_opt = opt
self.opt_class = type(opt)
self.opt_init_args = opt.init_args
self.learning_rate = opt.init_learning_rate
self.origin_params = opt.init_params["params"]
# 构建参数字典
# 用于构建训练网络中的参数字典。
def build_params_dict(self, network):
r"""
Build the parameter's dict of the network.
Args:
network (Cell): The training network.
"""
cells = network.cells_and_names()
params_dict = {}
for _, cell in cells:
for par in cell.get_parameters(expand=False):
params_dict[id(par)] = cell
return params_dict
# 构建带有梯度中心化的参数组
# 用于构建带有梯度中心化的参数组。
def build_gc_params_group(self, params_dict, parameters):
r"""
Build the parameter's group with grad centralization.
Args:
params_dict (dict): The network's parameter dict.
parameters (list): The network's parameter list.
"""
group_params = []
for group_param in parameters:
if 'order_params' in group_param.keys():
group_params.append(group_param)
continue
params_gc_value = []
params_value = []
for param in group_param['params']:
if 'beta' not in param.name and 'gamma' not in param.name and 'bias' not in param.name:
param_cell = params_dict[id(param)]
if (isinstance(param_cell, nn.Conv2d) and param_cell.group > 1) or \
isinstance(param_cell, CommonHeadLastFN):
params_value.append(param)
else:
params_gc_value.append(param)
else:
params_value.append(param)
if params_gc_value:
new_group_param = copy.deepcopy(group_param)
new_group_param['params'] = params_gc_value
new_group_param['grad_centralization'] = True
group_params.append(new_group_param)
if params_value:
new_group_param = copy.deepcopy(group_param)
new_group_param['params'] = params_value
group_params.append(new_group_param)
return group_params
# 添加梯度中心化
# 根据传入的网络添加梯度中心化标签,修改参数组。
def add_grad_centralization(self, network):
r"""
Add gradient centralization.
Args:
network (Cell): The training network.
"""
params_dict = self.build_params_dict(network)
parameters = self.origin_params
if parameters is not None and not isinstance(parameters, list):
parameters = list(parameters)
if not parameters:
raise ValueError("Optimizer got an empty parameter list.")
if not isinstance(parameters[0], (dict, Parameter)):
raise TypeError("Only a list of Parameter or dict can be supported.")
if isinstance(parameters[0], Parameter):
logger.warning("Only group parameters support gradient centralization.")
return
self.origin_params = self.build_gc_params_group(params_dict, parameters)
# 生成新的优化器
# 根据保存的参数和初始化参数生成新的优化器实例,并返回该优化器。
def generate_new_optimizer(self):
"""Generate new optimizer."""
if self.learning_rate is None:
self.learning_rate = self.single_opt.learning_rate
if not self.is_lars:
opt = self.opt_class(params=self.origin_params, learning_rate=self.learning_rate, **self.opt_init_args)
else:
opt = LARS(self.opt_class(params=self.origin_params, learning_rate=self.learning_rate, \
**self.opt_init_args), **self.lars_init_args)
return opt
#这段代码定义了一个名为 ParameterProcess 的类,用于处理参数的一些操作,包括创建参数组和自动设置梯度分割点。
class ParameterProcess:
r"""
Process parameter for Boost. Currently, this class supports creating group parameters
and automatically setting gradient segmentation point.
Examples:
>>> from mindspore import Tensor, Parameter, nn
>>> import mindspore.ops as ops
>>> from mindspore.boost import OptimizerProcess
>>>
>>> class Net(nn.Cell):
... def __init__(self, in_features, out_features):
... super(Net, self).__init__()
... self.weight = Parameter(Tensor(np.ones([in_features, out_features]).astype(np.float32)),
... name='weight')
... self.weight2 = Parameter(Tensor(np.ones([in_features, out_features]).astype(np.float32)),
... name='weight2')
... self.matmul = ops.MatMul()
... self.matmul2 = ops.MatMul()
...
... def construct(self, x):
... output = self.matmul(x, self.weight)
... output2 = self.matmul2(x, self.weight2)
... return output + output2
...
>>> size, in_features, out_features = 16, 16, 10
>>> network = Net(in_features, out_features)
>>> new_parameter = net.trainable_params()[:1]
>>> parameter_process = ParameterProcess()
>>> group_params = parameter_process.generate_group_params(new_parameter, net.trainable_params())
"""
def __init__(self):
self._parameter_indices = 1
# 分配参数组
# 将参数分配到不同的组,并设置梯度分割点。
def assign_parameter_group(self, parameters, split_point=None):
r"""
Assign parameter group.
Args:
parameters (list): The network's parameter list.
split_point (list): The gradient split point of this network. default: None.
"""
if not isinstance(parameters, (list, tuple)) or not parameters:
return parameters
parameter_len = len(parameters)
if split_point:
split_parameter_index = split_point
else:
split_parameter_index = [parameter_len // 2]
for i in range(parameter_len):
if i in split_parameter_index:
self._parameter_indices += 1
parameters[i].comm_fusion = self._parameter_indices
return parameters
# 生成参数组
# 生成带有参数组的参数列表,用于优化器的设置。
def generate_group_params(self, parameters, origin_params):
r"""
Generate group parameters.
Args:
parameters (list): The network's parameter list.
origin_params (list): The network's origin parameter list.
"""
origin_params_copy = origin_params
if origin_params_copy is not None:
if not isinstance(origin_params_copy, list):
origin_params_copy = list(origin_params_copy)
if not origin_params_copy:
raise ValueError("Optimizer got an empty parameter list.")
if not isinstance(origin_params_copy[0], (dict, Parameter)):
raise TypeError("Only a list of Parameter or dict can be supported.")
if isinstance(origin_params_copy[0], Parameter):
group_params = [{"params": parameters}]
return group_params
group_params = []
params_name = [param.name for param in parameters]
new_params_count = copy.deepcopy(params_name)
new_params_clone = {}
max_key_number = 0
for group_param in origin_params_copy:
if 'order_params' in group_param.keys():
new_group_param = copy.deepcopy(group_param)
new_group_param['order_params'] = parameters
group_params.append(new_group_param)
continue
params_value = []
for param in group_param['params']:
if param.name in params_name:
index = params_name.index(param.name)
params_value.append(parameters[index])
new_params_count.remove(param.name)
new_group_param = copy.deepcopy(group_param)
new_group_param['params'] = params_value
group_params.append(new_group_param)
if len(group_param.keys()) > max_key_number:
max_key_number = len(group_param.keys())
new_params_clone = copy.deepcopy(group_param)
if new_params_count:
params_value = []
for param in new_params_count:
index = params_name.index(param)
params_value.append(parameters[index])
if new_params_clone:
new_params_clone['params'] = params_value
group_params.append(new_params_clone)
else:
group_params.append({"params": params_value})
return group_params
#该函数主要用于获取本地 PCA 矩阵的路径。
def _get_local_pca_mat_path(weight_load_dir, pca_mat_path, n_component, device_number, network):
"""
get local pca mat path.
Args:
weight_load_dir (str): The weight(ckpt) file directory to be load.
pca_mat_path (str): the path to load pca mat. Default: None.
n_component (int): pca component.
device_number (int): device number.
network (Cell): The network.
"""
if pca_mat_path is not None and os.path.exists(pca_mat_path) and os.path.isfile(pca_mat_path) and \
pca_mat_path.endswith(".npy"):
# 如果提供的 pca_mat_path 存在且是一个有效的 .npy 文件,则使用该路径
full_pca_mat_path = pca_mat_path
pca_mat_exist = True
else: # 否则,如果 weight_load_dir 存在且是一个目录,则构建临时的 PCA 矩阵文件路径
if weight_load_dir is None or not os.path.exists(weight_load_dir) or not os.path.isdir(weight_load_dir):
raise ValueError("The weight_load_dir: {} is None / not exists / not directory.".format(weight_load_dir))
full_pca_mat_path = os.path.join(weight_load_dir, "pca_mat_temp.npy")
pca_mat_exist = False
# 构建保存 PCA 计算结束标志的文件路径
save_pca_end_path = os.path.join(os.path.dirname(full_pca_mat_path), "save_pca_end.txt")
if os.path.exists(save_pca_end_path):
os.remove(save_pca_end_path)
# 获取全局排名rank和本地 PCA 矩阵路径
rank = _get_global_rank()
local_pca_mat_path = full_pca_mat_path[:-4] + "_rank_" + str(rank) + ".npy"
if os.path.exists(local_pca_mat_path):
os.remove(local_pca_mat_path)
# 如果排名不是设备数量的倍数,则返回本地 PCA 矩阵路径
if rank % device_number != 0:
return local_pca_mat_path
# 如果 PCA 矩阵已存在,则加载它,否则根据权重数据计算 PCA 矩阵并保存
if pca_mat_exist:
pca_mat = np.load(full_pca_mat_path)
else:
data = _load_weights(weight_load_dir, network)
pca_mat = _compute_pca_mat(data, n_component)
np.save(full_pca_mat_path, pca_mat)
# 保存本地 PCA 矩阵
_save_local_pca_mat(pca_mat, full_pca_mat_path, n_component)
return local_pca_mat_path
#该函数用于加载权重ckpt文件中的参数数据。
def _load_weights(weight_load_dir, network):
"""
load weights.
Args:
weight_load_dir (str): The weight(ckpt) file directory to be load.
network (Cell): The network.
"""
# 获取网络中需要梯度的参数列表
param_requires_grad_list = []
for param in network.trainable_params():
param_requires_grad_list.append(param.name)
# 初始化参数矩阵元组
param_mat_tuple = ()
# 获取权重文件列表
weight_file_list = os.listdir(weight_load_dir)
for file in weight_file_list: # 遍历权重文件列表
if not file.endswith('.ckpt'):
continue
file_path = os.path.join(weight_load_dir, file)
# 加载权重文件
param_dict = load_checkpoint(file_path)
param_tuple = ()
for key, value in param_dict.items(): # 遍历加载的参数字典
if key in param_requires_grad_list:
param_tuple += (value.asnumpy().reshape((1, -1)),) # 如果参数需要梯度,则将其转换为 NumPy 数组并添加到元组中
param = np.concatenate(param_tuple, axis=1) # 将参数元组合并为一个参数矩阵,并添加到元组中
param_mat_tuple += (param,)
param_mat = np.concatenate(param_mat_tuple, axis=0) # 将所有加载的参数矩阵合并为一个参数矩阵
return param_mat
#该函数用于计算PCA主成分分析的变换矩阵。
def _compute_pca_mat(data, n_component, randomized=True):
"""
compute pca mat.
Args:
data (array): array-like of shape (n_samples, n_features)
Training data, where `n_samples` is the number of samples
and `n_features` is the number of features.
n_component (int): pca component.
randomized (bool) if use randomized svd.
"""
if data.shape[0] < n_component:
raise ValueError("The samples: {} is less than: n_component {}.".format(data.shape[0], n_component))
if randomized: # 使用随机化的SVD计算PCA主成分
components = _randomized_svd(data, n_component)
else: # 使用标准的SVD计算PCA主成分
components = _full_svd(data, n_component)
return components
#该函数用于使用随机化的SVD方法计算PCA主成分。
def _randomized_svd(data, n_component, n_oversample=10, n_iter=1):
"""
compute pca mat use randomized svd.
Args:
data (array): array-like of shape (n_samples, n_features)
Training data, where `n_samples` is the number of samples
and `n_features` is the number of features.
n_component (int): pca component.
n_oversample (int): oversample num
n_iter (int): iteration count
"""
mean = np.mean(data, axis=0) # 计算数据的均值,并将数据居中化
data -= mean
n_random = n_component + n_oversample # 计算超采样后的随机向量数目
n_samples, n_features = data.shape # 获取数据的样本数量和特征数量
transpose = n_samples < n_features # 判断是否需要转置数据矩阵
if transpose:
data = data.T
q_mat = _randomized_range_finder(data, n_random, n_iter) # 使用随机化的方法获取样本空间的随机投影矩阵Q矩阵
b_mat = q_mat.T @ data # 计算B矩阵B = Q^T * X
u_hat, _, vt_mat = la.svd(b_mat, full_matrices=False) # 对B矩阵进行SVD分解得到U_hat和V^T矩阵
del b_mat
# 计算最终的U矩阵和V^T矩阵
u_mat = np.dot(q_mat, u_hat)
u_mat, vt_mat = _svd_flip(u_mat, vt_mat, transpose)
if transpose: # 如果需要转置返回U矩阵的转置否则返回V^T矩阵的前n_component行
components = u_mat[:, :n_component].T
else:
components = vt_mat[:n_component, :]
return components
#该函数用于使用标准的SVDSingular Value Decomposition方法计算PCA主成分。
def _full_svd(data, n_component):
"""
compute pca mat use full svd.
Args:
data (array): array-like of shape (n_samples, n_features)
Training data, where `n_samples` is the number of samples
and `n_features` is the number of features.
n_component (int): pca component.
"""
mean = np.mean(data, axis=0) # 计算数据的均值,并将数据居中化
data -= mean
u, _, v = la.svd(data, full_matrices=False) # 使用标准SVD方法分解数据矩阵得到U、S和V^T矩阵
_, v = _svd_flip(u, v) # 调整U和V^T矩阵的方向
components = v[:n_component] # 选取前n_component个主成分返回V^T的前n_component行
return components
#该函数用于使用随机SVD方法计算PCA主成分。
def _randomized_range_finder(data, size, n_iter=1):
"""
compute pca mat use randomized svd.
Args:
data (array): array-like of shape (n_samples, n_features)
Training data, where `n_samples` is the number of samples
and `n_features` is the number of features.
size (int): n_component + n_oversample.
n_iter (int): iteration count
"""
# 随机生成一个初始的Q矩阵其形状为 (n_features, size)
q_mat = np.random.normal(size=(data.shape[1], size))
# 进行多次迭代更新Q矩阵
for _ in range(n_iter):
q_mat, _ = la.lu(data @ q_mat, permute_l=True) # 使用LU分解对 data @ Q 进行正交化
q_mat, _ = la.lu(data.T @ q_mat, permute_l=True) # 使用LU分解对 data^T @ Q 进行正交化
q_mat, _ = la.qr(data @ q_mat, mode="economic") # 对 data @ Q 进行经济型QR分解得到正交矩阵Q
return q_mat
#该函数用于在SVD奇异值分解计算中对结果进行翻转以确保奇异向量左奇异向量和右奇异向量的一致性。
def _svd_flip(u, v, transpose=True):
"""
svd flip.
Args:
u (ndarray): the output of `linalg.svd`.
v (ndarray): the output of `linalg.svd`.
transpose (bool): if data is transposed.
"""
if not transpose:
# 如果数据未转置,则根据左奇异向量的最大绝对值元素的符号来翻转左奇异向量和右奇异向量
max_abs_cols = np.argmax(np.abs(u), axis=0)
signs = np.sign(u[max_abs_cols, range(u.shape[1])])
u *= signs
v *= signs[:, np.newaxis]
else:
# 如果数据已经转置,则根据右奇异向量的最大绝对值元素的符号来翻转左奇异向量和右奇异向量
max_abs_rows = np.argmax(np.abs(v), axis=1)
signs = np.sign(v[range(v.shape[0]), max_abs_rows])
u *= signs
v *= signs[:, np.newaxis]
return u, v
#该函数用于将 PCA主成分分析矩阵保存到本地文件中。
def _save_local_pca_mat(pca_mat, full_pca_mat_path, n_component):
"""
save pca mat.
Args:
pca_mat (numpy.ndarray): pca mat to be saved.
full_pca_mat_path (str): the path of full pca mat.
n_component (int): pca component.
"""
parallel_mode = auto_parallel_context().get_parallel_mode()
rank_size = 1 if parallel_mode == ParallelMode.STAND_ALONE else get_group_size()
local_dim = math.ceil(n_component / rank_size)
for rank_id in range(rank_size):
start_index = rank_id * local_dim
end_index = (rank_id + 1) * local_dim
pca_start_index = min(n_component, start_index)
pca_end_index = min(n_component, end_index)
p_local = np.zeros([local_dim, pca_mat.shape[1]])
if pca_start_index != pca_end_index:
p_local[0: pca_end_index - pca_start_index, :] = pca_mat[pca_start_index: pca_end_index, :]
local_pca_mat_path = full_pca_mat_path[:-4] + "_rank_" + str(rank_id) + ".npy"
np.save(local_pca_mat_path, p_local)
save_pca_end_path = os.path.join(os.path.dirname(full_pca_mat_path), "save_pca_end.txt")
os.mknod(save_pca_end_path)
#该函数用于从本地加载 PCA主成分分析矩阵。
def _load_local_pca_mat(local_pca_mat_path, timeout):
"""
load pca mat.
Args:
local_pca_mat_path (str): local pca mat file path.
"""
save_pca_end_path = os.path.join(os.path.dirname(local_pca_mat_path), "save_pca_end.txt")
start_time = time.time()
while True:
current_time = time.time()
if (current_time - start_time) > timeout:
raise RuntimeError("the time of waiting to load local pca mat is larger than {} second.".format(timeout))
if os.path.exists(save_pca_end_path):
break
time.sleep(5)
pca_mat = np.load(local_pca_mat_path)
return pca_mat

View File

@ -0,0 +1,409 @@
# Copyright 2021 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.
# ============================================================================
"""boost"""
import threading
from mindspore.nn.optim import SGD
from .less_batch_normalization import LessBN
from .grad_freeze import GradientFreeze
from .base import OptimizerProcess, ParameterProcess
from .base import _get_local_pca_mat_path
__all__ = ["AutoBoost"]
_boost_config_mode = ["auto", "manual", "enable_all", "disable_all"]
_boost_config_level = {
"O0": {
"less_bn": False,
"grad_freeze": False,
"adasum": False,
"grad_accumulation": False,
"dim_reduce": False},
"O1": {
"less_bn": True,
"grad_freeze": True,
"adasum": False,
"grad_accumulation": False,
"dim_reduce": False},
"O2": {
"less_bn": True,
"grad_freeze": True,
"adasum": True,
"grad_accumulation": False,
"dim_reduce": False}}
#定义了一个名为 AutoBoost 的类,用于提供自动加速网络训练和评估的功能。
class AutoBoost:
r"""
Provide auto accelerating for network.
Args:
level (str): Boost config level. Default: "O0".
boost_config_dict (dict): User config hyperparameter dict, recommended config format:
.. code-block::
{
"boost": {
"mode": "auto",
"less_bn": False,
"grad_freeze": False,
"adasum": False,
"grad_accumulation": False,
"dim_reduce": False
},
"common": {
"gradient_split_groups": [50, 100],
"device_number": 8
},
"less_bn": {
"fn_flag": True,
"gc_flag": True
},
"grad_freeze": {
"param_groups": 10,
"freeze_type": 1,
"freeze_p": 0.7,
"total_steps": 65536
}
"grad_accumulation": {
"grad_accumulation_step": 1
},
"dim_reduce": {
"rho": 0.55,
"gamma": 0.9,
"alpha": 0.001,
"sigma": 0.4,
"n_components": 32,
"pca_mat_path": None,
"weight_load_dir": None,
"timeout": 1800
}
}
- boost:
- mode (str): How to set the boost. Supports ["auto", "manual", "enable_all", "disable_all"].
Default: "auto".
- auto: Depend on the argument "boost_level" in class Model.
- manual: Depend on "boost_config_dict".
- enable_all: Set all boost functions true.
- disable_all: Set all boost functions false.
- less_bn (bool): Whether to apply less_bn function. Default: False.
- grad_freeze: (bool): Whether to apply grad_freeze function. Default: False.
- adasum (bool): Whether to apply adasum function. Default: False.
- grad_accumulation (bool): Whether to apply grad_accumulation function. Default: False.
- dim_reduce (bool): Whether to apply dim_reduce function. Default: False.
If set dim_reduce true, other functions will be false.
If set grad_freeze true and dim_reduce false, other functions will be false.
- common:
- gradient_split_groups (list): The gradient split point of this network. Default: [50, 100].
- device_number (int): Device number. Default: 8.
- less_bn:
- fn_flag (bool): Whether changing fc to fn. Default: True.
- gc_flag (bool): Whether to apply gc. Default: True.
- grad_freeze:
- param_groups (int): The number of parameter groups. Default: 10.
- freeze_type (int): Gradient freeze grouping strategy, select from [0, 1]. Default: 1.
- freeze_p (float): Gradient freezing probability. Default: 0.7.
- total_steps (int): Total training steps. Default: 65536.
- grad_accumulation:
- grad_accumulation_step (int): Steps to accumulate gradients. Default: 1.
- dim_reduce:
The leading principles of dim_reduce:
.. math::
\begin{align}
grad\_k &= pca\_mat \cdot grad\\
dk &= - bk \cdot grad\_k\\
sk &= rho ^ m \cdot dk\\
delta\_loss &= sigma \cdot grad\_k.T \cdot sk
\end{align}
Here:
- pca_mat (array): Shape (k*n), k is part of n_components, n is the size of weight.
- bk (array): Shape (k*k), is the symmetric positive definite matrix in Quasi-Newton method.
we need to find the m satisfy:
.. math::
new\_loss < old\_loss + delta\_loss
Then, get delta_grad to update the weights for model:
.. math::
\begin{align}
grad\_k\_proj &= pca\_mat.T \cdot grad\_k\\
new\_grad\_momentum &= gamma \cdot old\_grad\_momentum + grad - grad\_k\_proj\\
delta\_grad &= alpha \cdot new\_grad\_momentum - pca\_mat.T \cdot sk
\end{align}
- rho (float): Generally, it does not need to be modified. Default: 0.55.
- gamma (float): Generally, it does not need to be modified. Default: 0.9.
- alpha (float): Generally, it does not need to be modified. Default: 0.001.
- sigma (float): Generally, it does not need to be modified. Default: 0.4.
- n_components (int): PCA component. Default: 32.
- pca_mat_path (str): The path to load pca mat. Default: None.
- weight_load_dir (str): The directory to load weight files saved as ckpt. Default: None.
- timeout (int): Waiting time to load local pca mat. Default: 1800 (second).
User can load the config through the JSON file or use the dictionary directly.
The unconfigured parameters will adopt the default values.
Raises:
ValueError: The boost mode not in ["auto", "manual", "enable_all", "disable_all"].
Supported Platforms:
``Ascend``
Examples:
>>> from mindspore.boost import AutoBoost
>>> #1) when configuring the dict directly:
>>> boost_config_dict = {"boost": {"mode": "auto"}}
>>> boost = AutoBoost("O1", boost_config_dict)
>>>
>>> #2) when loading the dict from a json file:
>>> import json
>>> boost_json = "/path/boost_config.json"
>>> with open(boost_json, 'r') as fp:
>>> boost_config_dict = json.load(fp)
>>> boost = AutoBoost("O1", boost_config_dict)
"""
_instance_lock = threading.Lock()
_instance = None
def __init__(self, level="O0", boost_config_dict=""):
if level not in _boost_config_level.keys():
level = "O0"
if self._instance.level is None:
# 初始化一些默认参数和配置
self.level = level
self.boost_config_dict = boost_config_dict
self._fn_flag = True
self._gc_flag = True
self._param_groups = 10
self._freeze_type = 1
self._freeze_p = 0.7
self._total_steps = 65536
self.gradient_groups = None
self.device_number = 8
self.grad_accumulation_step = 1
self.rho = 0.55
self.gamma = 0.9
self.alpha = 0.001
self.sigma = 0.4
self.n_components = 32
self.pca_mat_path = None
self.weight_load_dir = None
self.local_pca_mat_path = None
self.timeout = 1800
self.boost_config = self._get_configuration(level, self.boost_config_dict)
self._param_processer = ParameterProcess()
# pylint: disable=unused-argument
def __new__(cls, *args, **kwargs):
if AutoBoost._instance is None:
with AutoBoost._instance_lock:
if AutoBoost._instance is None:
AutoBoost._instance = object.__new__(cls)
AutoBoost._instance.level = None
AutoBoost._instance.boost_config_dict = None
return AutoBoost._instance
# 根据配置自动处理网络训练
def network_auto_process_train(self, network, optimizer):
r"""
Boost network train.
Args:
network (Cell): The training network.
optimizer (Cell): Optimizer for updating the weights.
"""
# 如果启用了维度降低功能
if self.boost_config["dim_reduce"]:
# 获取本地PCA矩阵的路径
self.local_pca_mat_path = _get_local_pca_mat_path(self.weight_load_dir, self.pca_mat_path,
self.n_components, self.device_number, network)
optimizer = SGD(network.trainable_params(), learning_rate=1) # 创建一个新的SGD优化器用于维度降低
setattr(optimizer, "dim_reduce", True) # 设置优化器的dim_reduce属性为True
return network, optimizer # 返回修改后的网络和优化器
# 如果启用了减少Batch NormalizationLessBN功能
if self.boost_config["less_bn"]:
network = LessBN(network, fn_flag=self._fn_flag) # 使用LessBN对网络进行修改可以选择是否改变全连接层为全标准化层
optimizer_process = OptimizerProcess(optimizer) # 创建优化器处理器
group_params = self._param_processer.assign_parameter_group(network.trainable_params(), # 将网络的可训练参数分组
self.gradient_groups)
# 生成新的参数组并更新优化器参数
optimizer_process.origin_params = \
self._param_processer.generate_group_params(group_params, optimizer_process.origin_params)
if self._gc_flag: # 如果启用了梯度中心化grad centralization则进行梯度中心化处理
optimizer_process.add_grad_centralization(network)
optimizer = optimizer_process.generate_new_optimizer() # 生成新的优化器
# 如果启用了梯度冻结Gradient Freeze功能
if self.boost_config["grad_freeze"]:
# 创建梯度冻结处理器
freeze_processer = GradientFreeze(self._param_groups, self._freeze_type,
self._freeze_p, self._total_steps)
network, optimizer = freeze_processer.freeze_generate(network, optimizer) # 对网络和优化器进行梯度冻结处理
# 如果启用了Adasum功能
if self.boost_config["adasum"]:
setattr(optimizer, "adasum", True) # 设置优化器的adasum属性为True
return network, optimizer # 返回修改后的网络和优化器
# 根据配置自动处理网络评估
def network_auto_process_eval(self, network):
r"""
Boost network eval.
Args:
network (Cell): The inference network.
"""
# 如果启用了维度降低功能
if self.boost_config["dim_reduce"]:
return network # 直接返回网络,不进行其他处理
# 如果启用了减少Batch NormalizationLessBN功能
if self.boost_config["less_bn"]:
network = LessBN(network) # 使用LessBN对网络进行修改
return network # 返回修改后的网络
def set_fn_flag(self, fn_flag):
self._fn_flag = fn_flag
def set_gc_flag(self, gc_flag):
self._gc_flag = gc_flag
def set_param_groups(self, param_groups):
self._param_groups = param_groups
def set_freeze_type(self, freeze_type):
self._freeze_type = freeze_type
def set_freeze_p(self, freeze_p):
self._freeze_p = freeze_p
def set_total_steps(self, total_steps):
self._total_steps = total_steps
def set_device_number(self, device_number):
self.device_number = device_number
def set_grad_accumulation_step(self, grad_accumulation_step):
self.grad_accumulation_step = grad_accumulation_step
def set_gradient_split_groups(self, gradient_groups):
# 检查梯度分割点是否为列表或整数,如果不是则引发值错误异常
if not isinstance(gradient_groups, (list, int)):
raise ValueError(f"gradient_groups `{gradient_groups}` is not in (list, int)")
# 如果传入的是整数,将其转换为包含一个元素的列表
if isinstance(gradient_groups, int):
gradient_groups = list(gradient_groups)
self.gradient_groups = gradient_groups # 设置梯度分割点组
def set_rho(self, rho):
self.rho = rho
def set_gamma(self, gamma):
self.gamma = gamma
def set_alpha(self, alpha):
self.alpha = alpha
def set_sigma(self, sigma):
self.sigma = sigma
def set_n_components(self, n_components):
self.n_components = n_components
def set_pca_mat_path(self, pca_mat_path):
self.pca_mat_path = pca_mat_path
def set_weight_load_dir(self, weight_load_dir):
self.weight_load_dir = weight_load_dir
def set_timeout(self, timeout):
self.timeout = timeout
def _get_configuration(self, level, boost_config_dict):
"""Get configuration."""
level_config = _boost_config_level[level] # 获取指定级别的配置信息
if not boost_config_dict: # 如果没有提供用户配置字典,直接返回指定级别的配置信息
return level_config
mode = "auto" # 默认使用 "auto" 模式
# 检查用户配置字典中是否包含 boost 配置,以及是否有指定 boost 模式
if 'boost' in boost_config_dict and 'mode' in boost_config_dict['boost']:
mode = boost_config_dict['boost']['mode']
# 检查 boost 模式是否合法,如果不合法则引发值错误异常
if mode not in _boost_config_mode:
raise ValueError("The boost mode must be in {}, but got {}".format(_boost_config_mode, mode))
# 根据不同的模式来处理配置信息
if mode == "manual":
# 如果是手动模式,使用用户提供的 boost 配置来覆盖默认配置
for key, value in boost_config_dict["boost"].items():
if key in level_config:
level_config[key] = value
elif mode == "enable_all": # 如果是启用所有模式,将所有 boost 配置项设置为 True
level_config = {key: True for key in level_config}
elif mode == "disable_all": # 如果是禁用所有模式,将所有 boost 配置项设置为 False
level_config = {key: False for key in level_config}
# 提取有效的 boost 配置信息,只保留在指定级别中的配置项和 "common" 中的配置项
valid_boost_each_mode_config = []
for key, boost_each_mode_config in boost_config_dict.items():
if key in level_config.keys() and level_config[key] or key == "common":
valid_boost_each_mode_config.append(boost_each_mode_config)
# 遍历有效的配置信息,根据配置项调用对应的设置方法
for boost_each_mode_config in valid_boost_each_mode_config:
for key_s in boost_each_mode_config.keys():
if key_s in self._boost_config_func_map:
self._boost_config_func_map[key_s](self, boost_each_mode_config[key_s])
# 返回最终的配置信息
return level_config
_boost_config_func_map = {
"fn_flag": set_fn_flag,
"gc_flag": set_gc_flag,
"param_groups": set_param_groups,
"freeze_type": set_freeze_type,
"freeze_p": set_freeze_p,
"total_steps": set_total_steps,
"device_number": set_device_number,
"gradient_split_groups": set_gradient_split_groups,
"grad_accumulation_step": set_grad_accumulation_step,
"rho": set_rho,
"gamma": set_gamma,
"alpha": set_alpha,
"sigma": set_sigma,
"n_components": set_n_components,
"pca_mat_path": set_pca_mat_path,
"weight_load_dir": set_weight_load_dir,
"timeout": set_timeout
}

View File

@ -0,0 +1,585 @@
# Copyright 2021 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.
# ============================================================================
"""Boost Mode Cell Wrapper."""
from mindspore.nn.wrap import TrainOneStepCell
import mindspore.context as context
from mindspore.context import ParallelMode
from mindspore.parallel._utils import _get_global_rank, _get_device_num, _get_gradients_mean
from mindspore.communication.management import get_group_size, create_group
from mindspore.nn.cell import Cell
from mindspore.common import Tensor, RowTensor
from mindspore.common.parameter import Parameter, ParameterTuple
from mindspore.nn.wrap.grad_reducer import DistributedGradReducer
from mindspore.ops import functional as F
from mindspore.ops import composite as C
from mindspore.ops import operations as P
from mindspore.common import dtype as mstype
from .boost import AutoBoost
from .grad_freeze import FreezeOpt, freeze_cell
from .adasum import AdaSum
from .dim_reduce import DimReduce
from .grad_accumulation import gradient_accumulation_op, gradient_clear_op
from .base import _load_local_pca_mat
__all__ = ["BoostTrainOneStepCell", "BoostTrainOneStepWithLossScaleCell"]
_get_delta_weight = C.MultitypeFuncGraph("_get_delta_weight")
@_get_delta_weight.register("Tensor", "Tensor")
def _get_delta_weight_process(new_parameter, old_parameter):
delta_w = old_parameter - new_parameter
return delta_w
_save_weight = C.MultitypeFuncGraph("_save_weight")
@_save_weight.register("Tensor", "Tensor")
def _save_weight_process(new_parameter, old_parameter):
return P.Assign()(new_parameter, old_parameter)
_grad_scale = C.MultitypeFuncGraph("grad_scale")
reciprocal = P.Reciprocal()
@_grad_scale.register("Tensor", "Tensor")
def tensor_grad_scale(scale, grad):
return grad * F.cast(reciprocal(scale), F.dtype(grad))
@_grad_scale.register("Tensor", "RowTensor")
def tensor_grad_scale_row_tensor(scale, grad):
return RowTensor(grad.indices,
grad.values * F.cast(reciprocal(scale), F.dtype(grad.values)),
grad.dense_shape)
_grad_overflow = C.MultitypeFuncGraph("_grad_overflow")
grad_overflow = P.FloatStatus()
@_grad_overflow.register("Tensor")
def _tensor_grad_overflow(grad):
return grad_overflow(grad)
@_grad_overflow.register("RowTensor")
def _tensor_grad_overflow_row_tensor(grad):
return grad_overflow(grad.values)
#一个名为 BoostTrainOneStepCell 的类,用于包装训练网络和优化器,实现训练过程中的一步。
class BoostTrainOneStepCell(TrainOneStepCell):
r"""
Boost Network training package class.
Wraps the network with an optimizer. The resulting Cell is trained with input '\*inputs'.
The backward graph will be created in the construct function to update the parameter. Different
parallel modes are available for training.
Args:
network (Cell): The training network. The network only supports single output.
optimizer (Union[Cell]): Optimizer for updating the weights.
sens (numbers.Number): The scaling number to be filled as the input of backpropagation. Default value is 1.0.
Inputs:
- **(\*inputs)** (Tuple(Tensor)) - Tuple of input tensors with shape :math:`(N, \ldots)`.
Outputs:
Tensor, a tensor means the loss value, the shape of which is usually :math:`()`.
Raises:
TypeError: If `sens` is not a number.
Supported Platforms:
``Ascend`` ``GPU`` ``CPU``
Examples:
>>> from mindspore import boost
>>> net = Net()
>>> loss_fn = nn.SoftmaxCrossEntropyWithLogits()
>>> optim = nn.Momentum(net.trainable_params(), learning_rate=0.1, momentum=0.9)
>>> #1) Using the WithLossCell existing provide
>>> loss_net = nn.WithLossCell(net, loss_fn)
>>> train_net = boost.BoostTrainOneStepCell(loss_net, optim)
>>>
>>> #2) Using user-defined WithLossCell
>>> class MyWithLossCell(Cell):
... def __init__(self, backbone, loss_fn):
... super(MyWithLossCell, self).__init__(auto_prefix=False)
... self._backbone = backbone
... self._loss_fn = loss_fn
...
... def construct(self, x, y, label):
... out = self._backbone(x, y)
... return self._loss_fn(out, label)
...
... @property
... def backbone_network(self):
... return self._backbone
...
>>> loss_net = MyWithLossCell(net, loss_fn)
>>> train_net = boost.BoostTrainOneStepCell(loss_net, optim)
"""
def __init__(self, network, optimizer, sens=1.0):
# 调用父类的初始化方法传入训练网络network、优化器optimizer和敏感度sens
super(BoostTrainOneStepCell, self).__init__(network, optimizer, sens)
self.hyper_map = C.HyperMap() # 创建一个超映射HyperMap对象用于并行操作
self.freeze = isinstance(optimizer, FreezeOpt) # 检查是否使用梯度冻结FreezeOpt如果不是则获取优化器的参数作为权重
if not self.freeze:
self.weights = self.optimizer.parameters
self.train_strategy = getattr(self.optimizer, 'train_strategy', None) # 获取优化器的训练策略train_strategy默认为None
# 检查是否在数据并行或独立模式下使用梯度累积,并根据配置信息设置相应的参数
auto_boost = AutoBoost()
self.use_grad_accumulation = self.parallel_mode in (ParallelMode.DATA_PARALLEL, ParallelMode.STAND_ALONE)
self.use_grad_accumulation = self.use_grad_accumulation & auto_boost.boost_config["grad_accumulation"]
self.max_accumulation_step = 1
if self.use_grad_accumulation:
self.max_accumulation_step = auto_boost.grad_accumulation_step
if self.max_accumulation_step <= 1:
self.max_accumulation_step = 1
self.use_grad_accumulation = False
# 如果启用梯度累积,则创建用于累积梯度的参数和变量
self.accumulation_step = Parameter(Tensor(0, dtype=mstype.int32), name="accumulation_step")
if self.use_grad_accumulation:
self.grad_accumulation = self.weights.clone(prefix="grad_accumulation", init='zeros')
# 检查是否启用维度降维dimension reduction
self.enable_dim_reduce = self.check_dim_reduce_enable()
if self.enable_dim_reduce:
local_pca_mat_path = auto_boost.local_pca_mat_path
rho = auto_boost.rho
gamma = auto_boost.gamma
alpha = auto_boost.alpha
sigma = auto_boost.sigma
_rank = _get_global_rank()
_rank_size = 1 if self.parallel_mode == ParallelMode.STAND_ALONE else get_group_size()
_device_number = auto_boost.device_number
n_components = auto_boost.n_components
timeout = auto_boost.timeout
pca_mat = _load_local_pca_mat(local_pca_mat_path, timeout) # 加载本地的 PCA 矩阵
self.weights_clone = ParameterTuple(self.weights).clone(prefix="weights_clone", init="same") # 创建权重的克隆,用于维度降维
# 创建维度降维对象
self.dim_reduce = DimReduce(self.network, self.optimizer, self.weights, pca_mat, n_components, rho, gamma,
alpha, sigma, _rank, _rank_size)
# 初始化梯度冻结相关的参数和变量
self.freeze_nets = None
self.step = Parameter(Tensor(0, dtype=mstype.int32))
if self.freeze:
if self.reducer_flag:
self.mean = _get_gradients_mean()
self.degree = _get_device_num()
else:
self.mean = None
self.degree = None
# 创建梯度冻结的网络
self.freeze_nets = freeze_cell(self.reducer_flag, self.network, self.optimizer, self.sens,
self.grad, self.use_grad_accumulation, self.mean, self.degree,
self.max_accumulation_step)
# 检查是否启用 AdasumAll-reduce算法如果启用则配置相关参数
self.enable_adasum = self.check_adasum_enable()
self.sync_tensor = Parameter(Tensor(0, dtype=mstype.int32))
if self.enable_adasum:
_rank = _get_global_rank()
_rank_size = get_group_size()
_device_number = auto_boost.device_number
self.device_number = _device_number
group_number = _rank_size // _device_number
# 计算当前设备的排名
self.server_rank = _rank % _device_number
# 计算每个设备的参数范围
parameter_rank_number = len(self.weights) // _device_number
self.start = [x * parameter_rank_number for x in range(_device_number)]
self.end = [(x + 1) * parameter_rank_number for x in range(_device_number)]
self.end[-1] = len(self.weights)
# 获取当前设备的参数
current_weights = self.weights[self.start[self.server_rank]: self.end[self.server_rank]]
# 创建梯度的克隆对象,用于 Adasum 算法
self.grad_clone = ParameterTuple(current_weights).clone(prefix="delta_weight")
# 创建 Adasum 算法对象
self.adasum = AdaSum(_rank, _device_number, group_number, self.grad_clone)
# 计算每个组的参数个数
self.degree = int(self.degree / group_number)
# 创建分组列表
group_list = [list(range(x * self.degree, (x + 1) * self.degree)) for x in range(group_number)]
# 计算当前设备所在组的名称
current_index = _rank // _device_number
server_group_name = "allreduce_" + str(current_index)
# 创建分布式梯度归约器
create_group(server_group_name, group_list[current_index])
self.grad_reducer = DistributedGradReducer(self.weights, self.mean, self.degree, group=server_group_name)
def construct(self, *inputs):
if self.freeze: # 如果启用了梯度冻结
loss = self.gradient_freeze_process(*inputs) # 执行梯度冻结算法的处理
else: # 执行正常的训练过程
loss = self.network(*inputs) # 计算网络前向传播的损失 loss
sens = F.fill(loss.dtype, loss.shape, self.sens) # 使用损失 loss 的数据类型和形状创建感知度sens
grads = self.grad(self.network, self.weights)(*inputs, sens) # 计算梯度 grads
grads = self.grad_reducer(grads) # 对梯度 grads 进行归约操作,以适应并行训练环境
if self.use_grad_accumulation: # 如果启用了梯度累积
loss = self.gradient_accumulation_process(loss, grads, sens, *inputs) # 执行梯度累积算法的处理
else:
if self.enable_dim_reduce: # 如果启用了维度降低Dimension Reduction
# 执行维度降低算法的处理
loss = F.depend(loss, self.dim_reduce(loss, grads, sens, self.weights, self.weights_clone, *inputs))
elif self.enable_adasum: # 如果启用了 Adasum 算法
loss = F.depend(loss, self.adasum_process(loss, grads)) # 执行 Adasum 算法的处理
else: # 否则,执行正常的优化器更新操作
loss = F.depend(loss, self.optimizer(grads))
return loss # 返回损失值 loss
def gradient_freeze_process(self, *inputs):
r"""
Gradient freeze algorithm process.
Args:
inputs (tuple(Tensor)): Tuple of input tensors with shape :math:`(N, \ldots)`.
Outputs:
- **loss** (Tensor) - Network loss, tensor with shape :math:`()`.
"""
if self.train_strategy is None: # 如果未定义训练策略,则使用默认的 step 和 max_index
step = self.step
max_index = len(self.freeze_nets)
else: # 否则,根据训练策略获取当前 step 和 max_index
step = self.train_strategy[self.step]
max_index = len(self.train_strategy)
loss = self.freeze_nets[step](*inputs) # 使用当前 step 执行梯度冻结网络的前向传播,并计算损失 loss
if self.step + 1 >= max_index: # 更新 step如果超过最大索引 max_index则重置为 0
self.step = 0
else:
self.step += 1
return loss # 更新 step如果超过最大索引 max_index则重置为 0
def gradient_accumulation_process(self, loss, grads, sens, *inputs):
r"""
Gradient accumulation algorithm process.
Args:
loss (Tensor): Tensor with shape :math:`()`.
grads (tuple(Tensor)): Tuple of gradient tensors.
sens (Tensor): Tensor with shape :math:`()`.
inputs (tuple(Tensor)): Tuple of input tensors with shape :math:`(N, \ldots)`.
Outputs:
- **loss** (Tensor) - Network loss, tensor with shape :math:`()`.
"""
# 使用梯度累积操作将梯度累积到 grad_accumulation 张量中,并依赖于当前损失 loss
loss = F.depend(loss, self.hyper_map(F.partial(gradient_accumulation_op, self.max_accumulation_step),
self.grad_accumulation, grads))
self.accumulation_step += 1
if self.accumulation_step >= self.max_accumulation_step: # 如果累积步数达到最大累积步数,则执行以下操作
if self.enable_dim_reduce: # 如果启用了维度减少,则依赖于维度减少操作
loss = F.depend(loss, self.dim_reduce(loss, self.grad_accumulation, sens, self.weights,
self.weights_clone, *inputs))
elif self.enable_adasum: # 如果启用了 Adasum则依赖于 Adasum 处理
loss = F.depend(loss, self.adasum_process(loss, self.grad_accumulation))
else: # 否则,使用优化器更新梯度累积 grad_accumulation
loss = F.depend(loss, self.optimizer(self.grad_accumulation))
self.accumulation_step = 0
if self.accumulation_step == 0: # 如果累积步数为 0则清除梯度累积 grad_accumulation
loss = F.depend(loss, self.hyper_map(F.partial(gradient_clear_op), self.grad_accumulation))
return loss # 返回损失值 loss
def adasum_process(self, loss, grads):
r"""
Adasum algorithm process.
Args:
loss (Tensor): Tensor with shape :math:`()`.
grads (tuple(Tensor)): Tuple of gradient tensors.
Outputs:
- **loss** (Tensor) - Network loss, tensor with shape :math:`()`.
"""
loss = F.depend(loss, self.optimizer(grads)) # 使用优化器更新梯度 grads并依赖于当前损失 loss
rank_weights = self.weights[self.start[self.server_rank]: self.end[self.server_rank]] # 计算当前设备的权重张量 rank_weights
grad_clone = F.depend(self.grad_clone, loss) # 依赖于损失 loss 的梯度副本 grad_clone
delta_w = self.hyper_map(F.partial(_get_delta_weight), rank_weights, grad_clone) # 使用超映射操作计算梯度变化 delta_w
adasum_res = self.adasum(delta_w, rank_weights, grad_clone) # 计算 Adasum 结果 adasum_res
sync_tensor = F.depend(self.sync_tensor, adasum_res) # 创建同步张量 sync_tensor并依赖于 adasum_res
sync_flag = self.adasum.sync_barrier(sync_tensor) # 执行 Adasum 同步屏障操作
# 遍历每个设备,并根据同步结果更新权重
for i in range(self.device_number):
weight_tuple = self.weights[self.start[i]: self.end[i]]
node_rank = F.depend(weight_tuple, sync_flag)
update_weights = self.adasum.broadcast_list[i](node_rank)
if i == self.server_rank: # 如果是服务器设备,使用 grad_clone 更新权重
self.hyper_map(F.partial(_save_weight), self.grad_clone, update_weights)
else: # 如果是其他设备,使用权重元组更新权重
self.hyper_map(F.partial(_save_weight), weight_tuple, update_weights)
return loss # 返回损失值 loss
#该方法用于检查是否启用 Adasum 算法。
def check_adasum_enable(self):
r"""
Check adasum enable.
"""
if not getattr(self.optimizer, "adasum", None) or not self.reducer_flag: # 检查优化器中是否存在 adasum 属性,并且检查是否设置 reducer_flag
return False
_rank_size = get_group_size() # 获取当前训练组的总大小
_device_number = 8 # 设定设备数量
group_number = _rank_size // _device_number # 计算训练组的数量
is_enable = bool(group_number > 1 and group_number & (group_number - 1) == 0) # 判断是否满足启用条件Adasum 要求训练组数量为 2 的幂
return is_enable
#该方法用于检查是否启用维度降低dim_reduce功能。
def check_dim_reduce_enable(self):
r"""
Check dim_reduce enable.
"""
if not getattr(self.optimizer, "dim_reduce", None): # 检查优化器中是否存在 dim_reduce 属性
return False
return True # 如果存在 dim_reduce 属性,则表示启用了维度降低功能
class BoostTrainOneStepWithLossScaleCell(BoostTrainOneStepCell):
r"""
Boost Network training with loss scaling.
This is a training step with loss scaling. It takes a network, an optimizer and possibly a scale update
Cell as args. The loss scale value can be updated in both host side or device side. The
BoostTrainOneStepWithLossScaleCell will be compiled to be graph which takes `*inputs` as input data.
The Tensor type of `scale_sense` is acting as loss scaling value. If you want to update it on host side,
the value must be provided. If the Tensor type of `scale_sense` is not given, the loss scale update logic
must be provide by Cell type of `scale_sense`.
Args:
network (Cell): The training network. The network only supports single output.
optimizer (Cell): Optimizer for updating the weights.
scale_sense (Union[Tensor, Cell]): If this value is Cell type, the loss scaling update logic cell.If this value
is Tensor type, Tensor with shape :math:`()` or :math:`(1,)`.
Inputs:
- **(*inputs)** (Tuple(Tensor)) - Tuple of input tensors with shape :math:`(N, \ldots)`.
Outputs:
Tuple of 3 Tensor, the loss, overflow flag and current loss scaling value.
- **loss** (Tensor) - Tensor with shape :math:`()`.
- **overflow** (Tensor) - Tensor with shape :math:`()`, type is bool.
- **loss scaling value** (Tensor) - Tensor with shape :math:`()`
Raises:
TypeError: If `scale_sense` is neither Cell nor Tensor.
ValueError: If shape of `scale_sense` is neither (1,) nor ().
Supported Platforms:
``Ascend`` ``GPU``
Examples:
>>> import numpy as np
>>> from mindspore import Tensor, Parameter, nn
>>> import mindspore.ops as ops
>>> from mindspore.nn import WithLossCell
>>> from mindspore import dtype as mstype
>>> from mindspore import boost
>>>
>>> class Net(nn.Cell):
... def __init__(self, in_features, out_features):
... super(Net, self).__init__()
... self.weight = Parameter(Tensor(np.ones([in_features, out_features]).astype(np.float32)),
... name='weight')
... self.matmul = ops.MatMul()
...
... def construct(self, x):
... output = self.matmul(x, self.weight)
... return output
...
>>> size, in_features, out_features = 16, 16, 10
>>> #1) when the type of scale_sense is Cell:
>>> net = Net(in_features, out_features)
>>> loss = nn.MSELoss()
>>> optimizer = nn.Momentum(net.trainable_params(), learning_rate=0.1, momentum=0.9)
>>> net_with_loss = WithLossCell(net, loss)
>>> manager = nn.DynamicLossScaleUpdateCell(loss_scale_value=2**12, scale_factor=2, scale_window=1000)
>>> train_network = boost.BoostTrainOneStepWithLossScaleCell(net_with_loss, optimizer, scale_sense=manager)
>>> input = Tensor(np.ones([out_features, in_features]), mstype.float32)
>>> labels = Tensor(np.ones([out_features,]), mstype.float32)
>>> output = train_network(input, labels)
>>>
>>> #2) when the type of scale_sense is Tensor:
>>> net = Net(in_features, out_features)
>>> loss = nn.MSELoss()
>>> optimizer = nn.Momentum(net.trainable_params(), learning_rate=0.1, momentum=0.9)
>>> net_with_loss = WithLossCell(net, loss)
>>> inputs = Tensor(np.ones([size, in_features]).astype(np.float32))
>>> label = Tensor(np.zeros([size, out_features]).astype(np.float32))
>>> scaling_sens = Tensor(np.full((1), np.finfo(np.float32).max), dtype=mstype.float32)
>>> train_network = boost.BoostTrainOneStepWithLossScaleCell(net_with_loss, optimizer, scale_sense=scaling_sens)
>>> output = train_network(inputs, label)
"""
def __init__(self, network, optimizer, scale_sense):
super(BoostTrainOneStepWithLossScaleCell, self).__init__(network, optimizer, sens=None)
self.base = Tensor(1, mstype.float32) # 创建常量 Tensor用于计算损失缩放
self.reduce_sum = P.ReduceSum(keep_dims=False) # 创建用于 ReduceSum 操作的 P.ReduceSum 实例
self.less_equal = P.LessEqual() # 创建用于比较操作的 P.LessEqual 实例
self.allreduce = P.AllReduce() # 创建用于 AllReduce 操作的 P.AllReduce 实例
self.is_distributed = (self.parallel_mode != ParallelMode.STAND_ALONE) # 检查是否是分布式训练环境
self.gpu_target = (context.get_context("device_target") == "GPU") # 检查是否在 GPU 设备上运行
self.loss_scaling_manager = None # 初始化损失缩放管理器
if isinstance(scale_sense, Cell): # 如果 scale_sense 是 Cell 类型,则使用指定的损失缩放管理器
self.loss_scaling_manager = scale_sense
self.scale_sense = Parameter(Tensor(scale_sense.get_loss_scale(), dtype=mstype.float32),
name="scale_sense")
elif isinstance(scale_sense, Tensor): # 如果 scale_sense 是 Tensor 类型,则手动指定损失缩放值
if scale_sense.shape == (1,) or scale_sense.shape == (): # 检查损失缩放值的形状是否合法
self.scale_sense = Parameter(scale_sense, name='scale_sense')
else:
raise ValueError("The shape of scale_sense must be (1,) or (), but got {}".format(scale_sense.shape))
else: # 如果 scale_sense 不是合法类型,则抛出异常
raise TypeError("The scale_sense must be Cell or Tensor, but got {}".format(type(scale_sense)))
def construct(self, *inputs):
weights = self.weights # 获取网络权重
loss = self.network(*inputs) # 计算网络损失
scaling_sens = self.scale_sense # 获取损失缩放值
status, scaling_sens = self._start_overflow_check(loss, scaling_sens) # 开始进行损失缩放溢出检测
scaling_sens_filled = C.ones_like(loss) * F.cast(scaling_sens, F.dtype(loss)) # 对损失进行损失缩放
grads = self.grad(self.network, weights)(*inputs, scaling_sens_filled) # 计算网络梯度,并根据损失缩放值对梯度进行缩放
grads = self.hyper_map(F.partial(_grad_scale, scaling_sens), grads)
# get the overflow buffer
# 获取溢出状态的条件标志
cond = self._get_overflow_status(status, grads)
overflow = self._process_loss_scale(cond) # 处理损失缩放,确定是否发生溢出
# if there is no overflow, do optimize
# 如果没有溢出,执行优化器操作
if not overflow:
if self.use_grad_accumulation:
loss = self.gradient_accumulation_process(loss, grads, scaling_sens_filled, *inputs)
else:
if self.enable_dim_reduce:
loss = F.depend(loss, self.dim_reduce(loss, grads, scaling_sens_filled, self.weights,
self.weights_clone, *inputs))
elif self.enable_adasum:
loss = F.depend(loss, self.adasum_process(loss, grads))
else:
loss = F.depend(loss, self.optimizer(grads))
return loss, cond, scaling_sens # 返回损失、溢出标志和损失缩放值
#该函数用于重新设置损失缩放值
def _set_sense_scale(self, sens):
"""
If the user has set the sens in the training process and wants to reassign the value, he can call
this function again to make modification, and sens needs to be of type Tensor.
Inputs:
- **sens** (Tensor) - The new sense whose shape and type are the same with original `scale_sense`.
"""
if self.scale_sense and isinstance(sens, Tensor):
self.scale_sense.set_data(sens)
else:
raise TypeError("The input type must be Tensor, but got {}".format(type(sens)))
#该函数用于开始浮点溢出检测
def _start_overflow_check(self, pre_cond, compute_input):
"""
Start floating-point overflow detection. Create and clear the overflow detection state.
Specify the argument 'pre_cond' and 'compute_input' to make sure overflow status is cleared at the right time.
Taking this situation as an example, we need to execute state clearing after loss calculation and then detect
overflow in the process of gradient calculation. In this case, pre_cond should be the output of the loss
function, and compute_input should be the input of gradients-computing function.
Inputs:
- **pre_cond** (Tensor) - A precondition for starting overflow detection. It determines the executing order
of overflow state clearing and prior processions. It makes sure that the function 'start_overflow'
clears status after finishing the process of precondition.
- **compute_input** (object) - The input of subsequent process. Overflow detection should be performed on a
certain computation. Set `compute_input` as the input of the computation, to ensure overflow status is
cleared before executing the computation.
Outputs:
Tuple[object, object], the first value is False for GPU backend, while it is an instance of
NPUAllocFloatStatus for other backend. The status is used to detect overflow during overflow detection.
The second value is the same as the input of `compute_input`, but contains some information about the
execution order.
"""
status = False
if not self.gpu_target:
# init overflow buffer
# 初始化溢出缓冲区
status = P.NPUAllocFloatStatus()()
status = F.depend(status, pre_cond)
# clear overflow buffer
# 清除溢出缓冲区
clear_status = P.NPUClearFloatStatus()(status)
compute_input = F.depend(compute_input, clear_status)
return status, compute_input
#该函数用于获取浮点溢出状态
def _get_overflow_status(self, status, compute_output):
"""
Get floating-point overflow status.
Get overflow results after executing the target process for overflow detection.
Inputs:
- **status** (object) - A status instance used to detect the overflow.
- **compute_output** - Overflow detection should be performed on a certain computation. Set `compute_output`
as the output of the computation, to ensure overflow status is acquired before executing the
computation.
Outputs:
bool, whether the overflow occurs or not.
"""
if not self.gpu_target:
status = F.depend(status, compute_output)
get_status = P.NPUGetFloatStatus()(status)
status = F.depend(status, get_status)
# sum overflow buffer elements, 0:not overflow , >0:overflow
# 求和溢出缓冲区的元素0 表示没有溢出,>0 表示溢出
flag_sum = self.reduce_sum(status, (0,))
else:
flag_sum = self.hyper_map(F.partial(_grad_overflow), compute_output)
flag_sum = P.AddN()(flag_sum)
# convert flag_sum to scalar
# 将 flag_sum 转换为标量
flag_sum = P.Reshape()(flag_sum, (()))
if self.is_distributed:
# sum overflow flag over devices
# 在设备上汇总溢出标志
flag_reduce = self.allreduce(flag_sum)
overflow = self.less_equal(self.base, flag_reduce)
else:
overflow = self.less_equal(self.base, flag_sum)
return overflow
#该函数用于根据溢出情况计算损失缩放比例
def _process_loss_scale(self, overflow):
"""
Calculate loss scale according to the overflow.
Inputs:
- **overflow** (bool) - Whether the overflow occurs or not.
Outputs:
bool, overflow value.
"""
if self.loss_scaling_manager is not None:
return self.loss_scaling_manager(self.scale_sense, overflow)
return overflow

View File

@ -0,0 +1,197 @@
# Copyright 2021 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.
# ==============================================================================
"""Visualization for detection/segmentation dataset.
检测/分割数据集的可视化
"""
import os
import sys
import importlib
import numpy as np
from mindspore import log as logger
def imshow_det_bbox(image, bboxes, labels, segm=None, class_names=None, score_threshold=0, bbox_color=(0, 255, 0),
text_color=(203, 192, 255), mask_color=(128, 0, 128), thickness=2, font_size=0.8, show=True,
win_name="win", wait_time=2000, out_file=None):
"""Draw an image with given bboxes and class labels (with scores).
用给定的框和类标签带分数绘制一幅图像
Args:
image (ndarray): The image to be displayed, shaped (C, H, W) or (H, W, C), formatted RGB.
bboxes (ndarray): Bounding boxes (with scores), shaped (N, 4) or (N, 5),
data should be ordered with (N, x, y, w, h).
labels (ndarray): Labels of bboxes, shaped (N, 1).
segm (ndarray): The segmentation masks of image in M classes, shaped (M, H, W) (Default=None).
class_names (list[str], tuple[str], dict): Names of each class to map label to class name
(Default=None, only display label).
score_threshold (float): Minimum score of bboxes to be shown (Default=0).
bbox_color (tuple(int)): Color of bbox lines.
The tuple of color should be in BGR order (Default=(0, 255 ,0), means 'green').
text_color (tuple(int)): Color of texts.
The tuple of color should be in BGR order (Default=(203, 192, 255), means 'pink').
mask_color (tuple(int)): Color of mask.
The tuple of color should be in BGR order (Default=(128, 0, 128), means 'purple').
thickness (int): Thickness of lines (Default=2).
font_size (int, float): Font size of texts (Default=0.8).
show (bool): Whether to show the image (Default=True).
win_name (str): The window name (Default="win").
wait_time (int): Value of waitKey param (Default=2000, means display interval is 2000ms).
out_file (str, optional): The filename to write the imagee (Default=None). File extension name
is required to indicate the image compression type, e.g. 'jpg', 'png'.
Returns:
ndarray: The image with bboxes drawn on it.
Raises:
ImportError: If opencv-python is not installed.
AssertionError: If `image` is not in (H, W, C) or (C, H, W) format.
AssertionError: If `bboxes` is not in (N, 4) or (N, 5) format.
AssertionError: If `labels` is not in (N, 1) format.
AssertionError: If `segm` is not in (M, H, W) format.
AssertionError: If `class_names` is not of type list, tuple or dict.
AssertionError: If `bbox_color` is not a tuple in format of (B, G, R).
AssertionError: If `text_color` is not a tuple in format of (B, G, R).
AssertionError: If `mask_color` is not a tuple in format of (B, G, R).
Examples:
>>> import numpy as np
>>> import mindspore.dataset as ds
>>> from mindspore.dataset.utils.browse_dataset import imshow_det_bbox
>>>
>>> # Read Detection dataset, such as VOC2012.
>>> voc_dataset_dir = "/path/to/voc_dataset_directory"
>>> dataset = ds.VOCDataset(voc_dataset_dir, task="Detection", shuffle=False, decode=True, num_samples=5)
>>> dataset_iter = dataset.create_dict_iterator(output_numpy=True, num_epochs=1)
>>>
>>> # draw dataset
>>> for index, data in enumerate(dataset_iter):
... image = data["image"]
... bbox = data["bbox"]
... label = data["label"]
... # draw image with bboxes
... imshow_det_bbox(image, bbox, label,
... class_names=['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat',
... 'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike', 'person',
... 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor'],
... win_name="my_window",
... wait_time=5000,
... show=True,
... out_file="voc_dataset_{}.jpg".format(str(index)))
Examples using `imshow_det_bbox` on VOC2012:
.. image:: browse_dataset.png
"""
# 定义一个名为imshow_det_bbox的函数
def imshow_det_bbox(image, bboxes, labels, segm=None, class_names=None, score_threshold=0, bbox_color=(0, 255, 0),
text_color=(203, 192, 255), mask_color=(128, 0, 128), thickness=2, font_size=0.8, show=True,
win_name="win", wait_time=2000, out_file=None):
try:
# 尝试导入cv2模块OpenCV库如果导入失败抛出ImportError异常
cv2 = importlib.import_module("cv2")
except ModuleNotFoundError:
raise ImportError("Importing cv2 failed, try to install it by running `pip install opencv-python`.")
# 数据验证和参数检查
assert isinstance(image, np.ndarray) and image.ndim == 3 and (image.shape[0] == 3 or image.shape[2] == 3), \
"image must be a ndarray in (H, W, C) or (C, H, W) format."
if bboxes is not None:
assert isinstance(bboxes, np.ndarray) and bboxes.ndim == 2 and (bboxes.shape[1] == 4 or bboxes.shape[1] == 5), \
"bboxes must be a ndarray in (N, 4) or (N, 5) format."
assert isinstance(labels, np.ndarray) and labels.ndim == 2 and labels.shape[1] == 1 and \
labels.shape[0] == bboxes.shape[
0], "labels must be a ndarray in (N, 1) format and has same N with bboxes."
if segm is not None:
assert isinstance(segm, np.ndarray) and segm.ndim == 3, "segm must be a ndarray in (M, H, W) format."
H, W = (image.shape[0], image.shape[1]) if image.shape[2] == 3 else (image.shape[1], image.shape[2])
assert H == segm.shape[1] and W == segm.shape[2], "segm must has same height and width with image."
if bboxes is not None:
assert bboxes.shape[0] <= segm.shape[0], "number of segm masks must not be less than the number of bboxes."
assert isinstance(class_names, (tuple, list, dict)), "class_names must be a list, tuple or dict."
assert isinstance(bbox_color, tuple) and len(bbox_color) == 3, \
"bbox_color must be a three tuple, formatted (B, G, R)."
assert isinstance(text_color, tuple) and len(text_color) == 3, \
"text_color must be a three tuple, formatted (B, G, R)."
assert isinstance(mask_color, tuple) and len(mask_color) == 3, \
"mask_color must be a three tuple, formatted (B, G, R)."
assert isinstance(thickness, int), "thickness must be an int."
assert thickness >= 0, "thickness must be larger than or equal to zero."
assert isinstance(font_size, (int, float)), "font_size must be an int or float."
assert font_size >= 0, "font_size must be larger than or equal to zero."
assert isinstance(show, bool), "show must be a bool."
assert isinstance(win_name, str), "win_name must be a str."
assert isinstance(wait_time, int), "wait_time must be an int."
assert wait_time >= 0, "wait_time must be larger than or equal to zero."
if out_file is not None:
assert isinstance(out_file, str), "out_file must be a str."
if score_threshold > 0:
assert bboxes.shape[1] == 5
if not show:
assert out_file is not None
# 对图像进行处理
if image.shape[0] == 3:
image = image.transpose((1, 2, 0))
draw_image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
if bboxes is not None:
bbox_num = bboxes.shape[0]
for i in range(bbox_num):
draw_bbox = bboxes[i]
if len(draw_bbox) > 4:
if draw_bbox[4] < score_threshold:
continue
# bbox
x1, y1 = int(draw_bbox[0]), int(draw_bbox[1])
x2, y2 = int(draw_bbox[0] + draw_bbox[2]), int(draw_bbox[1] + draw_bbox[3])
cv2.rectangle(draw_image, (x1, y1), (x2, y2), bbox_color, thickness)
# label
try:
draw_label = str(class_names[labels[i][0]]) if class_names is not None else f'class {labels[i][0]}'
except (IndexError, KeyError):
draw_label = f'class {labels[i][0]}'
if len(draw_bbox) > 4:
draw_label += f'|{draw_bbox[-1]:.02f}'
cv2.putText(draw_image, draw_label, (x1, y2), cv2.FONT_HERSHEY_SIMPLEX, font_size, text_color, thickness)
if segm is not None:
mask = segm[i].astype(bool)
draw_image[mask] = draw_image[mask] * 0.5 + np.array(mask_color) * 0.5
else:
if segm is not None:
segm_num = segm.shape[0]
for i in range(segm_num):
mask = segm[i].astype(bool)
draw_image[mask] = draw_image[mask] * 0.5 + np.array(mask_color) * 0.5
# 如果需要显示图像调用cv2.imshow方法显示图像
if show:
cv2.imshow(win_name, draw_image)
if cv2.waitKey(wait_time) == 27:
sys.exit()
# 如果需要保存图像到文件使用cv2.imwrite方法保存图像
if out_file:
logger.info("Saving image file with name: " + out_file + "...")
cv2.imwrite(out_file, draw_image)
os.chmod(out_file, 0o600)
# 返回处理后的图像
return draw_image

View File

@ -0,0 +1,32 @@
/**
* Copyright 2022-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 "transform/graph_ir/op_declare/cluster_ops_declare.h"
namespace mindspore::transform {
// KMeansCentroids
INPUT_MAP(KMeansCentroids) = {
{1, INPUT_DESC(x)}, {2, INPUT_DESC(y)}, {3, INPUT_DESC(sum_square_y)}, {4, INPUT_DESC(sum_square_x)}};
//输入映射x索引为1y索引为2sum_square_y索引为3sum_square_x索引为4
ATTR_MAP(KMeansCentroids) = {
{"use_actual_distance", ATTR_DESC(use_actual_distance, AnyTraits<bool>(), AnyTraits<bool>())}};
//属性映射属性use_actual_distance类型为bool
OUTPUT_MAP(KMeansCentroids) = {
{0, OUTPUT_DESC(segment_sum)}, {1, OUTPUT_DESC(segment_count)}, {2, OUTPUT_DESC(kmean_total_sum)}};
//输出映射segment_sum索引为0segment_count索引为1kmean_total_sum索引为2
REG_ADPT_DESC(KMeansCentroids, prim::kPrimKMeansCentroids->name(), ADPT_DESC(KMeansCentroids))
//注册KMeansCentroids操作的适配器描述kPrimKMeansCentroids预设的name变量
} // namespace mindspore::transform

View File

@ -0,0 +1,858 @@
# Copyright 2019-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.
# ==============================================================================
"""
The configuration module provides various functions to set and get the supported
configuration parameters, and read a configuration file.
Common imported modules in corresponding API examples are as follows:
配置模块提供了各种功能来设置和获取支持配置参数并读取配置文件
.. code-block::
import mindspore.dataset as ds
"""
import os
import platform
import random
import numpy
import mindspore._c_dataengine as cde
from mindspore import log as logger
from .validator_helpers import replace_none
__all__ = ['set_sending_batches', 'load', '_init_device_info',
'set_seed', 'get_seed',
'set_prefetch_size', 'get_prefetch_size',
'set_num_parallel_workers', 'get_num_parallel_workers',
'set_numa_enable', 'get_numa_enable',
'set_monitor_sampling_interval', 'get_monitor_sampling_interval',
'set_callback_timeout', 'get_callback_timeout',
'set_auto_num_workers', 'get_auto_num_workers',
'set_enable_shared_mem', 'get_enable_shared_mem',
'set_enable_autotune', 'get_enable_autotune',
'set_autotune_interval', 'get_autotune_interval',
'set_auto_offload', 'get_auto_offload',
'set_enable_watchdog', 'get_enable_watchdog',
'set_multiprocessing_timeout_interval', 'get_multiprocessing_timeout_interval']
INT32_MAX = 2147483647
UINT32_MAX = 4294967295
_config = cde.GlobalContext.config_manager()
def _init_device_info():
"""
INTERNAL USE ONLY!
As rank_id need to pass into deep layer for numa and device_queue.
One process work with only one rank_id, In standalone scenario,
rank_id may come from env 'CUDA_VISIBLE_DEVICES', For distribute
scenario, rank_id come from _get_global_rank().
由于rank_id需要传递到numa和device_queue的深层
一个进程只使用一个rank_id在独立场景中rank_id可能来自envCUDA_VISIBLE_DEVICES用于分发场景中rank_id来自_get_global_rank
"""
# 导入必要的模块和类
from mindspore import context
from mindspore.parallel._auto_parallel_context import auto_parallel_context
from mindspore.parallel._utils import _get_global_rank
import os
# 默认情况下禁用 NUMANon-Uniform Memory Access支持
numa_enable = False
# 从环境变量中获取 NUMA_ENABLEDATASET_ENABLE_NUMA 和 MS_ENABLE_NUMA 之一)的值,如果为 "True" 则启用 NUMA
numa_enable_env = os.getenv("DATASET_ENABLE_NUMA", None)
if numa_enable_env and numa_enable_env.strip() == 'True':
numa_enable = True
numa_enable_env = os.getenv("MS_ENABLE_NUMA", None)
if numa_enable_env and numa_enable_env.strip() == 'True':
numa_enable = True
# 获取当前设备的目标GPU 或 Ascend
device_target = context.get_context("device_target")
# 如果设备目标是 GPU
if device_target == "GPU":
# 获取全局排名global rank
rank_id = _get_global_rank()
# 获取并行模式parallel mode
parallel_mode = auto_parallel_context().get_parallel_mode()
# 如果并行模式为 "stand_alone",则将 rank_id 设置为设备的 IDdevice_id
if parallel_mode == "stand_alone":
rank_id = context.get_context("device_id")
# 如果启用了 NUMA则设置 NUMA 支持为 True
if numa_enable:
_config.set_numa_enable(True)
# 设置 rank_id
_config.set_rank_id(rank_id)
# 如果设备目标是 Ascend
elif device_target == "Ascend":
# Ascend 是一个特殊情况,最好从环境变量中获取排名信息
env_rank_size = os.getenv("RANK_SIZE", None)
env_rank_id = os.getenv("RANK_ID", None)
rank_size = 0
rank_id = 0
# 如果环境变量中包含 RANK_SIZE 和 RANK_ID则解析它们并设置 rank_size 和 rank_id
if env_rank_size and env_rank_id:
try:
rank_size = int(env_rank_size.strip())
rank_id = int(env_rank_id.strip())
except ValueError:
raise ValueError("rank_size or rank_id is not int.")
# 如果排名数量大于 1且启用了 NUMA则设置 NUMA 支持为 True
if rank_size > 1:
if numa_enable:
_config.set_numa_enable(True)
# 设置 rank_id
_config.set_rank_id(rank_id)
def set_seed(seed):
"""
Set the seed so the random generated number will be fixed for deterministic results.
设置种子使随机生成的数字固定以获得确定性结果
Note:
This set_seed function sets the seed in the Python random library and numpy.random library
for deterministic Python augmentations using randomness. This set_seed function should
be called when iterator is created to reset the random seed.
Args:
seed(int): Random number seed. It is used to generate deterministic random numbers.
Raises:
TypeError: If `seed` isn't of type int.
ValueError: If `seed` < 0 or `seed` > UINT32_MAX(4294967295).
Examples:
>>> # Set a new global configuration value for the seed value.
>>> # Operations with randomness will use the seed value to generate random values.
>>> ds.config.set_seed(1000)
"""
# 检查输入的种子是否为整数且不是布尔值
if not isinstance(seed, int) or isinstance(seed, bool):
raise TypeError("seed isn't of type int.")
# 检查种子是否在合法范围内 [0, UINT32_MAX(4294967295)]
if seed < 0 or seed > UINT32_MAX:
raise ValueError(
"seed given is not within the required range [0, UINT32_MAX(4294967295)].")
# 使用 Config 设置随机数种子
_config.set_seed(seed)
# 使用 random 库设置 Python 的随机数种子
random.seed(seed)
# 注意numpy.random 不是线程安全的,因此在多线程环境中需要设置随机数种子
numpy.random.seed(seed)
def get_seed():
"""
Get random number seed. If the seed has been set, then will
return the set value, otherwise it will return the default seed value
which equals to std::mt19937::default_seed.
Returns:
int, random number seed.
Examples:
>>> # Get the global configuration of seed.
>>> # If set_seed() is never called before, the default value(std::mt19937::default_seed) will be returned.
>>> seed = ds.config.get_seed()
"""
return _config.get_seed()
def set_prefetch_size(size):
"""
Set the queue capacity of the thread in pipeline.
设置管道中线程的队列容量
Args:
size (int): The length of the cache queue.
Raises:
TypeError: If `size` is not of type int.
ValueError: If `size` <= 0 or `size` > INT32_MAX(2147483647).
Note:
Since total memory used for prefetch can grow very large with high number of workers,
when the number of workers is greater than 4, the per worker prefetch size will be reduced.
The actual prefetch size at runtime per-worker will be prefetchsize * (4 / num_parallel_workers).
Examples:
>>> # Set a new global configuration value for the prefetch size.
>>> ds.config.set_prefetch_size(1000)
"""
# 检查输入的大小是否为整数且不是布尔值
if not isinstance(size, int) or isinstance(size, bool):
raise TypeError("size isn't of type int.")
# 检查大小是否在合法范围内 (0, INT32_MAX(2147483647)]
if size <= 0 or size > INT32_MAX:
raise ValueError(
"size is not within the required range (0, INT32_MAX(2147483647)].")
# 使用 Config 设置操作连接器的大小,即设置预取大小
_config.set_op_connector_size(size)
def get_prefetch_size():
"""
Get the prefetch size as for number of rows.
If `set_prefetch_size` is never called before, the default value 16 will be returned.
获取行数的预取大小
如果以前从未调用过set_prefetch_size则将返回默认值16
Returns:
int, total number of rows to be prefetched.
Examples:
>>> # Get the global configuration of prefetch size.
>>> # If set_prefetch_size() is never called before, the default value(16) will be returned.
>>> prefetch_size = ds.config.get_prefetch_size()
"""
return _config.get_op_connector_size()
def set_num_parallel_workers(num):
"""
Set a new global configuration default value for the number of parallel workers.
This setting will affect the parallelism of all dataset operation.
为并行工作线程的数量设置一个新的全局配置默认值
此设置将影响所有数据集操作的并行性
Args:
num (int): Number of parallel workers to be used as a default for each operation.
Raises:
TypeError: If `num` is not of type int.
ValueError: If `num` <= 0 or `num` > INT32_MAX(2147483647).
Examples:
>>> # Set a new global configuration value for the number of parallel workers.
>>> # Now parallel dataset operators will run with 8 workers.
>>> ds.config.set_num_parallel_workers(8)
"""
# 检查输入的值是否为整数类型,且不是布尔类型
if not isinstance(num, int) or isinstance(num, bool):
raise TypeError("num isn't of type int.")
# 检查输入的值是否在合法范围内
if num <= 0 or num > INT32_MAX:
raise ValueError("Number of parallel workers given is not within the required range"
" (0, INT32_MAX(2147483647)].")
# 设置数据集的并行工作线程数
_config.set_num_parallel_workers(num)
def get_num_parallel_workers():
"""
Get the global configuration of number of parallel workers.
This is the DEFAULT num_parallel_workers value used for each operation.
获取并行工作者数量的全局配置
这是用于每个操作的DEFAULT num_paralle_workers值
Returns:
int, number of parallel workers to be used as a default for each operation.
Examples:
>>> # Get the global configuration of parallel workers.
>>> # If set_num_parallel_workers() is never called before, the default value(8) will be returned.
>>> num_parallel_workers = ds.config.get_num_parallel_workers()
"""
return _config.get_num_parallel_workers()
def set_numa_enable(numa_enable):
"""
Set the default state of numa enabled. If numa_enable is True, need to ensure numa library is installed.
设置numa enabled的默认状态如果numa_enable为True则需要确保安装了numa库
Args:
numa_enable (bool): Whether to use numa bind feature.
Raises:
TypeError: If `numa_enable` is not a boolean data type.
Examples:
>>> # Set a new global configuration value for the state of numa enabled.
>>> # Now parallel dataset operators will run with numa bind function
>>> ds.config.set_numa_enable(True)
"""
if not isinstance(numa_enable, bool):
raise TypeError("numa_enable must be a boolean dtype.")#如果 `numa_enable` 不是布尔类型将引发一个类型错误TypeError异常其中包含错误消息 "numa_enable must be a boolean dtype."
#如果 `numa_enable` 是布尔类型,调用 `_config.set_numa_enable(numa_enable)` 来设置NUMA支持的状态。这里假设 `_config` 是一个外部配置对象用于设置NUMA支持的状态。
_config.set_numa_enable(numa_enable)
def get_numa_enable():
"""
Get the state of numa to indicate enabled/disabled.
This is the DEFAULT numa enabled value used for the all process.
Returns:
bool, the default state of numa enabled.
Examples:
>>> # Get the global configuration of numa.
>>> numa_state = ds.config.get_numa_enable()
"""
return _config.get_numa_enable()
def set_monitor_sampling_interval(interval):
"""
Set the default interval (in milliseconds) for monitor sampling.
Args:
interval (int): Interval (in milliseconds) to be used for performance monitor sampling.
Raises:
TypeError: If `interval` is not type int.
ValueError: If `interval` <= 0 or `interval` > INT32_MAX(2147483647).
Examples:
>>> # Set a new global configuration value for the monitor sampling interval.
>>> ds.config.set_monitor_sampling_interval(100)
"""
if not isinstance(interval, int) or isinstance(interval, bool):
raise TypeError("interval isn't of type int.")
if interval <= 0 or interval > INT32_MAX:
raise ValueError(
"Interval given is not within the required range (0, INT32_MAX(2147483647)].")
_config.set_monitor_sampling_interval(interval)
def get_monitor_sampling_interval():
"""
Get the global configuration of sampling interval of performance monitor.
If `set_monitor_sampling_interval` is never called before, the default value(1000) will be returned.
Returns:
int, interval (in milliseconds) for performance monitor sampling.
Examples:
>>> # Get the global configuration of monitor sampling interval.
>>> # If set_monitor_sampling_interval() is never called before, the default value(1000) will be returned.
>>> sampling_interval = ds.config.get_monitor_sampling_interval()
"""
return _config.get_monitor_sampling_interval()
def set_auto_num_workers(enable):
"""
Set num_parallel_workers for each op automatically(This feature is turned off by default).
If turned on, the num_parallel_workers in each op will be adjusted automatically, possibly overwriting the
num_parallel_workers passed in by user or the default value (if user doesn't pass anything) set by
ds.config.set_num_parallel_workers().
For now, this function is only optimized for YoloV3 dataset with per_batch_map (running map in batch).
This feature aims to provide a baseline for optimized num_workers assignment for each operation.
Operation whose num_parallel_workers is adjusted to a new value will be logged.
Args:
enable (bool): Whether to enable auto num_workers feature or not.
Raises:
TypeError: If `enable` is not of boolean type.
Examples:
>>> # Enable auto_num_worker feature, this might override the num_parallel_workers passed in by user
>>> ds.config.set_auto_num_workers(True)
"""
if not isinstance(enable, bool):
raise TypeError("enable must be of type bool.")
_config.set_auto_num_workers(enable)
def _set_auto_workers_config(option):
"""
INTERNAL USE ONLY!
Select the weight profile of auto_num_workers. currently these 7 options are supported.
Option #0 leaf_num_workers:batch_num_workers:map_num_workers=1:1:1
Option #1 leaf_num_workers:batch_num_workers:map_num_workers=2:1:1
Option #2 leaf_num_workers:batch_num_workers:map_num_workers=1:2:1
Option #3 leaf_num_workers:batch_num_workers:map_num_workers=1:1:2
Option #4 leaf_num_workers:batch_num_workers:map_num_workers=2:2:1
Option #5 leaf_num_workers:batch_num_workers:map_num_workers=2:1:2
Option #6 leaf_num_workers:batch_num_workers:map_num_workers=1:2:2
Args:
option (int): The id of the profile to use.
Raises:
TypeError: If `option` is not of type int.
ValueError: If `option` is not within the range of [0, 6].
"""
if not isinstance(option, int) or isinstance(option, bool):
raise TypeError("option isn't of type int.")
if option < 0 or option > 6:
raise ValueError("option isn't within the required range of [0, 6].")
_config.set_auto_worker_config(option)
def get_auto_num_workers():
"""
Get the setting (turned on or off) automatic number of workers.
Returns:
bool, whether auto number worker feature is turned on.
Examples:
>>> # Get the global configuration of auto number worker feature.
>>> flag = ds.config.get_auto_num_workers()
"""
return _config.get_auto_num_workers()
def set_callback_timeout(timeout):
"""
Set the default timeout (in seconds) for DSWaitedCallback.
Args:
timeout (int): Timeout (in seconds) to be used to end the wait in DSWaitedCallback in case of a deadlock.
Raises:
TypeError: If `timeout` is not type int.
ValueError: If `timeout` <= 0 or `timeout` > INT32_MAX(2147483647).
Examples:
>>> # Set a new global configuration value for the timeout value.
>>> ds.config.set_callback_timeout(100)
"""
if not isinstance(timeout, int) or isinstance(timeout, bool):
raise TypeError("timeout isn't of type int.")
if timeout <= 0 or timeout > INT32_MAX:
raise ValueError("Timeout given is not within the required range.")
_config.set_callback_timeout(timeout)
def get_callback_timeout():
"""
Get the default timeout for WaitedDSCallback.
Returns:
int, Timeout (in seconds) to be used to end the wait in DSWaitedCallback in case of a deadlock.
Examples:
>>> # Get the global configuration of callback timeout.
>>> # If set_callback_timeout() is never called before, the default value(60) will be returned.
>>> callback_timeout = ds.config.get_callback_timeout()
"""
return _config.get_callback_timeout()
def __str__():
"""
String representation of the configurations.
Returns:
str, configurations.
"""
return str(_config)
def load(file):
"""
Load the project configuration from the file.
Args:
file (str): Path of the configuration file to be loaded.
Raises:
RuntimeError: If `file` is invalid and parsing fails.
Examples:
>>> # Set new default configuration according to values in the configuration file.
>>> # example config file:
>>> # {
>>> # "logFilePath": "/tmp",
>>> # "numParallelWorkers": 4,
>>> # "seed": 5489,
>>> # "monitorSamplingInterval": 30
>>> # }
>>> config_file = "/path/to/config/file"
>>> ds.config.load(config_file)
"""
_config.load(file)
def set_enable_autotune(enable, filepath_prefix=None):
"""
Set whether to enable AutoTune. AutoTune is disabled by default.
AutoTune is used to automatically adjust the global configuration of the data pipeline
according to the workload of environmental resources during the training process to
improve the speed of data processing.
The optimized global configuration can be saved as a JSON file by setting `json_filepath`
for subsequent reuse.
Args:
enable (bool): Whether to enable AutoTune.
filepath_prefix (str, optional): The prefix filepath to save the optimized global configuration.
The rank id and the json extension will be appended to the filepath_prefix string in multi-device training,
rank id will be set to 0 in standalone training.
For example, if filepath_prefix="/path/to/some/dir/prefixname" and rank_id is 1, then the path
of the generated file will be "/path/to/some/dir/prefixname_1.json"
If the file already exists, it will be automatically overwritten. Default: None,
means not to save the configuration file, but the tuned result still can be checked through INFO log.
Raises:
TypeError: If `enable` is not of type boolean.
TypeError: If `json_filepath` is not of type str.
RuntimeError: If `json_filepath` is an empty string.
RuntimeError: If `json_filepath` is a directory.
RuntimeError: If `json_filepath` does not exist.
RuntimeError: If `json_filepath` does not have write permission.
Note:
- When `enable` is False, `json_filepath` will be ignored.
- The JSON file can be loaded by API `mindspore.dataset.deserialize` to build a tuned pipeline.
- In distributed training scenario, set_enable_autotune() must be called after cluster communication has been
initialized (mindspore.communication.management.init()), otherwise the AutoTune file will always suffix with
rank id 0.
An example of the generated JSON file is as follows. "remark" file will conclude that if the dataset has been
tuned or not. "summary" filed will show the tuned configuration of dataset pipeline. Users can modify scripts
based on the tuned result.
.. code-block::
{
"remark": "The following file has been auto-generated by the Dataset AutoTune.",
"summary": [
"CifarOp(ID:5) (num_parallel_workers: 2, prefetch_size:64)",
"MapOp(ID:4) (num_parallel_workers: 2, prefetch_size:64)",
"MapOp(ID:3) (num_parallel_workers: 2, prefetch_size:64)",
"BatchOp(ID:2) (num_parallel_workers: 8, prefetch_size:64)"
],
"tree": {
...
}
}
Examples:
>>> # enable AutoTune and save optimized data pipeline configuration
>>> ds.config.set_enable_autotune(True, "/path/to/autotune_out.json")
>>>
>>> # enable AutoTune
>>> ds.config.set_enable_autotune(True)
"""
if not isinstance(enable, bool):
raise TypeError("enable must be of type bool.")
save_autoconfig = bool(enable and filepath_prefix is not None)
if filepath_prefix and not isinstance(filepath_prefix, str):
raise TypeError(
"json_filepath must be a str value but was: {}.".format(filepath_prefix))
if enable and filepath_prefix == "":
raise RuntimeError(
"The value of json_filepath cannot be the empty string.")
if not enable and filepath_prefix is not None:
logger.warning(
"The value of json_filepath is ignored when enable is False.")
if enable and filepath_prefix is None:
logger.warning(
"Dataset AutoTune is enabled but no json path is specified, check INFO log for tuned result.")
json_filepath = replace_none(filepath_prefix, "")
_config.set_enable_autotune(enable, save_autoconfig, json_filepath)
def get_enable_autotune():
"""
Get whether AutoTune is currently enabled.
Returns:
bool, whether AutoTune is currently enabled.
Examples:
>>> # get the state of AutoTune
>>> autotune_flag = ds.config.get_enable_autotune()
"""
return _config.get_enable_autotune()
def set_autotune_interval(interval):
"""
Set the configuration adjustment interval (in steps) for AutoTune.
The default setting is 0, which will adjust the configuration after each epoch.
Otherwise, the configuration will be adjusted every `interval` steps.
Args:
interval (int): Interval (in steps) to adjust the configuration of the data pipeline.
Raises:
TypeError: If `interval` is not of type int.
ValueError: If `interval` is not non-negative.
Examples:
>>> # set a new interval for AutoTune
>>> ds.config.set_autotune_interval(30)
"""
if not isinstance(interval, int) or isinstance(interval, bool):
raise TypeError("interval must be of type int.")
if interval < 0 or interval > INT32_MAX:
raise ValueError(
"Interval given is not within the required range [0, INT32_MAX(2147483647)].")
_config.set_autotune_interval(interval)
def get_autotune_interval():
"""
Get the current configuration adjustment interval (in steps) for AutoTune.
Returns:
int, the configuration adjustment interval (in steps) for AutoTune.
Examples:
>>> # get the global configuration of the autotuning interval
>>> autotune_interval = ds.config.get_autotune_interval()
"""
return _config.get_autotune_interval()
def get_enable_shared_mem():
"""
Get the default state of shared mem enabled variable.
Note:
`get_enable_shared_mem` is not supported on Windows and MacOS platforms yet.
Returns:
bool, the state of shared mem enabled variable.
Examples:
>>> # Get the flag of shared memory feature.
>>> shared_mem_flag = ds.config.get_enable_shared_mem()
"""
# For Windows and MacOS we forbid shared mem function temporarily
enable_shared_mem = _config.get_enable_shared_mem()
if enable_shared_mem and platform.system().lower() in {"windows", "darwin"}:
logger.warning(
"For Windows and MacOS we forbid shared mem function temporarily.")
_config.set_enable_shared_mem(False)
return False
return enable_shared_mem
def set_enable_shared_mem(enable):
"""
Set the default state of shared memory flag. If shared_mem_enable is True, will use shared memory queues
to pass data to processes that are created for operators that set python_multiprocessing=True.
Note:
`set_enable_shared_mem` is not supported on Windows and MacOS platforms yet.
Args:
enable (bool): Whether to use shared memory in operators when python_multiprocessing=True.
Raises:
TypeError: If `enable` is not a boolean data type.
Examples:
>>> # Enable shared memory feature to improve the performance of Python multiprocessing.
>>> ds.config.set_enable_shared_mem(True)
"""
if not isinstance(enable, bool):
raise TypeError("enable must be of type bool.")
if enable:
# For Windows and MacOS we forbid shared mem function temporarily
if platform.system().lower() in {"windows", "darwin"}:
logger.warning("For Windows and MacOS we forbid shared mem function temporarily.")
return
logger.warning("The shared memory is on, multiprocessing performance will be improved. "
"Note: the required shared memory can't exceeds 80% of the available shared memory.")
_config.set_enable_shared_mem(enable)
def set_sending_batches(batch_num):
"""
Set the default sending batches when training with sink_mode=True in Ascend device.
Args:
batch_num (int): the total sending batches, when batch_num is set, it will wait unless sending batches
increase, default is 0 which means will send all batches in dataset.
Raises:
TypeError: If `batch_num` is not of type int.
Examples:
>>> # Set a new global configuration value for the sending batches
>>> ds.config.set_sending_batches(10)
"""
if not isinstance(batch_num, int) or isinstance(batch_num, bool):
raise TypeError("batch_num must be an int dtype.")
_config.set_sending_batches(batch_num)
def set_auto_offload(offload):
"""
Set the automatic offload flag of the dataset. If set_auto_offload is True,
automatically offload as many dataset operations from the CPU to the Device (GPU or Ascend).
Args:
offload (bool): Whether to use the automatic offload feature.
Raises:
TypeError: If offload is not a boolean data type.
Examples:
>>> # Enable automatic offload feature
>>> ds.config.set_auto_offload(True)
"""
if not isinstance(offload, bool):
raise TypeError("offload must be a bool dtype")
_config.set_auto_offload(offload)
def get_auto_offload():
"""
Get the state of the automatic offload flag (True or False)
Returns:
bool, Whether the automatic offload feature is enabled.
Example:
>>> # Get the global configuration of the automatic offload feature.
>>> auto_offload = ds.config.get_auto_offload()
"""
return _config.get_auto_offload()
def set_enable_watchdog(enable):
"""
Set the default state of watchdog Python thread as enabled, the default state of watchdog Python thread is enabled.
Watchdog is a thread which cleans up hanging subprocesses.
Args:
enable (bool): Whether to launch a watchdog Python thread. System default: True.
Raises:
TypeError: If `enable` is not a boolean data type.
Examples:
>>> # Set a new global configuration value for the state of watchdog Python thread as enabled.
>>> ds.config.set_enable_watchdog(True)
"""
if not isinstance(enable, bool):
raise TypeError("enable must be a boolean dtype.")
_config.set_enable_watchdog(enable)
def get_enable_watchdog():
"""
Get the state of watchdog Python thread to indicate enabled or disabled state.
This is the DEFAULT watchdog Python thread state value used for the all processes.
Returns:
bool, the default state of watchdog Python thread enabled.
Examples:
>>> # Get the global configuration of watchdog Python thread.
>>> watchdog_state = ds.config.get_enable_watchdog()
"""
return _config.get_enable_watchdog()
def set_multiprocessing_timeout_interval(interval):
"""
Set the default interval (in seconds) for multiprocessing/multithreading timeout when main process/thread gets
data from subprocesses/child threads.
Args:
interval (int): Interval (in seconds) to be used for multiprocessing/multithreading timeout when main
process/thread gets data from subprocess/child threads. System default: 300s.
Raises:
TypeError: If `interval` is not of type int.
ValueError: If `interval` <= 0 or `interval` > INT32_MAX(2147483647).
Examples:
>>> # Set a new global configuration value for multiprocessing/multithreading timeout when getting data.
>>> ds.config.set_multiprocessing_timeout_interval(300)
"""
if not isinstance(interval, int) or isinstance(interval, bool):
raise TypeError("interval isn't of type int.")
if interval <= 0 or interval > INT32_MAX:
raise ValueError(
"Interval given is not within the required range (0, INT32_MAX(2147483647)).")
_config.set_multiprocessing_timeout_interval(interval)
def get_multiprocessing_timeout_interval():
"""
Get the global configuration of multiprocessing/multithreading timeout when main process/thread gets data from
subprocesses/child threads.
Returns:
int, interval (in seconds) for multiprocessing/multithreading timeout when main process/thread gets data from
subprocesses/child threads (default is 300s).
Examples:
>>> # Get the global configuration of multiprocessing/multithreading timeout when main process/thread gets data
>>> # from subprocesses/child threads. If set_multiprocessing_timeout_interval() is never called before, the
>>> # default value(300) will be returned.
>>> multiprocessing_timeout_interval = ds.config.get_multiprocessing_timeout_interval()
"""
return _config.get_multiprocessing_timeout_interval()
def set_dynamic_shape(is_dynamic):
"""
Set the dynamic shape flag of the dataset.
Args:
is_dynamic (bool): Whether the dataset is dynamic shape. Default: False
Raises:
TypeError: If `is_dynamic` is not a boolean data type.
Examples:
>>> ds.config.set_dynamic_shape(True)
"""
if not isinstance(is_dynamic, bool):
raise TypeError("is_dynamic must be a boolean dtype.")
_config.set_dynamic_shape(is_dynamic)
def get_dynamic_shape():
"""
Get the dynamic shape flag of the dataset
Returns:
bool, whether the dataset is dynamic shape.
Examples:
>>> is_dynamic_shape = ds.config.get_dynamic_shape()
"""
return _config.get_dynamic_shape()

View File

@ -0,0 +1,41 @@
/**
* 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_declare/control_flow_ops_declare.h"
namespace mindspore::transform {
// Merge
INPUT_MAP(Merge) = EMPTY_INPUT_MAP;
//输入映射,设为空
DYN_INPUT_MAP(Merge) = {{1, DYN_INPUT_DESC(x)}};
//动态输入映射将索引为1的动态输入与名称为x的动态输入描述关联起来用于后续操作
ATTR_MAP(Merge) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(Merge) = {{0, OUTPUT_DESC(y)}, {1, OUTPUT_DESC(value_index)}};
//输出映射y索引为0value_index索引为1
REG_ADPT_DESC(Merge, kNameMerge, ADPT_DESC(Merge))
//注册Merge操作的适配器描述kNameMerge
// Switch
INPUT_MAP(Switch) = {{1, INPUT_DESC(data)}, {2, INPUT_DESC(pred)}};
//输入映射data索引为1pred索引为2
OUTPUT_MAP(Switch) = {{0, OUTPUT_DESC(output_false)}, {1, OUTPUT_DESC(output_true)}};
//输出映射output_false索引为0output_true索引为1
ATTR_MAP(Switch) = EMPTY_ATTR_MAP;
//属性映射,设为空
REG_ADPT_DESC(Switch, kNameGeSwitch, ADPT_DESC(Switch))
//注册Switch操作的适配器描述kNameGeSwitch
} // namespace mindspore::transform

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
/**
* 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_declare/ctc_ops_declare.h"
namespace mindspore::transform {
// CTCLoss
INPUT_MAP(CTCLoss) = {{1, INPUT_DESC(inputs)},
{2, INPUT_DESC(labels_indices)},
{3, INPUT_DESC(labels_values)},
{4, INPUT_DESC(sequence_length)}};
//输入映射inputs索引为1labels_indices索引为2labels_values索引为3sequence_length索引为4
ATTR_MAP(CTCLoss) = {
{"preprocess_collapse_repeated", ATTR_DESC(preprocess_collapse_repeated, AnyTraits<bool>())},
{"ctc_merge_repeated", ATTR_DESC(ctc_merge_repeated, AnyTraits<bool>())},
{"ignore_longer_outputs_than_inputs", ATTR_DESC(ignore_longer_outputs_than_inputs, AnyTraits<bool>())}};
//属性映射属性preprocess_collapse_repeated类型为bool属性ctc_merge_repeated类型为bool属性ignore_longer_outputs_than_inputs类型为bool
OUTPUT_MAP(CTCLoss) = {{0, OUTPUT_DESC(loss)}, {1, OUTPUT_DESC(gradient)}};
//输出映射loss索引为0gradient索引为1
REG_ADPT_DESC(CTCLoss, kNameCTCLoss, ADPT_DESC(CTCLoss))
//注册CTCLoss操作的适配器描述KNameCTCLoss
// CTCGreedyDecoder
INPUT_MAP(CTCGreedyDecoder) = {{1, INPUT_DESC(inputs)}, {2, INPUT_DESC(sequence_length)}};
//输入映射inputs索引为1sequence_length索引为2
ATTR_MAP(CTCGreedyDecoder) = {{"merge_repeated", ATTR_DESC(merge_repeated, AnyTraits<bool>())}};
//属性映射属性merge_repeated类型为bool
OUTPUT_MAP(CTCGreedyDecoder) = {{0, OUTPUT_DESC(decoded_indices)},
{1, OUTPUT_DESC(decoded_values)},
{2, OUTPUT_DESC(decoded_shape)},
{3, OUTPUT_DESC(log_probability)}};
//输出映射decoded_indices索引为0decoded_values索引为1decoded_shape索引为2log_probability索引为1
REG_ADPT_DESC(CTCGreedyDecoder, kNameCTCGreedyDecoder, ADPT_DESC(CTCGreedyDecoder))
//注册CTCGreedyDecoder操作的适配器描述KNameCTCGreedyDecoder
} // namespace mindspore::transform

View File

@ -0,0 +1,53 @@
/**
* 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 "transform/graph_ir/op_declare/data_flow_ops_declare.h"
#include <vector>
#include <string>
namespace mindspore::transform {
INPUT_MAP(TensorArray) = {{1, INPUT_DESC(size)}};
//输入映射size索引为1
ATTR_MAP(TensorArray) = {{"dtype", ATTR_DESC(dtype, AnyTraits<GEType>())},
{"element_shape", ATTR_DESC(element_shape, AnyTraits<std::vector<int64_t>>())},
{"dynamic_size", ATTR_DESC(dynamic_size, AnyTraits<bool>())},
{"clear_after_read", ATTR_DESC(clear_after_read, AnyTraits<bool>())},
{"identical_element_shapes", ATTR_DESC(identical_element_shapes, AnyTraits<bool>())},
{"tensor_array_name", ATTR_DESC(tensor_array_name, AnyTraits<std::string>())}};
//属性映射属性dtype类型为GEType属性element_shape类型为int64_t属性dynamic_size类型为bool属性identical_element_shapes类型为bool
//属性clear_after_read类型为bool属性tensor_array_name类型为bool
OUTPUT_MAP(TensorArray) = {{0, OUTPUT_DESC(handle)}, {1, OUTPUT_DESC(flow)}};
//输出映射handle索引为0flow索引为1
REG_ADPT_DESC(TensorArray, kNameTensorArray, ADPT_DESC(TensorArray))
//注册TensorArray,操作的适配器描述KNameTensorArray,
INPUT_MAP(TensorArrayWrite) = {
{1, INPUT_DESC(handle)}, {2, INPUT_DESC(index)}, {3, INPUT_DESC(value)}, {4, INPUT_DESC(flow_in)}};
//输入映射handle索引为1index索引为2value索引为3flow_in索引为4
ATTR_MAP(TensorArrayWrite) = EMPTY_ATTR_MAP;
OUTPUT_MAP(TensorArrayWrite) = {{0, OUTPUT_DESC(flow_out)}};
REG_ADPT_DESC(TensorArrayWrite, kNameTensorArrayWrite, ADPT_DESC(TensorArrayWrite))
INPUT_MAP(TensorArrayGather) = {{1, INPUT_DESC(handle)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(flow_in)}};
//输入映射handle索引为1indices索引为2flow_in索引为3
ATTR_MAP(TensorArrayGather) = {{"dtype", ATTR_DESC(dtype, AnyTraits<GEType>())},
{"element_shape", ATTR_DESC(element_shape, AnyTraits<std::vector<int64_t>>())}};
//属性映射属性dtype类型为GEType属性element_shape类型为int64_t
OUTPUT_MAP(TensorArrayGather) = {{0, OUTPUT_DESC(value)}};
//输出映射value索引为0
REG_ADPT_DESC(TensorArrayGather, kNameTensorArrayGather, ADPT_DESC(TensorArrayGather))
//注册TensorArrayGather操作的适配器描述KNameTensorArrayGather
} // namespace mindspore::transform

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,116 @@
# Copyright 2019-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.
# ==============================================================================
"""
Define the data types.
定义数据类型
"""
import numpy as np
import mindspore._c_dataengine as cde
from mindspore._c_expression import typing
import mindspore.common.dtype as mstype
def nptype_to_detype(type_):
"""
Get de data type corresponding to numpy dtype.
获取numpy dtype对应的de数据类型
Args:
type_ (numpy.dtype): Numpy's dtype.
Returns:
The data type of de.
"""
# 如果传入的 'type_' 不是 NumPy 数据类型对象np.dtype则将其转换为 np.dtype 对象
if not isinstance(type_, np.dtype):
type_ = np.dtype(type_)
# 创建一个字典,将 NumPy 数据类型映射到 CDEMindSpore 数据增强库)的数据类型
# 这个字典用于将 NumPy 数据类型转换为 CDE 数据类型
return {
np.dtype("bool"): cde.DataType("bool"),
np.dtype("int8"): cde.DataType("int8"),
np.dtype("int16"): cde.DataType("int16"),
np.dtype("int32"): cde.DataType("int32"),
np.dtype("int64"): cde.DataType("int64"),
np.dtype("uint8"): cde.DataType("uint8"),
np.dtype("uint16"): cde.DataType("uint16"),
np.dtype("uint32"): cde.DataType("uint32"),
np.dtype("uint64"): cde.DataType("uint64"),
np.dtype("float16"): cde.DataType("float16"),
np.dtype("float32"): cde.DataType("float32"),
np.dtype("float64"): cde.DataType("float64"),
np.dtype("str"): cde.DataType("string"),
}.get(type_)
def mstype_to_detype(type_):
"""
Get de data type corresponding to mindspore dtype.
获取mindspore数据类型对应的de数据类型
Args:
type_ (mindspore.dtype): MindSpore's dtype.
Returns:
The data type of de.
"""
# 如果传入的 'type_' 不是 NumPy 数据类型对象np.dtype则将其转换为 np.dtype 对象
if not isinstance(type_, np.dtype):
type_ = np.dtype(type_)
# 创建一个字典,将 NumPy 数据类型映射到 CDEMindSpore 数据增强库)的数据类型
# 这个字典用于将 NumPy 数据类型转换为 CDE 数据类型
return {
np.dtype("bool"): cde.DataType("bool"),
np.dtype("int8"): cde.DataType("int8"),
np.dtype("int16"): cde.DataType("int16"),
np.dtype("int32"): cde.DataType("int32"),
np.dtype("int64"): cde.DataType("int64"),
np.dtype("uint8"): cde.DataType("uint8"),
np.dtype("uint16"): cde.DataType("uint16"),
np.dtype("uint32"): cde.DataType("uint32"),
np.dtype("uint64"): cde.DataType("uint64"),
np.dtype("float16"): cde.DataType("float16"),
np.dtype("float32"): cde.DataType("float32"),
np.dtype("float64"): cde.DataType("float64"),
np.dtype("str"): cde.DataType("string"),
}.get(type_)
def mstypelist_to_detypelist(type_list):
"""
Get list[de type] corresponding to list[mindspore.dtype].
获取列表[mindspore.dtype]对应的列表[detype]
Args:
type_list (list[mindspore.dtype]): a list of MindSpore's dtype.
Returns:
The list of de data type.
"""
# 遍历传入的 type_list 列表
for index, _ in enumerate(type_list):
# 如果列表中的元素不为 None
if type_list[index] is not None:
# 调用 mstype_to_detype 函数将 MindSpore 数据类型转换为 CDE 数据类型
type_list[index] = mstype_to_detype(type_list[index])
else:
# 如果列表中的元素为 None则将其设置为空字符串的 CDE 数据类型
type_list[index] = cde.DataType("")
# 返回转换后的 type_list 列表
return type_list

View File

@ -0,0 +1,245 @@
/**
* 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 "include/transform/graph_ir/df_graph_manager.h"
#include <sstream>
#ifndef ENABLE_LITE_ACL
#include "include/common/utils/python_adapter.h"
#include "pipeline/jit/pipeline.h"
#endif
#ifndef NO_DLIB
#include "tdt/tsd_client.h"
#endif
namespace mindspore {
namespace transform {
// 此构造函数用于初始化 DfGraphWrapper 类的一个新实例。
// 它接受四个参数:'name'、'id'、'graph_ptr' 和 'options'
DfGraphWrapper::DfGraphWrapper(const std::string &name, const int &id, const DfGraphPtr &graph_ptr,
const OptionMap &options)
: name_(name), id_(id), graph_ptr_(graph_ptr), options_(options) {}
DfGraphManager::DfGraphManager() { //构造函数
graph_id_ = 0;
graph_runner_ptr_ = nullptr;
sess_ptr_ = nullptr;
}
DfGraphManager::~DfGraphManager() { //析构函数
// in python first destroy after atexit but in c++ destoy before atexit
DeleteGraphRunner();
DeleteGeSession();
ClearGraph();
#ifndef ENABLE_LITE_ACL
python_adapter::set_python_env_flag(false);
#endif
}
DfGraphManager &DfGraphManager::GetInstance() {
static DfGraphManager instance;
return instance;
}
// 该函数用于生成图形ID。
int DfGraphManager::GenerateId() {
graph_id_++; // 递增图形ID
if (graph_id_ <= 0) { // 如果图形ID小于等于0则将其设置为1确保ID不为负数
graph_id_ = 1;
}
MS_LOG(INFO) << "Generate graph Id : " << graph_id_; // 打印生成的图形ID仅用于日志记录
return graph_id_; // 返回生成的图形ID
}
// 该函数用于向图形管理器中添加一个图形。
// 参数 'name' 表示图形的名称,'graph_ptr' 表示图形的指针,'options' 表示图形的选项。
Status DfGraphManager::AddGraph(const std::string &name, const DfGraphPtr &graph_ptr, const OptionMap &options) {
std::lock_guard<std::mutex> lg(lock_); // 使用互斥锁,确保添加图形的操作是线程安全的
if (name.empty()) { // 如果图形名称为空,返回无效参数错误
MS_LOG(ERROR) << "The graph name is null, add graph failed";
return Status::INVALID_ARGUMENT;
}
if (graph_ptr == nullptr) { // 如果图形指针为空,返回无效参数错误
MS_LOG(INFO) << "The new graph {" << name << "}'s pointer is null, add graph failed";
return Status::INVALID_ARGUMENT;
}
int id = GenerateId(); // 生成一个新的图形ID
// 创建一个 DfGraphWrapperPtr 对象,用于包装图形信息,并将图形添加到图形管理器中
DfGraphWrapperPtr wrap_ptr = std::make_shared<DfGraphWrapper>(name, id, graph_ptr, options);
// 将图形添加到图形管理器中
auto ret = graphs_.emplace(name, wrap_ptr);
if (ret.second == false) { // 如果图形名称已经存在,将旧的图形覆盖
MS_LOG(WARNING) << "The graph name:{ " << name << " }is already exists! The old graph will be overwritten!!";
ret.first->second = wrap_ptr;
}
MS_LOG(INFO) << "Add graph " << name << " to GraphManager success!"; // 成功添加图形后记录日志
return Status::SUCCESS; // 返回成功状态
}
// 该函数用于获取图形管理器中的所有图形,并以一个 DfGraphWrapperPtr 类型的向量返回这些图形。
std::vector<DfGraphWrapperPtr> DfGraphManager::GetAllGraphs() {
std::lock_guard<std::mutex> lg(lock_); // 使用互斥锁,确保获取图形的操作是线程安全的
std::vector<DfGraphWrapperPtr> ret; // 创建用于存储图形的向量
std::stringstream ss;
ss << "{ ";
for (auto it = graphs_.begin(); it != graphs_.end(); ++it) { // 遍历图形管理器中的所有图形
ss << it->first << ", "; // 将图形名称添加到日志记录字符串中
ret.emplace_back(it->second); // 将图形指针添加到返回向量中
}
ss << "}";
MS_LOG(INFO) << "Return graphs: " << ss.str(); // 记录获取的图形名称到日志
return ret; // 返回存储所有图形的向量
}
// 该函数用于获取已保存的图形名称集合。
// 返回类型为 std::set<string>,表示一个存储唯一图形名称的集合。
std::set<string> DfGraphManager::GetSavedGraphs() { return saved_graphs_; } // 直接返回保存的图形名称集合
// 该函数用于向已保存的图形名称集合中添加新的图形名称。
// 参数 'id' 表示要添加的图形名称。
void DfGraphManager::AddSavedGraphs(const std::string &id) { saved_graphs_.insert(id); } // 将新的图形名称 'id' 插入已保存的图形名称集合中
// 该函数用于根据图形名称获取对应的 DfGraphWrapperPtr 对象。
// 参数 'name' 表示要获取的图形名称。
DfGraphWrapperPtr DfGraphManager::GetGraphByName(const std::string &name) {
std::lock_guard<std::mutex> lg(lock_); // 使用互斥锁,确保获取图形的操作是线程安全的
if (name.empty()) {
MS_LOG(ERROR) << "The graph name is null";
return nullptr; // 如果图形名称为空,返回空指针
}
auto it = graphs_.find(name);
if (it == graphs_.end()) {
MS_LOG(INFO) << "Can't found graph name: " << name;
return nullptr; // 如果图形名称在图形管理器中找不到,返回空指针
}
MS_LOG(INFO) << "Return graph: " << name; // 记录获取的图形名称到日志
return it->second; // 返回找到的图形的 DfGraphWrapperPtr 对象
}
// 该函数用于清空图形管理器中的所有图形,并释放相关资源。
void DfGraphManager::ClearGraph() noexcept {
std::lock_guard<std::mutex> lg(lock_); // 使用互斥锁,确保清空图形的操作是线程安全的
graphs_.clear(); // 清空图形管理器中的所有图形
anf_graphs_.clear(); // 清空图形管理器中的所有 ANF 图形(可能是另一种图形表示)
MS_LOG(INFO) << "Remove all graphs in GraphManager"; // 记录已清空所有图形的日志
}
// 该函数用于将给定的 ANF 图形指针与特定的图形名称相关联。
// 参数 'name' 表示图形的名称,'anf_graph_ptr' 表示要关联的 ANF 图形指针。
void DfGraphManager::SetAnfGraph(const std::string &name, const AnfGraphPtr &anf_graph_ptr) {
DfGraphWrapperPtr df_graph = GetGraphByName(name); // 获取给定名称的图形包装器对象
if (df_graph == nullptr) {
MS_LOG(ERROR) << "Can't found graph name: " << name;
return; // 如果找不到给定名称的图形,则返回错误并退出函数
}
std::lock_guard<std::mutex> lg(lock_); // 使用互斥锁,确保设置 ANF 图形的操作是线程安全的
anf_graphs_[df_graph->id_] = anf_graph_ptr; // 将给定的 ANF 图形指针与图形包装器的 ID 相关联,并存储在 anf_graphs_ 容器中
}
// 该函数用于根据给定的图形 ID 获取对应的 ANF 图形指针。
// 参数 'graph_id' 表示要获取的图形 ID。
AnfGraphPtr DfGraphManager::GetAnfGraph(uint32_t graph_id) {
std::lock_guard<std::mutex> lg(lock_); // 使用互斥锁,确保获取 ANF 图形的操作是线程安全的
auto iter = anf_graphs_.find(graph_id);
if (iter == anf_graphs_.end()) {
MS_LOG(ERROR) << "Can't found anf graph, graph_id = " << graph_id;
return nullptr; // 如果找不到给定图形 ID 对应的 ANF 图形,则记录错误日志并返回空指针
}
return iter->second; // 返回找到的图形 ID 对应的 ANF 图形指针
}
// 该函数用于清空 ANF 图形容器,即移除所有已关联的 ANF 图形。
void DfGraphManager::EraseAnfGraph() {
std::lock_guard<std::mutex> lg(lock_); // 使用互斥锁,确保清空 ANF 图形容器的操作是线程安全的
anf_graphs_.clear(); // 清空 ANF 图形容器,移除所有已关联的 ANF 图形
}
// 该函数用于设置与图形管理器关联的 GEGraphEngine会话指针。
// 参数 'sess_ptr' 表示要设置的 GE 会话指针。
void DfGraphManager::SetGeSession(const std::shared_ptr<ge::Session> &sess_ptr) {
std::lock_guard<std::mutex> lg(lock_); // 使用互斥锁,确保设置 GE 会话的操作是线程安全的
if (sess_ptr == nullptr) {
MS_LOG(WARNING) << "You are adding a empty Ge Session"; // 如果传入的 GE 会话指针为空,记录警告日志
}
if (sess_ptr_ == nullptr) {
MS_LOG(INFO) << "Add a new Ge Session success"; // 如果之前未设置过 GE 会话,记录设置成功的日志
} else { // 如果之前已经设置过 GE 会话,记录设置成功的日志,并提示之前的 GE 会话将被覆盖
MS_LOG(INFO) << "Add a new Ge Session success, the old Ge Session will be overwritten!!";
}
sess_ptr_ = sess_ptr; // 将传入的 GE 会话指针设置为图形管理器关联的 GE 会话指针
}
// 该函数用于获取图形管理器关联的 GEGraphEngine会话指针。
// 返回类型为 std::shared_ptr<ge::Session>,表示 GE 会话指针。
std::shared_ptr<ge::Session> DfGraphManager::GetGeSession() {
std::lock_guard<std::mutex> lg(lock_); // 使用互斥锁,确保获取 GE 会话指针的操作是线程安全的
return sess_ptr_; // 返回图形管理器关联的 GE 会话指针
}
// 该函数用于删除图形管理器关联的 GEGraphEngine会话并清除与该会话相关的数据。
void DfGraphManager::DeleteGeSession() noexcept {
std::lock_guard<std::mutex> lg(lock_); // 使用互斥锁,确保删除 GE 会话的操作是线程安全的
if (sess_ptr_ == nullptr) {
MS_LOG(INFO) << "Ge Session is not exist"; // 如果当前没有关联的 GE 会话,记录日志并直接返回
} else {
sess_ptr_ = nullptr; // 将关联的 GE 会话指针设置为空指针,表示删除 GE 会话
saved_graphs_.clear(); // 清空已保存的图形名称集合,即移除所有已保存的图形信息
MS_LOG(INFO) << "Delete Ge Session success"; // 记录删除成功的日志
}
}
// 该函数用于设置与图形管理器关联的图形运行器GraphRunner指针。
// 参数 'graph_runner_ptr' 表示要设置的图形运行器指针。
void DfGraphManager::SetGraphRunner(const std::shared_ptr<transform::GraphRunner> &graph_runner_ptr) noexcept {
std::lock_guard<std::mutex> lg(lock_); // 使用互斥锁,确保设置图形运行器的操作是线程安全的
if (graph_runner_ptr == nullptr) { // 如果传入的图形运行器指针为空,记录警告日志
MS_LOG(WARNING) << "You are adding a empty GraphRunner";
}
if (graph_runner_ptr_ == nullptr) { // 如果之前未设置过图形运行器,记录设置成功的日志
MS_LOG(INFO) << "Add a new GraphRunner success";
} else { // 如果之前已经设置过图形运行器,记录设置成功的日志,并提示之前的图形运行器将被覆盖
MS_LOG(INFO) << "Add a new GraphRunner success, the old GraphRunner will be overwritten!!";
}
graph_runner_ptr_ = graph_runner_ptr; // 将传入的图形运行器指针设置为图形管理器关联的图形运行器指针
}
// 该函数用于获取图形管理器关联的图形运行器GraphRunner指针。
// 返回类型为 std::shared_ptr<transform::GraphRunner>,表示图形运行器指针
std::shared_ptr<transform::GraphRunner> DfGraphManager::GetGraphRunner() {
std::lock_guard<std::mutex> lg(lock_); // 使用互斥锁,确保获取图形运行器指针的操作是线程安全的
return graph_runner_ptr_; // 返回图形管理器关联的图形运行器指针
}
// 该函数用于删除图形管理器关联的图形运行器GraphRunner
void DfGraphManager::DeleteGraphRunner() noexcept {
std::lock_guard<std::mutex> lg(lock_); // 使用互斥锁,确保删除图形运行器的操作是线程安全的
if (graph_runner_ptr_ == nullptr) {
MS_LOG(INFO) << "GraphRunner is not exist"; // 如果当前没有关联的图形运行器,记录日志并直接返回
} else {
graph_runner_ptr_ = nullptr; // 将关联的图形运行器指针设置为空指针,表示删除图形运行器
MS_LOG(INFO) << "Delete GraphRunner success"; // 记录删除成功的日志
}
}
} // namespace transform
} // namespace mindspore

View File

@ -0,0 +1,331 @@
# Copyright 2021 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.
# ============================================================================
"""dim_reduce"""
import math
import numpy as np
from mindspore.nn.cell import Cell
from mindspore.ops import composite as C
from mindspore.ops import functional as F
from mindspore.ops import operations as P
from mindspore.common.tensor import Tensor
from mindspore.common.parameter import Parameter, ParameterTuple
from mindspore.common import dtype as mstype
__all__ = ["DimReduce"]
_scale_grad = C.MultitypeFuncGraph("_scale_grad")
@_scale_grad.register("Tensor", "Tensor")
def _scale_grad_process(scale, grad):
grad = F.cast(grad, mstype.float32)
grad = P.Div()(grad, scale)
return grad
_save_weight = C.MultitypeFuncGraph("_save_weight")
@_save_weight.register("Tensor", "Tensor")
def _save_weight_process(parameter, new_parameter):
return P.Assign()(parameter, new_parameter)
_pca_projection = C.MultitypeFuncGraph("_pca_projection")
@_pca_projection.register("Tensor", "Tensor")
def _pca_projection_process(pca_mat, grad):
grad_k = P.MatMul()(pca_mat, F.reshape(grad, (-1, 1)))
return grad_k
_pca_back_projection = C.MultitypeFuncGraph("_pca_back_projection")
@_pca_back_projection.register("Tensor", "Tensor", "Tensor")
#该函数用于PCA反投影
def _pca_back_projection_process(grad_k, pca_mat, grad):
grad_proj = P.MatMul()(F.transpose(pca_mat, (1, 0)), grad_k)
grad_proj_reshape = F.reshape(grad_proj, F.shape(grad))
return grad_proj_reshape
_update_grad_res_momentum = C.MultitypeFuncGraph("_update_grad_res_momentum")
@_update_grad_res_momentum.register("Float32", "Float32", "Tensor", "Tensor", "Tensor")
#该函数用于更新梯度残差动量
def _update_grad_res_momentum_process(gamma, alpha, grad_res_momentum, grad, grad_proj):
grad_res_momentum_new = gamma * grad_res_momentum + grad - grad_proj
P.Assign()(grad_res_momentum, grad_res_momentum_new)
res = alpha * grad_res_momentum_new
return res
_get_delta_weight = C.MultitypeFuncGraph("_get_delta_weight")
@_get_delta_weight.register("Tensor", "Tensor", "Tensor")
def _get_delta_weight_process(rho, dn, grad_res_momentum):
delta_weight = grad_res_momentum - rho * dn
return delta_weight
class DimReduce(Cell):
r"""
The dimension reduce training, is a novel algorithm for accelerating convergence of Deep Learning models.
.. math::
\begin{align}
grad\_k &= pca\_mat \cdot grad\\
dk &= - bk \cdot grad\_k\\
sk &= rho ^ m \cdot dk\\
delta\_loss &= sigma \cdot grad\_k.T \cdot sk
\end{align}
Here:
- pca_mat (array): Shape (k*n), k is part of n_components, n is the size of weight.
- bk (array): Shape (k*k), is the symmetric positive definite matrix in Quasi-Newton method.
we need to find the m satisfy:
.. math::
new\_loss < old\_loss + delta\_loss
Then, get delta_grad to update the weights for model:
.. math::
\begin{align}
grad\_k\_proj &= pca\_mat.T \cdot grad\_k\\
new\_grad\_momentum &= gamma \cdot old\_grad\_momentum + grad - grad\_k\_proj\\
delta\_grad &= alpha \cdot new\_grad\_momentum - pca\_mat.T \cdot sk
\end{align}
Args:
network (Cell): The training network. The network only supports single output.
optimizer (Union[Cell]): Optimizer for updating the weights.
weight (Tuple(Parameter)): Tuple of parameters.
pca_mat_local (numpy.ndarray): For PCA operation, k*n, k is part of n_components, n is the size of weight.
n_components (int): PCA.components.
rho (float): Coefficient.
gamma (float): Coefficient.
alpha (float): Coefficient.
sigma (float): Coefficient.
rank (int): Rank number.
rank_size (int): Rank size.
Inputs:
- **loss** (Tensor) - Tensor with shape :math:`()`.
- **old_grad** (Tuple(Tensor)) - Tuple of gradient tensors.
- **weight** (Tuple(Tensor)) - Tuple of parameters.
- **weight_clone** (Tuple(Tensor)) - clone of weight
- **(\*inputs)** (Tuple(Tensor)) - Tuple of input tensors with shape :math:`(N, \ldots)`.
Outputs:
- **loss** (Tensor) - Tensor with shape :math:`()`.
"""
def __init__(self, network, optimizer, weight, pca_mat_local, n_components, rho, gamma, alpha, sigma, rank,
rank_size):
super(DimReduce, self).__init__()
self.network = network
self.optimizer = optimizer
self.rank = rank
self.rank_size = rank_size
self.gamma = gamma
self.alpha = alpha
self.sigma = sigma
self.float_type = mstype.float32
self._set_rho_list(rho)
self._set_local_pca_mat(pca_mat_local, n_components, weight)
self._set_init_parameter(weight)
self.hyper_map = C.HyperMap()
self.concat = P.Concat()
self.matmul = P.MatMul()
self.mul = P.Mul()
self.add = P.Add()
#该函数是为了设置rhoρ值列表以便在优化算法中使用。
def _set_rho_list(self, rho):
"""set rho list info."""
self.max_search_time = 2 # 最大搜索次数
self.rho_list = []
for i in range(self.max_search_time):
self.rho_list.append(Tensor(np.power(rho, i), dtype=self.float_type))
self.rho_list.append(Tensor(0, dtype=self.float_type))
#该函数用于设置本地PCA矩阵信息
def _set_local_pca_mat(self, pca_mat_local, n_components, parameter_tuple):
"""set pca info."""
self.n_components = n_components
local_dim = math.ceil(self.n_components / self.rank_size)
self.start_index = self.rank * local_dim
self.end_index = (self.rank + 1) * local_dim
start = 0
self.pca_list_local = ()
# 遍历模型参数将本地PCA矩阵按参数大小分块并存储在pca_list_local中
for param in parameter_tuple:
size = np.shape(param.asnumpy().reshape((-1, 1)))[0]
self.pca_list_local += (Tensor(pca_mat_local[:, start:start + size], dtype=self.float_type),)
start += size
self.dk_pad_flag = False
pad_num = self.rank_size * local_dim - self.n_components
if pad_num: # 如果需要进行填充则设置dk_pad_flag为True并创建填充部分
self.dk_pad_flag = True
self.dk_pad_part = Tensor(np.zeros([pad_num, 1]), dtype=self.float_type)
if self.rank_size > 1:
self.broadcast_list = []
for i in range(self.rank_size): # 创建广播列表,用于跨设备通信
broadcast = P.Broadcast(i)
self.broadcast_list.append(broadcast)
self.allreduce = P.AllReduce() # 用于执行全局归约操作
self.allgather = P.AllGather() # 用于执行全局收集操作
def _set_init_parameter(self, parameter_tuple):
"""init parameters."""
self.true_flag = Tensor(True)
self.false_flag = Tensor(False)
self.epsilon = np.power(10.0, -20)
# 初始化gk_last参数
self.gk_last = Parameter(Tensor(np.zeros([self.n_components, 1]), dtype=self.float_type), name="gk_last")
self.gk_last_init = Parameter(Tensor(False), name="gk_last_init")
# 初始化bk和sk参数
self.bk = Parameter(Tensor(np.eye(self.n_components), dtype=self.float_type), name="bk")
self.sk = Parameter(Tensor(np.zeros([self.n_components, 1]), dtype=self.float_type), name="sk")
self.eye = Tensor(np.eye(self.n_components), dtype=self.float_type)
# 初始化grad_res_momentum参数
self.grad_res_momentum = ParameterTuple(parameter_tuple).clone(prefix="grad_res_momentum", init="zeros")
# 初始化gk_last_back和bk_back参数
self.gk_last_back = Parameter(Tensor(np.zeros([self.n_components, 1]), dtype=self.float_type),
name="gk_last_back")
self.bk_back = Parameter(Tensor(np.eye(self.n_components), dtype=self.float_type), name="bk_back")
# 初始化grad_proj_init和dn_init参数
self.grad_proj_init = ParameterTuple(parameter_tuple).clone(prefix="grad_proj_init", init="zeros")
self.dn_init = ParameterTuple(parameter_tuple).clone(prefix="dn_init", init="zeros")
def construct(self, loss, old_grad, loss_scale, weight, weight_clone, *inputs):
# 更新权重和梯度
weight = F.depend(weight, loss)
old_grad = F.depend(old_grad, weight)
old_grad = self.hyper_map(F.partial(_scale_grad, loss_scale), old_grad)
old_loss = self.allreduce(loss) / self.rank_size if self.rank_size > 1 else loss
# 计算gk_local
gk_local = self.hyper_map(_pca_projection, self.pca_list_local, old_grad)
gk_local = F.addn(gk_local)
gk_pad = self.allgather(gk_local) if self.rank_size > 1 else gk_local
gk_pad = F.reshape(gk_pad, (-1, 1))
gk = gk_pad[0:self.n_components, :]
# 保存权重和梯度
_save_weight(self.gk_last_back, self.gk_last)
_save_weight(self.bk_back, self.bk)
# 计算dk
dk = self._apply_quasi_newton_update(gk)
if self.dk_pad_flag:
dk_pad = self.concat((dk, self.dk_pad_part))
else:
dk_pad = dk
dk_local = dk_pad[self.start_index: self.end_index, :]
# 计算dn_local和grad_proj_local
dn_local = self.hyper_map(F.partial(_pca_back_projection, dk_local), self.pca_list_local, old_grad)
grad_proj_local = self.hyper_map(F.partial(_pca_back_projection, gk_local), self.pca_list_local, old_grad)
dn = self.dn_init if self.rank_size > 1 else dn_local
grad_proj = self.grad_proj_init if self.rank_size > 1 else grad_proj_local
if self.rank_size > 1:
for broadcast in self.broadcast_list:
dn_part = broadcast(dn_local)
dn = self.hyper_map(self.add, dn, dn_part)
grad_proj_part = broadcast(grad_proj_local)
grad_proj = self.hyper_map(self.add, grad_proj, grad_proj_part)
# 使用线搜索更新rho值
rho, find = self._line_search(gk, dk, dn, old_loss, weight, weight_clone, *inputs)
if not find:
_save_weight(self.gk_last, self.gk_last_back)
_save_weight(self.bk, self.bk_back)
# 更新梯度并执行优化步骤
update_grad = self.hyper_map(F.partial(_update_grad_res_momentum, self.gamma, self.alpha),
self.grad_res_momentum, old_grad, grad_proj)
delta_weight = self.hyper_map(F.partial(_get_delta_weight, rho), dn, update_grad)
update = self.optimizer(delta_weight)
weight = F.depend(weight, update)
clone = self.hyper_map(_save_weight, weight_clone, weight)
loss = F.depend(loss, clone)
return loss
#该函数用于线搜索,寻找最佳的 rho 值,以确保模型参数的更新不引起损失函数增加。
def _line_search(self, gk, dk, dn, old_loss, weight, weight_clone, *inputs):
"""line search rho."""
res = self.rho_list[-1] # 初始化rho为最小值
find = self.false_flag # 初始化find标志为False
for i in range(self.max_search_time): # 遍历rho候选列表尝试不同的rho值
find = self._find_rho(gk, dk, dn, old_loss, weight, weight_clone, self.rho_list[i], *inputs)
if find: # 如果找到了满足条件的rho值更新res并跳出循环
res = self.rho_list[i]
break
return res, find
#该函数用于查找最佳 rho 值的方法,以确保模型参数的更新不会导致损失函数增加。
def _find_rho(self, gk, dk, dn, old_loss, weight, weight_clone, rho, *inputs):
"""search rho."""
res = self.false_flag # 初始化res标志为False
# 计算sn即损失函数对应于rho值的更新
sn = self.hyper_map(F.partial(self.mul, -1 * rho), dn)
sn = F.depend(sn, old_loss)
update = self.optimizer(sn)
# 计算使用rho值更新后的损失函数
new_loss = F.depend(self.network(*inputs), update)
# 如果是分布式训练,对损失函数进行全局平均
if self.rank_size > 1:
new_loss = self.allreduce(new_loss) / self.rank_size
# 计算损失函数的变化
old_loss_delta = old_loss + self.sigma * rho * F.squeeze(self.matmul(F.transpose(gk, (1, 0)), dk))
# 如果使用rho值更新后的损失函数小于旧的损失函数表示找到了一个满足条件的rho值
if old_loss_delta > new_loss:
_save_weight(self.sk, rho * dk)
res = self.true_flag
# 更新weight_clone和weight的值
weight_clone = F.depend(weight_clone, old_loss_delta)
restore = self.hyper_map(_save_weight, weight, weight_clone)
res = F.depend(res, restore)
return res
#该函数用于应用拟牛顿更新。
def _apply_quasi_newton_update(self, gk):
"""apply quasi_newton update."""
if self.gk_last_init:
yk = gk - self.gk_last # 计算gk和上一次迭代的gk的差值
g = self.matmul(F.transpose(yk, (1, 0)), self.sk)
g = F.squeeze(g)
if g > self.epsilon:
pk = 1. / g
t1 = self.eye - self.matmul(pk * yk, F.transpose(self.sk, (1, 0)))
new_bk = self.matmul(self.matmul(F.transpose(t1, (1, 0)), self.bk), t1) + \
self.matmul(pk * self.sk, F.transpose(self.sk, (1, 0)))
_save_weight(self.bk, new_bk) # 更新拟牛顿矩阵bk
else:
_save_weight(self.gk_last_init, self.true_flag) # 第一次迭代时初始化gk_last_init
_save_weight(self.gk_last, gk) # 保存当前迭代的gk值
dk = -1 * self.matmul(self.bk, gk) # 计算拟牛顿更新后的dk值
return dk

View File

@ -0,0 +1,164 @@
# 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.
# ============================================================================
"""Ast optimizer for flatten recursive call."""
from typing import Any, Tuple
import ast
from ast import FunctionDef
from mindspore import log as logger
class FlattenRecursiveStmt(ast.NodeTransformer):
"""Ast optimizer for flatten recursive call."""
def __init__(self):
"""
Constructor of FlattenRecursiveStmt.
Returns:
An instance of ast optimizer for flatten recursive call.
"""
self._flatten_table: dict = {
ast.Return: ["value"],
ast.Call: ["args"],
ast.BinOp: ["left", "right"],
ast.BoolOp: ["values"],
ast.unaryop: ["operand"],
}
@staticmethod
def _generate_target_name(node: ast.AST, target_names):
"""Generate unique target name."""
if isinstance(node, ast.Call): #如果节点是ast.Call类型,它将检查节点的属性(表示函数调用的目标)的类型
func = node.func #如果是func类型则使用其属性作为目标名称
if isinstance(func, ast.Name): #如果是ast.Name类型则将使用其属性id作为目标名称
target_name = func.id
elif isinstance(func, ast.Attribute): #如果是ast.Attribute类型则使用其属性attr作为目标名称
target_name = func.attr
else: #如果不是这两种类型,则会记录一个警告,并将目标名称设置为"function"
logger.warning("unhandled type of func of ast.Call while generating new target name: %s ", type(func))
target_name = "function"
elif isinstance(node, ast.Return): #如果节点是ast.Return类型则将目标名称设置为"return_value"。
target_name = "return_value"
elif isinstance(node, (ast.BinOp, ast.boolop, ast.UnaryOp)): #如果节点是ast.BinOpast、ast.boolop或ast.UnaryOp类型它将使用相应操作符的类型名称作为目标名称。
target_name = type(node.op).__name__
else: #对于其他类型的节点,记录一个警告,并将目标名称设置为该节点的类型名称
logger.warning("unhandled type of node while generating new target name: %s ", type(node))
target_name = type(node).__name__
suffix = 0
result = target_name
while result in target_names: #在生成的目标名称上添加数字后缀,以确保它在目标名称列表中是唯一的
suffix += 1
result = f"{target_name}_{suffix}"
target_names.append(result)
return result #返回生成的目标名称并将其添加到列表中
@staticmethod
def _fill_in_original_target_names(target_names, node):
"""Fill in original target names before getting unique names."""
for function_index in range(len(node.body)): #遍历ASTAbstract Syntax Tree节点的node.body
child = node.body[function_index]
if not isinstance(child, ast.Assign): #在每个节点中,检查是否是一个赋值语句(ast.Assign)
continue #如果不是,继续处理下一个节点。
targets = child.targets #如果节点是赋值语句,则获取赋值语句的目标(targets)。
for target in targets: #如果目标是ast.Name类型则获取变量名(target.id)并检查该名称是否已经存在于target_names列表中。
if not isinstance(target, ast.Name):
raise RuntimeError("currently only support ast.Name targets")
target_name = target.id
if target_name not in target_names: #如果变量名不在target_names列表中就将其添加进去
target_names.append(target_name)
@staticmethod
# 检查node是否是以下类型之一ast.Name, ast.Constant, ast.Num, ast.Str, ast.NameConstant, ast.Bytes, ast.Ellipsis
# 如果是就直接返回一个空字符串和原始node因为这些节点是不需要生成新赋值节点的。
def _create_new_assign_node(node: ast.AST, target_names) -> Tuple[str, ast.AST]:
"""Create new assign node to be inserted into ast.FunctionDef."""
if isinstance(node, (ast.Name, ast.Constant, ast.Num, ast.Str, ast.NameConstant, ast.Bytes, ast.Ellipsis)):
return "", node
#对于其他类型的节点调用FlattenRecursiveStmt._generate_target_name函数来生成一个新的目标名称。
new_target_name = FlattenRecursiveStmt._generate_target_name(node, target_names)
return new_target_name, ast.Assign(targets=[ast.Name(id=new_target_name, ctx=ast.Store())], value=node) #创建一个新的赋值节点ast. Assign.node作为赋值的值(value)。 返回这个新的目标名称和创建的赋值节点
def _flatten_statement(self, node: ast.AST, target_names) -> [ast.AST]:
"""Flatten recursive statement according to different node type."""
flatten_config = self._flatten_table.get(type(node)) #通过查找_flatten_table字典获取node类型对应的展开配置flatten_config。如果没有找到对应的配置它将返回一个空列表
if flatten_config is None:
return []
results = []
for todo_name in flatten_config:
todos = getattr(node, todo_name) #遍历展开配置中的每个待展开项(todo_name)
#对于列表类型的属性遍历列表中的每个元素调用FlattenRecursiveStmt._create_new_assign_node函数来生成一个新的赋值节点并将生成的新目标名称替换原始元素的位置。
#如果生成的新节点与原始节点相同,则保留原始节点。 否则,将新节点添加到结果列表中。
if isinstance(todos, list):
new_list = []
for todo in todos:
new_target_name, new_node = FlattenRecursiveStmt._create_new_assign_node(todo, target_names)
if id(new_node) == id(todo):
new_list.append(todo)
else:
new_list.append(ast.Name(id=new_target_name, ctx=ast.Load()))
results.append(new_node)
setattr(node, todo_name, new_list)
#对于字典类型的属性它会遍历字典中的每个键值对调用FlattenRecursiveStmt._create_new_assign_node函数来生成新的赋值节点并将生成的新目标名称替换原始值的位置。
#同样,如果生成的新节点与原始节点相同,则保留原始节点。 否则,将新节点添加到结果列表中。
elif isinstance(todos, dict):
new_dict = []
for key, value in todos:
new_target_name, new_node = FlattenRecursiveStmt._create_new_assign_node(value, target_names)
if id(new_node) == id(value):
new_dict[key] = value
else:
new_dict[key] = ast.Name(id=new_target_name, ctx=ast.Load())
results.append(new_node)
setattr(node, todo_name, new_dict)
else:
new_target_name, new_node = FlattenRecursiveStmt._create_new_assign_node(todos, target_names)
if id(new_node) != id(todos):
setattr(node, todo_name, ast.Name(id=new_target_name, ctx=ast.Load()))
results.append(new_node)
return results #函数返回结果列表,其中包含所有生成的新赋值节点
#检查node的名称是否为"construct",如果不是直接返回原始node
def visit_FunctionDef(self, node: FunctionDef) -> Any:
"""Traverse construct node and flatten recursive nodes."""
if node.name != "construct":
return node
target_names = [] #创建一个空的target_names列表并调用_fill_in_original_target_names函数来填充原始目标名称
self._fill_in_original_target_names(target_names, node)
index = len(node.body) - 1 #从函数体的最后一个语句开始向前遍历每个语句由node.body列表表示
while index >= 0:
child = node.body[index] #对于每个语句函数检查是否是一个赋值语句ast.Assign或者是一个表达式语句ast.Expr
if isinstance(child, ast.Assign):
stmt = child.value #如果是赋值语句,获取赋值语句的值
elif isinstance(child, ast.Expr):
stmt = child.value #如果是表达式语句,获取表达式的值
else:
stmt = child #否则,将语句本身作为要处理的节点
results = self._flatten_statement(stmt, target_names) #调用_flatten_statement函数来展开语句中的递归节点并传递target_names列表。 该函数将返回一个包含生成的新赋值节点的列表。
#如果_flatten_statement返回了结果函数将这些结果逆序遍历并将每个新节点插入到原始节点的前面以确保展开的赋值节点按正确的顺序插入。
if results:
results.reverse()
for result in results:
node.body.insert(index, result)
index += 1
index -= 1
return node
def transform(self, ast_root): #这是FlattenRecursiveStmt类的transform方法它是FlattenRecursiveStmt的接口方法。
#这个方法接受一个ASTAbstract Syntax Tree的根节点ast_root作为输入并返回经过展开递归节点处理后的AST根节点。
"""Interface of FlattenRecursiveStmt."""
ast_root = self.visit(ast_root) #调用self.visit(ast_root)这是一个递归的AST遍历过程它会调用visit_FunctionDef等方法来处理AST中的各种节点。
ast_root = ast.fix_missing_locations(ast_root) #使用ast.fix_missing_locations(ast_root)来修复AST节点中缺失的位置信息。 在处理AST时可能会对节点进行插入、删除等操作导致节点的位置信息丢失。ast.fix_missing_locations会遍历AST并为缺失位置的节点添加默认的位置信息。
return ast_root #返回经过展开递归节点处理和位置修复后的AST根节点

View File

@ -0,0 +1,45 @@
/**
* 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_declare/functional_ops_declare.h"
namespace mindspore::transform {
// Case
INPUT_MAP(Case) = {{1, INPUT_DESC(branch_index)}};
//输入映射branch_index索引为1
DYN_INPUT_MAP(Case) = {{2, DYN_INPUT_DESC(input)}};
//动态输入映射将索引为2的动态输入与名称为input的动态输入描述关联起来用于后续操作
ATTR_MAP(Case) = EMPTY_ATTR_MAP;
//属性映射,设为空
DYN_OUTPUT_MAP(Case) = {{0, DYN_OUTPUT_DESC(output)}};
//动态输出映射将索引为0的动态输出与名称为output的动态输出描述关联起来用于后续操作
DYN_SUBGRAPH_MAP(Case) = {{0, DYN_SUBGRAPH_DESC(branches)}};
//动态子图映射将索引为0的动态子图与名称为branches的动态描述关联起来用于后续操作
REG_ADPT_DESC(Case, kNameCase, ADPT_DESC(Case));
//注册Case操作的适配器描述kNameCase
// While
DYN_INPUT_MAP(While) = {{1, DYN_INPUT_DESC(input)}};
//输入映射input索引为1
ATTR_MAP(While) = {{"parallel_iterations", ATTR_DESC(parallel_iterations, AnyTraits<int32_t>())}};
//属性映射属性parallel_iterations类型为int32_t
DYN_OUTPUT_MAP(While) = {{0, DYN_OUTPUT_DESC(output)}};
//动态输出映射将索引为0的动态输出与名称为output的动态输出描述关联起来用于后续操作
SUBGRAPH_MAP(While) = {{0, SUBGRAPH_DESC(cond)}, {1, SUBGRAPH_DESC(body)}};
//动态子图映射将索引为0的动态子图与名称为cond的动态描述关联将索引为1的动态子图与名称为body的动态描述关联用于后续操作
REG_ADPT_DESC(While, kNameWhile, ADPT_DESC(While));
//注册While操作的适配器描述kNameWhile
} // namespace mindspore::transform

View File

@ -0,0 +1,82 @@
# Copyright 2021 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.
# ============================================================================
"""grad accumulation"""
from mindspore.nn.cell import Cell
from mindspore.common import Parameter, Tensor
from mindspore.common import dtype as mstype
from mindspore.ops import composite as C
from mindspore.ops import functional as F
from mindspore.ops import operations as P
__all__ = ["GradientAccumulation", "gradient_accumulation_op", "gradient_clear_op"]
# 创建梯度积累操作
gradient_accumulation_op = C.MultitypeFuncGraph("gradient_accumulation_op")
# 注册梯度积累操作的计算图,输入参数是积累步数(整数),累积的梯度张量,以及当前步的梯度张量
@gradient_accumulation_op.register("Int64", "Tensor", "Tensor")
def cumulative_grad_process(accumulation_step, cumulative_grad, grad):
"""Apply gradient accumulation to cumulative grad."""
# 将当前步的梯度张量除以积累步数,并加到累积梯度上
return P.AssignAdd()(cumulative_grad, grad / accumulation_step)
# 创建梯度清零操作
gradient_clear_op = C.MultitypeFuncGraph("gradient_clear_op")
# 注册梯度清零操作的计算图,输入参数是累积的梯度张量
@gradient_clear_op.register("Tensor")
def clear_grad(cumulative_grad):
# 创建一个和累积梯度形状一样的全零张量,并将其赋值给累积梯度,实现梯度清零
zero_grad = P.ZerosLike()(cumulative_grad)
return F.assign(cumulative_grad, zero_grad)
# 定义梯度积累类
class GradientAccumulation(Cell):
"""
After accumulating the gradients of multiple steps, call to optimize its update.
Args:
max_accumulation_step (int): Steps to accumulate gradients.
optimizer (Cell): Optimizer used.
"""
def __init__(self, max_accumulation_step, optimizer):
super(GradientAccumulation, self).__init__()
self._max_accumulation_step = max_accumulation_step
self.optimizer = optimizer
self.weights = optimizer.parameters
self.hyper_map = C.HyperMap()
# 创建用于累积梯度的张量,初始值为全零
self._grad_accumulation = self.weights.clone(prefix="grad_accumulation", init='zeros')
# 创建用于记录当前累积步数的参数初始值为0
self._accumulation_step = Parameter(Tensor(0, dtype=mstype.int32), name="accumulation_step")
def construct(self, loss, grads):
# 使用梯度积累操作将当前步的梯度添加到累积梯度上
loss = F.depend(loss, self.hyper_map(F.partial(gradient_accumulation_op, self._max_accumulation_step),
self._grad_accumulation, grads))
# 增加累积步数
self._accumulation_step += 1
# 如果累积步数达到最大累积步数,执行优化器进行梯度更新,并重置累积步数
if self._accumulation_step >= self._max_accumulation_step:
loss = F.depend(loss, self.optimizer(self._grad_accumulation))
self._accumulation_step = 0
# 如果累积步数为0执行梯度清零操作
if self._accumulation_step == 0:
loss = F.depend(loss, self.hyper_map(F.partial(gradient_clear_op), self._grad_accumulation))
return loss

View File

@ -0,0 +1,454 @@
# Copyright 2021 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.
# ============================================================================
"""grad freeze"""
import numpy as np
from mindspore.nn.cell import Cell
from mindspore.nn.optim import Optimizer
from mindspore.common import Tensor
from mindspore.common import dtype as mstype
from mindspore.nn.optim import LARS
from mindspore.nn.wrap.grad_reducer import DistributedGradReducer
from mindspore.ops import functional as F
from .base import ParameterProcess
from .grad_accumulation import GradientAccumulation
__all__ = ['GradientFreeze', 'FreezeOpt', 'freeze_cell']
CONTINUOUS_STRATEGY = 0
INTERVAL_STRATEGY = 1
class FreezeOpt(Cell):
"""
Optimizer that supports gradients freezing training.
Args:
opt (Cell): non-freezing optimizer instance, such as 'Momentum', 'SGD'.
train_parameter_groups (Union[tuple, list]): Groups of parameters for gradients freezing training.
train_strategy (Union[tuple(int), list(int), Tensor]): Strategy for gradients freezing training.
Supported Platforms:
``Ascend``
"""
def __init__(self, opt, train_parameter_groups=None, train_strategy=None):
super(FreezeOpt, self).__init__()
# 检查非冻结优化器是否是 Optimizer 的实例
# 初始化各种参数,包括是否使用 LARS 优化器,优化器类型等
# 创建一个优化器列表 self.opts用于存储梯度冻结训练中的优化器
# 检查是否传入的 opt 参数是 Optimizer 类的实例,如果不是则抛出异常
if not isinstance(opt, Optimizer):
raise TypeError(
f"The first arg 'opt' must be an Optimizer instance, but got {type(opt)}")
# 如果 train_strategy 参数被指定,但 train_parameter_groups 参数未被指定,抛出异常
if train_strategy is not None and train_parameter_groups is None:
raise ValueError("When the 'train_strategy' is specified, the value of 'train_parameter_groups' "
"must also be specified")
# 检查传入的 opt 是否为 LARSLayer-wise Adaptive Rate Scaling优化器的实例
if isinstance(opt, LARS):
self.is_lars = True
self.opt_class = type(opt.opt)# 获取 LARS 内部的优化器类型
self.opt_init_args = opt.opt.init_args # 获取 LARS 内部优化器的初始化参数
self.lars_init_args = opt.init_args# 获取 LARS 自身的初始化参数
self.single_opt = opt.opt# 获取 LARS 内部的优化器实例
self.parameters = opt.opt.parameters# 获取优化器的参数列表
self.learning_rate = opt.opt.init_learning_rate# 获取优化器的学习率
self.dynamic_lr = opt.opt.dynamic_lr# 获取优化器是否使用动态学习率
else:
self.is_lars = False
self.opt_class = type(opt)# 获取传入的非 LARS 优化器的类型
self.opt_init_args = opt.init_args# 获取非 LARS 优化器的初始化参数
self.single_opt = opt# 获取传入的非 LARS 优化器实例
self.parameters = opt.parameters# 获取优化器的参数列表
self.learning_rate = opt.init_learning_rate# 获取优化器的学习率
self.dynamic_lr = opt.dynamic_lr# 获取优化器是否使用动态学习率
# 创建一个空的优化器列表 self.opts
self.opts = []
# 如果 train_parameter_groups 参数未被指定,则默认创建 10 个参数组,每组包含部分优化器的参数
if train_parameter_groups is None:
self.groups_num = 10 # 定义参数组的数量
step = 6 # 每组参数包含的参数个数
parameters = opt.parameters # 获取整个模型的参数列表
# 将参数列表分割成多个参数组,每组包含 step 个参数
train_parameter_groups = (tuple(parameters[(i * step):]) for i in range(self.groups_num))
else:
# 如果用户指定了 train_parameter_groups则检查其类型并获取参数组的数量
if not isinstance(train_parameter_groups, (tuple, list)):
raise TypeError(
"The specified 'train_parameter_groups' should be tuple or list")
self.groups_num = len(train_parameter_groups)
# 初始化训练策略
self._init_train_strategy(train_strategy)
# 创建不同全局步数下的新学习率
self._create_new_group_learning_rate()
# 初始化优化器索引
self.opt_index = 0
# 遍历每个参数组,为每个参数组生成一个相应的优化器实例,并存储在 self.opts 列表中
for params in train_parameter_groups:
if not isinstance(params, (tuple, list)):
raise TypeError("The each element of 'train_parameter_groups' should be tuple or list "
"to store the Parameter")
# generate one-to-one opt corresponding to the parameter group
# 生成一个与参数组对应的优化器实例,并添加到 self.opts 列表中
self.opts.append(self._generate_new_optimizer(params))
self.opt_index += 1
"""初始化用于梯度冻结的训练策略。
Args:
train_strategy: 用于指定梯度冻结的训练策略的参数可以是以下之一
- None表示不使用任何特定的训练策略
- 整数列表或元组包含整数的列表或元组用于指定哪些梯度应该被冻结
- Tensor一个包含整数的张量其中每个整数表示哪些梯度应该被冻结
Raises:
ValueError: 如果train_strategy的类型不合法或包含不合法的元素
TypeError: 如果train_strategy的类型不是Nonetuplelist或Tensor
"""
def _init_train_strategy(self, train_strategy):
"""Init train strategy for gradient freeze."""
# 检查传入的train_strategy是否是元组或列表
if isinstance(train_strategy, (tuple, list)):
# 如果是,遍历其中的元素
for ele in train_strategy:
# 检查每个元素是否为整数,如果不是则引发异常
if not isinstance(ele, int):
raise ValueError(
"The element in train_strategy should be int number")
# 如果所有元素都是整数将train_strategy转换为int32类型的张量并赋值给self.train_strategy
self.train_strategy = Tensor(train_strategy, mstype.int32)
# 如果train_strategy是Tensor类型
elif isinstance(train_strategy, Tensor):
# 检查Tensor的维度是否为1dtype是否为int32如果不是则引发异常
if train_strategy.ndim != 1 or train_strategy.dtype != mstype.int32:
raise ValueError("When train_strategy is a Tensor, the dimension should be 1 and "
"the dtype should be int32")
# 如果满足条件直接赋值给self.train_strategy
self.train_strategy = train_strategy
# 如果train_strategy为None
elif train_strategy is None:
# 直接将self.train_strategy设置为None
self.train_strategy = None
# 如果train_strategy不是上述三种类型之一引发类型错误异常
else:
raise TypeError(
"The specified 'train_strategy' should be None, tuple, list or Tensor")
def _create_new_group_learning_rate(self):
"""Create new learning rate for different global step."""
"""创建不同全局步骤的新学习率。"""
# 初始化一个空的动态学习率列表,列表的数量等于组数(groups_num)
self.dynamic_learning_rate = [[] for _ in range(self.groups_num)]
# 如果当前的学习率为None将学习率设置为单一优化器single_opt的学习率
if self.learning_rate is None:
self.learning_rate = self.single_opt.learning_rate
return
# 如果启用了动态学习率dynamic_lr且学习率是列表类型list且训练策略是Tensor类型
if self.dynamic_lr and isinstance(self.learning_rate, list) and isinstance(self.train_strategy, Tensor):
train_strategy = list(self.train_strategy.asnumpy())
if len(self.learning_rate) <= len(train_strategy):
for i, lr in enumerate(self.learning_rate):
self.dynamic_learning_rate[train_strategy[i]].append(lr)
def _generate_new_optimizer(self, params):
"""Generate new optimizer."""
if self.dynamic_learning_rate[self.opt_index]:
lr = self.dynamic_learning_rate[self.opt_index]
else:
lr = self.learning_rate
if not self.is_lars:
opt = self.opt_class(params=params, learning_rate=lr, **self.opt_init_args)
opt._update_local_parameters_name("boost_{}".format(self.opt_index)) # pylint: disable=W0212
else:
opt = LARS(self.opt_class(params=params, learning_rate=lr, **self.opt_init_args),
**self.lars_init_args)
opt.opt._update_local_parameters_name("boost_{}".format(self.opt_index)) # pylint: disable=W0212
opt._update_local_parameters_name("boost_{}".format(self.opt_index)) # pylint: disable=W0212
return opt
class _TrainFreezeCell(Cell):
r"""
Gradient freezing training network.
Args:
net (Cell): The training network.训练网络接受一个神经网络模型作为参数
sens (numbers.Number): The scaling number to be filled as the input of backpropagation. Default value is 1.0.用作反向传播输入的缩放值默认值为 1.0
grad (tuple(Tensor)): The gradients of network parameters and inputs.网络参数和输入的梯度这里 grad 是一个包含参数和输入梯度的元组
grad_reducer (Cell): Constructs a gradient reducer Cell, which applies communication and average operations on
single-process gradient values.构建一个梯度缩减器 Cell用于在单进程梯度值上执行通信和平均操作
use_grad_accumulation (bool): Whether use grad accumulation.是否使用梯度累积指示是否启用梯度的累积
optimizer (Union[Cell]): Optimizer for updating the weights.用于更新权重的优化器接受一个优化器作为参数
max_accumulation_step (numbers.Number): Max grad accumulation steps. Default: 1.0最大梯度累积步骤默认值为 1.0
Supported Platforms:
``Ascend``
"""
# 初始化方法,接受一系列参数,用于配置训练网络
def __init__(self, net, sens, grad, grad_reducer, use_grad_accumulation, optimizer, max_accumulation_step=1):
# 调用父类 Cell 的初始化方法,并关闭自动前缀
super(_TrainFreezeCell, self).__init__(auto_prefix=False)
# 将传入的参数保存为类成员变量
self.net = net
self.grad = grad
self.grad_reducer = grad_reducer
self.opt = optimizer
self.parameters = optimizer.parameters
self.sens = sens
self.use_grad_accumulation = use_grad_accumulation
self.max_accumulation_step = max_accumulation_step
# 如果启用了梯度累积
if use_grad_accumulation:
# 创建 GradientAccumulation 对象,用于管理梯度累积
self.grad_accumulation = GradientAccumulation(
self.max_accumulation_step, self.optimizer)
# 构建方法,定义了训练过程中的具体操作
def construct(self, *inputs):
# 计算网络的损失
loss = self.net(*inputs)
# 创建一个与损失相同数据类型和形状的感知度张量
sens = F.fill(loss.dtype, loss.shape, self.sens)
# 计算网络参数的梯度grad 是一个包含参数梯度的元组
grads = self.grad(self.net, self.parameters)(*inputs, sens)
# 使用梯度缩减器对梯度进行缩减
grads = self.grad_reducer(grads)
# 如果启用了梯度累积
if self.use_grad_accumulation:
# 将损失和梯度传递给梯度累积器,并获得新的损失值
loss = self.grad_accumulation(loss, grads)
else:
# 否则,执行优化器来更新权重,并将损失与梯度之间建立依赖关系
loss = F.depend(loss, self.opt(grads))
# 返回损失值
return loss
class GradientFreeze:
r"""
Freezing the gradients of some layers randomly. The number and
probability of frozen layers can be configured by users
Args:
param_groups (Union[tuple, list]): Groups of parameters for gradients freezing training.
freeze_type (int): Strategy of gradients freezing training.
freeze_p (float): probability of gradients freezing training.
total_steps (numbers.Number): Steps of the whole training.
Examples:
>>> gradient_freeze_class = boost.GradientFreeze(10, 1, 0.5, 2000)
>>> network, optimizer = gradient_freeze_class.freeze_generate(network, optimizer)
"""
# 初始化方法,接受一系列参数来配置对象
def __init__(self, param_groups, freeze_type, freeze_p, total_steps):
# 保存传入的参数为对象的成员变量
self._param_groups = param_groups # 参数组,包含需要进行参数冻结的参数
self._freeze_type = freeze_type # 冻结类型,指定如何冻结参数,可能的取值有 'epoch' 或 'step'
self._freeze_p = freeze_p # 冻结比例,用于控制参数冻结的比例
self._total_steps = total_steps # 总步数,用于计算训练的总步数
self.grad_reducer = F.identity # grad_reducer 初始化为 F.identity通常用于梯度的标识操作
self._param_processer = ParameterProcess() # 创建 ParameterProcess 对象,并将其保存为成员变量
# 定义一个方法,用于将参数分组以进行梯度冻结训练
def split_parameters_groups(self, net, freeze_para_groups_number):
r"""
Split parameter groups for gradients freezing training.
Args:
net (Cell): The training network.
freeze_para_groups_number (int): The number of gradient freeze groups.
"""
# 创建一个空列表,用于存储分组后的参数
grouped_params = []
# 遍历可训练参数
tmp = []
for para in net.trainable_params():
name = para.name
# ensure 'bn' after 'conv' is not split
# 如果参数名称中包含 'bn' 或 'bias',则将参数添加到临时列表中
if 'bn' in name or 'bias' in name:
tmp.append(para)
# 如果临时列表中的参数数量已经达到 3 个或更多
elif len(tmp) >= 3:
# 将临时列表中的参数添加到分组参数列表中,并重新初始化临时列表
grouped_params.append(tmp)
tmp = [para]
# 否则,继续将参数添加到临时列表中
else:
tmp.append(para)
# 处理可能剩余的参数
if tmp:
grouped_params.append(tmp)
# 计算每个冻结组之间的步幅,以确保平均分配参数到不同的冻结组
stride = len(grouped_params) // freeze_para_groups_number
# 创建冻结后的参数组列表,每个元素是一个参数列表
freeze_grouped_params = [sum(grouped_params[i * stride:], [])
for i in range(freeze_para_groups_number)]
# 返回分组后的冻结参数列表
return freeze_grouped_params
#函数签名
def generate_freeze_index_sequence(self, parameter_groups_number, freeze_strategy, freeze_p, total_steps):
r"""
Generate index sequence for gradient freezing training.
Args:
parameter_groups_number (int): The number of parameter groups.
freeze_strategy (int): Gradient freeze grouping strategy, select from [0, 1].
freeze_p (float): Gradient freezing probability.
total_steps (int): Total training steps.
"""
#计算total_step略高于total_steps的101%
total_step = int(total_steps * 1.01)
#如果parameter_groups_number小于等于1则返回一个长度为total_step的零列表
if parameter_groups_number <= 1:
return [0 for _ in range(total_step)]
# local continuous freezing training strategy, as '00001234'
#检查freeze_strategy是否等于CONTINUOUS_STRATEGY常量。
if freeze_strategy == CONTINUOUS_STRATEGY:
#根据提供的公式使用freeze_p和parameter_groups_number计算zero_cnt。
zero_cnt = int(
freeze_p * (parameter_groups_number - 1) / (1 - freeze_p) + 0.5)
#创建一个列表sub_idx其中包括zero_cnt次重复的零然后是从1到parameter_groups_number的序列。
sub_idx = [0] * zero_cnt + list(range(1, parameter_groups_number))
#通过重复sub_idx直到其长度等于total_step来生成freeze_idxes列表。
freeze_idxes = []
while len(freeze_idxes) < total_step:
freeze_idxes += sub_idx
#返回freeze_idxes列表。
return freeze_idxes
# interval freezing training strategy, as '01020304'
#检查freeze_strategy是否等于INTERVAL_STRATEGY常量。
if freeze_strategy == INTERVAL_STRATEGY:
#初始化index_all其中包括从1到parameter_groups_number的序列计算每个索引的概率prob并初始化freeze_idxes、zero_cnt和freeze_cnt
index_all = list(range(1, parameter_groups_number))
prob = [x / sum(index_all) for x in index_all]
freeze_idxes = [0]
zero_cnt = 1
freeze_cnt = 0
#启动一个循环直到freeze_idxes达到所需的长度。计算当前的freeze_p_cur。
while len(freeze_idxes) < total_step:
freeze_p_cur = 1.0 * freeze_cnt / (zero_cnt + freeze_cnt)
#检查当前的冻结概率是否小于1 - freeze_p。
if freeze_p_cur < 1 - freeze_p:
#如果条件成立则根据提供的概率从index_all中随机选择一个索引并将其附加到freeze_idxes然后增加freeze_cnt。
freeze_idxes.append(
int(np.random.choice(index_all[::-1], p=prob)))
freeze_cnt += 1
#如果条件不成立则将零附加到freeze_idxes并增加zero_cnt。
else:
freeze_idxes.append(0)
zero_cnt += 1
#返回freeze_idxes列表。
return freeze_idxes
#如果freeze_strategy既不是CONTINUOUS_STRATEGY也不是INTERVAL_STRATEGY则引发一个ValueError其中包含一条消息指示不支持的策略。
raise ValueError(
f"Unsupported freezing training strategy '{freeze_strategy}'")
# 生成冻结网络和优化器的方法
def freeze_generate(self, network, optimizer):
r"""
Generate freeze network and optimizer.
Args:
network (Cell): The training network.
optimizer (Cell): Optimizer for updating the weights.
"""
# 将网络的参数分成多个参数组
train_para_groups = self.split_parameters_groups(
network, self._param_groups)
# 对每个参数组进行处理,生成每个参数组的参数
for i in range(self._param_groups):
train_para_groups[i] = self._param_processer.generate_group_params(train_para_groups[i],
optimizer.init_params['params'])
# 生成冻结索引策略
train_strategy = self.generate_freeze_index_sequence(
self._param_groups, self._freeze_type, self._freeze_p, self._total_steps)
# 创建带有冻结功能的优化器
optimizer = FreezeOpt(optimizer, train_para_groups, train_strategy)
# 返回网络和优化器
return network, optimizer
# 生成带有冻结功能的网络和优化器的方法
def freeze_cell(reducer_flag, network, optimizer, sens, grad, use_grad_accumulation, mean=None, degree=None,
max_accumulation_step=1):
r"""
Generate freeze network and optimizer.
Args:
reducer_flag (bool): Reducer flag.
network (Cell): The training network.
optimizer (Cell): Optimizer for updating the weights.
sens (numbers.Number): The scaling number.
grad (tuple(Tensor)): Tuple of gradient tensors.
use_grad_accumulation (bool): Use gradient accumulation flag.
mean (bool): Gradients mean flag. default: None.
degree (int): Device number. default: None.
max_accumulation_step (int): Max accumulation steps. default: 1.
Examples:
>>> import numpy as np
>>> from mindspore import Tensor, Parameter, nn
>>> import mindspore.ops as ops
>>> from mindspore.boost.grad_freeze import freeze_cell
>>>
>>> class Net(nn.Cell):
... def __init__(self, in_features, out_features):
... super(Net, self).__init__()
... self.weight = Parameter(Tensor(np.ones([in_features, out_features]).astype(np.float32)),
... name='weight')
... self.matmul = ops.MatMul()
...
... def construct(self, x):
... output = self.matmul(x, self.weight)
... return output
...
>>> in_features, out_features = 16, 10
>>> network = Net(in_features, out_features)
>>> optimizer = nn.Momentum(net.trainable_params(), learning_rate=0.1, momentum=0.9)
>>> grad = ops.GradOperation(get_by_list=True, sens_param=True)
>>> freeze_nets = freeze_cell(False, network, optimizer, 1.0, grad, False, None, None, 1)
"""
# 如果reducer_flag为真表示使用了分布式梯度聚合
if reducer_flag:
# 创建参数处理器
param_processer = ParameterProcess()
# 创建梯度reducers将每个optimizer的参数传递给参数处理器
grad_reducers = (DistributedGradReducer(param_processer.assign_parameter_group(opt.parameters),
mean, degree) for opt in optimizer.opts)
# 创建冻结网络的元组每个网络对应一个optimizer
freeze_nets = tuple(_TrainFreezeCell(network, sens, grad, reducer,
use_grad_accumulation, opt, max_accumulation_step)
for reducer, opt in zip(grad_reducers, optimizer.opts))
else:
# 如果没有使用分布式梯度聚合直接创建冻结网络的元组每个网络对应一个optimizer
freeze_nets = tuple(_TrainFreezeCell(network, sens, grad, F.identity,
use_grad_accumulation, opt, max_accumulation_step)
for opt in optimizer.opts)
# 返回冻结网络的元组
return freeze_nets

View File

@ -0,0 +1,70 @@
/**
* 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 "include/transform/graph_ir/graph_builder.h"
#include <sstream>
#include "ops/math_ops.h"
namespace mindspore {
namespace transform {
// 该函数用于构建 MDDatasetMindSpore Dataset的图形Graph
DfGraphPtr BuildMDDatasetGraph(const DatasetGraphParam &param) {
MS_LOG(INFO) << "BuildMDDatasetGraph."; // 记录日志,表示正在构建 MDDataset 图形
// InitData
// 创建一个操作符 "InitData",使用参数 "init_data_tmp" 作为操作符的名称,并设置属性 "channel_name" 为
// param.queue_name() 的值
auto d = ge::op::InitData("init_data_tmp").set_attr_channel_name(param.queue_name());
// set graph inputs & outputs
// 设置图形的输入和输出
std::vector<ge::Operator> inputs{d}; // 将 "InitData" 操作符设置为图形的输入
std::vector<ge::Operator> outputs{d}; // 将 "InitData" 操作符设置为图形的输出
// 创建一个名为 "dataset" 的 MDDataset 图形,并使用 "dataset_graph" 指针指向该图形
DfGraphPtr dataset_graph = std::make_shared<DfGraph>("dataset");
// 将输入和输出设置到 MDDataset 图形中
(void)dataset_graph->SetInputs(inputs);
(void)dataset_graph->SetOutputs(outputs);
return dataset_graph; // 返回构建好的 MDDataset 图形的指针
}
// 该函数用于构建数据集的图形Graph
Status BuildDatasetGraph(const DatasetGraphParam &param, const std::string &phase) {
Status ret; // 存储函数执行结果的状态对象
std::string graph_name = phase; // 以给定的 'phase' 参数作为图形的名称
MS_LOG(INFO) << "BuildDatasetGraph begin. phase is " << phase; // 记录日志,表示开始构建数据集图形
MS_LOG(INFO) << "param is " << param.ToString() << "."; // 记录日志,打印参数 'param' 的详细信息
// 调用 BuildMDDatasetGraph 函数构建 MDDataset 图形,并将构建好的图形指针存储在 'dataset_graph' 变量中
DfGraphPtr dataset_graph = BuildMDDatasetGraph(param);
// 将构建好的 MDDataset 图形添加到图形管理器中,并使用 'graph_name' 作为图形的名称
ret = DfGraphManager::GetInstance().AddGraph(graph_name, dataset_graph);
// 根据 AddGraph 函数的执行结果,进行相应的日志记录
if (ret != Status::SUCCESS) { // 如果添加图形失败,记录错误日志
MS_LOG(ERROR) << "BuildDatasetGraph failed.";
} else { // 如果添加图形成功,记录结束日志
MS_LOG(INFO) << "BuildDatasetGraph end.";
}
return ret; // 返回函数执行结果的状态对象
}
} // namespace transform
} // namespace mindspore

View File

@ -0,0 +1,249 @@
# Copyright 2020 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.
# ============================================================================
"""Patterns for describing graphs"""
#描述图形的模式
from mindspore.ops import Primitive
from mindspore.common.tensor import Tensor
from mindspore._c_expression import Pattern, OneOf_, Prim_, Call_, NoneOf_, Any, NewTensor_, NewParameter_, Imm
__all__ = [
"OneOf",
"Prim",
"Call",
"NoneOf",
"Any",
"NewTensor",
"NewParameter",
"Imm"
]
class OneOf(OneOf_):
r"""
Express a pattern which allows a list of patterns.
表达一个允许模式列表的模式
"""
def __init__(self, patterns=None):
r"""
Args:
patterns(Union[:class:`mindspore.graph_utils.graph_pattern`,
tuple[:class:`mindspore.graph_utils.graph_pattern`],
list[:class:`mindspore.graph_utils.graph_pattern`]]): list of allowed patterns,
each element should be one of the exposed Pattern instance.
Raises:
TypeError: raise type error for invalid inputs.
"""
self.patterns = patterns
if isinstance(patterns, Pattern):
OneOf_.__init__(self, [patterns])
#如果patterns是mindspore.graph_utils.graph_pattern类的实例则使用包含patterns的单一元素列表初始化基类OneOf_。
elif isinstance(patterns, (tuple, list)) and all(isinstance(pattern, Pattern) for pattern in patterns):
OneOf_.__init__(self, patterns)
#如果patterns是元组或列表并且其中的所有元素都是mindspore.graph_utils.graph_pattern类的实例
#则使用包含patterns中模式的列表初始化基类OneOf_
else:
raise TypeError(f"Expect patterns to be a list of Patterns/Pattern, got : {patterns}")
#如果patterns是其他类型的对象或者其中包含不是mindspore.graph_utils.graph_pattern类的实例
#则抛出TypeError并附带相应的错误消息。
class Prim(Prim_):
r"""
Express a pattern of certain primitive type(s).
表示某种基本类型的模式
NOTE:
This pattern will match and only match the primitive value node. If matching primitive CNode is needed,
please refer to CallWith pattern.
"""
def __init__(self, types, name=None):
r"""
Args:
支持三种不同的types参数输入方式
types (Union[str, :class:`mindspore.ops.Primitive`, list[:class:`mindspore.ops.Primitive`],
tuple[:class:`mindspore.ops.Primitive`]):
Specify allowed types.
If it is a string, the form could be
1) a single primitive type, e.g. 'Conv2D'若types是一个字符串则可以是单个基本类型例如 'Conv2D'
2) a set of primitive types separated by '|', e.g. 'MatMul|Conv2D'
多个基本类型|符号分隔例如 'MatMul|Conv2D'
It can also be a Primitive or a list/tuple of Primitives, e.g. [ops.Conv2D(1, 6)]
如果types是一个Primitive对象则表示仅匹配该具体的基本类型
如果types是一个列表或元组并且列表中的元素都是Primitive对象则表示匹配多个基本类型
name (str): name of the pattern, optional. Default: None.
Raises:
TypeError: raise type error for invalid argument.
"""
# 如果提供了 name 参数,但不是字符串类型,则抛出 TypeError
if name is not None and not isinstance(name, str):
raise TypeError(f"Expect string, got : {name}")
# 将参数 name 赋值给对象的 name 属性
self.name = name
# 根据 types 参数的类型进行不同的处理
if isinstance(types, str):
if self.name is None:
self.name = types
self.types = types.split('|')
# 如果 types 是一个字符串,则将其按照 '|' 符号拆分,并存储在 self.types 中
elif isinstance(types, Primitive):
# 如果 types 是一个 Primitive 对象,则表示只允许匹配这个具体的基本类型
if self.name is None:
self.name = types.name
self.types = [types]
elif isinstance(types, (tuple, list)) and all(isinstance(tp, Primitive) for tp in types):
# 如果 types 是一个包含 Primitive 对象的列表或元组,则表示允许匹配多个基本类型
if self.name is None:
self.name = ""
for prim in types:
self.name += prim.name
self.types = types
else:
# 如果 types 参数不是允许的类型,则抛出 TypeError
raise TypeError(f"Expecting a primitive type string or a list of Primitives, got : {types}")
# 调用父类 Prim_ 的初始化方法,将处理好的 types 和 name 作为参数传递给父类
Prim_.__init__(self, self.types, self.name)
class Call(Call_):
#初始化对象的属性
r"""
Express a primitive CNode.
"""
def __init__(self, prim_pattern, inputs=None):
r"""
Args:
prim_pattern (Union[str, :class:`mindspore.graph_utils.graph_pattern.IsPrimTypeOf`,
:class:`mindspore.ops.Primitive`]): Primitive ValueNode in the Primitive CNode.
inputs (Union[list[:class:`mindspore.graph_utils.graph_pattern`],
tuple[:class:`mindspore.graph_utils.graph_pattern`]]):
Specify inputs pattern for the primitive(s), optional. If None, accepts any inputs; if specified, input
patterns should be of right order and each element should be one of the exposed Pattern instance.
模式的顺序应该正确每个元素应该是公开的Pattern实例之一
Raises:
TypeError: raise type error for invalid argument.
"""
#检查prim_pattern的类型是否是Pattern、Primitive或字符串类型。
#如果不是这些类型之一则抛出TypeError表示期望prim_pattern是Pattern、Primitive或字符串类型。
if not isinstance(prim_pattern, (Pattern, str, Primitive)):
raise TypeError(f"Expect prim_pattern to be Pattern, Primitive or string, got : {prim_pattern}")
#将传入的prim_pattern赋值给实例变量self.prim_pattern以保存原语模式Primitive Pattern或原语名称Primitive name
self.prim_pattern = prim_pattern
#将self.inputs初始化为空列表
self.inputs = []
#None什么都不做
if inputs is None:
pass
#检查inputs是否为Pattern的列表或元组且其中的所有元素都是Pattern类型。
elif isinstance(inputs, (tuple, list)) and all(isinstance(input, Pattern) for input in inputs):
self.inputs = inputs
#如果inputs不满足上述条件抛出TypeError表示期望inputs是Pattern的列表。
else:
raise TypeError(f"Expect inputs to be a list of Patterns, got : {inputs}")
Call_.__init__(self, self.prim_pattern, self.inputs)
#调用基类Call_的构造函数来完成初始化传入self.prim_pattern作为原语模式或名称
#以及self.inputs作为输入模式列表。
class NoneOf(NoneOf_):
r"""
Express a pattern which forbids a list of patterns.
表达一个禁止模式列表的模式
NOTE:
NoneOf pattern should not be the root pattern.
#NoneOf模式不是根模式
"""
def __init__(self, patterns=None):
r"""
Args:
patterns(Union[list[:class:`mindspore.graph_utils.graph_pattern`]]: list of forbidden patterns, each
element should be one of the exposed Pattern instance.
禁用模式列表每个元素应该是公开的Pattern实例之一
Raises:
TypeError: raise type error for invalid argument.
"""
self.patterns = patterns
if patterns is None:
NoneOf_.__init__(self, ())
#如果 patterns 参数为 None即未提供 patterns则将 None 传递给 NoneOf_ 类的初始化方法。
elif isinstance(patterns, Pattern):
NoneOf_.__init__(self, [patterns])
#如果 patterns 参数是一个单独的 Pattern 对象,则将包含这个 Pattern 对象的列表传递给 NoneOf_ 类的初始化方法。
elif isinstance(patterns, (tuple, list)) and all(isinstance(pattern, Pattern) for pattern in patterns):
NoneOf_.__init__(self, patterns)
#如果 patterns 参数是一个列表或元组,并且列表中的元素都是 Pattern 对象,
#则将整个列表传递给 NoneOf_ 类的初始化方法。
else:
raise TypeError(f"Expect list of Patterns/Pattern, got : {patterns}")
class NewTensor(NewTensor_):
r"""
New Tensor to be used in the target.
要在目标中使用的新张量
"""
def __init__(self, input_tensor):
r"""
Args:
input_tensor(:class:`mindspore.common.tensor.Tensor`): new tensor to be used in the target.
要在目标中使用的新张量
Raises:
TypeError: raise type error for invalid argument.
"""
self.input_tensor = input_tensor
# 将传入的 input_tensor 参数赋值给对象的 input_tensor 属性
if isinstance(input_tensor, Tensor):
# 检查 input_tensor 参数的类型
NewTensor_.__init__(self, input_tensor)
# 如果 input_tensor 是一个 Tensor 对象,则调用 NewTensor_ 类的初始化方法,并传入 input_tensor 作为参数
else:
raise TypeError(f"Expect input_tensor to be a Tensor got : {input_tensor}")
# 如果 input_tensor 参数不是 Tensor 对象,则抛出 TypeError指示输入参数类型错误
class NewParameter(NewParameter_):
r"""
New Parameter to be used in the target.
"""
def __init__(self, para_name, default_tensor, requires_grad=False, layerwise_parallel=False):
r"""
Args:
para_name(str): name for the new Parameter.
default_tensor(:class:`mindspore.common.tensor.Tensor`): default value for the new Parameter.
requires_grad(bool): True if the parameter requires gradient. Default: True.
如果参数需要梯度则为True
layerwise_parallel(bool): switch for layerwise parallel mode. Default: False.
Layerwise_parallel (bool):分层并行模式开关
Raises:
TypeError: raise type error for invalid argument.
"""
# 将传入的 para_name、default_tensor、requires_grad 和 layerwise_parallel 参数赋值给对象的相应属性
self.para_name = para_name
self.default_tensor = default_tensor
self.requires_grad = requires_grad
self.layerwise_parallel = layerwise_parallel
# 检查传入的参数类型是否正确,并根据结果选择初始化父类 NewParameter_
if isinstance(para_name, str) and isinstance(default_tensor, Tensor) and isinstance(requires_grad, bool) and\
isinstance(layerwise_parallel, bool):
# 如果 para_name 是一个字符串default_tensor 是一个 Tensor 对象requires_grad 和 layerwise_parallel 都是布尔值,
# 则调用 NewParameter_ 类的初始化方法,并传入 para_name、default_tensor、requires_grad 和 layerwise_parallel 作为参数。
NewParameter_.__init__(self, self.para_name, self.default_tensor, self.requires_grad,
self.layerwise_parallel)
else:
# 如果有任何一个参数类型不正确,则抛出 TypeError指示输入参数类型错误。
raise TypeError(f"Expect para_name(str), default_tensor(Tensor), requires_grad(bool), \
layerwise_parallel(bool) got : {para_name}, {default_tensor}, \
{requires_grad}, {layerwise_parallel}")

View File

@ -0,0 +1,234 @@
/**
* 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 "include/transform/graph_ir/graph_runner.h"
#include <algorithm>
#include <string>
#include <memory>
#ifndef ENABLE_LITE_ACL
#include "pybind11/pybind11.h"
#endif
#include "utils/log_adapter.h"
#include "include/common/utils/config_manager.h"
#include "sys/time.h"
#include "include/common/utils/utils.h"
#include "include/common/utils/callbacks.h"
#ifdef ENABLE_D
#include "include/common/utils/callbacks_ge.h"
#endif
#include "utils/ms_context.h"
#ifndef ENABLE_LITE_ACL
namespace py = pybind11;
#endif
namespace mindspore {
namespace transform {
// 该函数用于创建新的 GEGraphEngine会话。
// 参数 'sess_options' 表示会话的选项。
std::shared_ptr<ge::Session> GraphRunner::NewSession(const SessionOptions &sess_options) {
#ifdef ENABLE_D
std::shared_ptr<ge::Session> ret; // 用于存储创建的 GE 会话的智能指针
auto ms_context = MsContext::GetInstance(); // 获取 MindSpore 上下文实例
MS_EXCEPTION_IF_NULL(ms_context); // 检查上下文实例是否为空
if (ms_context->backend_policy() == "ge") { // 检查当前的后端策略是否为 GE
ret = std::make_shared<ge::Session>(sess_options); // 创建一个新的 GE 会话,并使用传入的选项 'sess_options'
if (ret == nullptr) { // 如果创建 GE 会话失败,抛出异常并记录错误日志
MS_LOG(EXCEPTION) << "Create GE session failed!";
}
MS_LOG(INFO) << "Create new GE session success!"; // 记录成功创建 GE 会话的日志
return ret; // 返回新创建的 GE 会话的智能指针
}
#endif
MS_LOG(WARNING) << "no GE client, return nullptr!"; // 如果没有启用 GE 后端,记录警告日志并返回空指针
return nullptr; // 返回空指针,表示没有创建 GE 会话
}
// 该构造函数用于初始化GraphRunner对象
GraphRunner::GraphRunner(const GraphRunnerOptions &options)
: options_(options), graph_manager_(DfGraphManager::GetInstance()) {
// 检查并记录MindSpore的并行策略是否为ONE_DEVICE
if (ConfigManager::GetInstance().parallel_strategy() == ParallelStrategy::ONE_DEVICE) {
MS_LOG(INFO) << "ME run in ONE_DEVICE strategy mode";
}
if (options.sess_ptr != nullptr) { // 根据options中传入的sess_ptr判断是否已有现有会话
sess_ = options.sess_ptr;
} else { // 若sess_ptr为空则调用NewSession函数创建新的GE会话
sess_ = NewSession(options.options);
if (sess_ == nullptr) {
MS_LOG(WARNING) << "graph runner sess_ is nullptr!";
}
}
#ifdef ENABLE_D
auto ms_context = MsContext::GetInstance();
MS_EXCEPTION_IF_NULL(ms_context);
if (ms_context->backend_policy() == "ge") {
// register the callback function
// 注册回调函数
if (sess_->RegisterCallBackFunc(callbacks::kCheckPoint, callbacks::CheckpointSaveCallback) != ge::GRAPH_SUCCESS) {
MS_LOG(EXCEPTION) << "register callback failed!";
}
if (sess_->RegisterCallBackFunc(callbacks::kSummary, callbacks::SummarySaveCallback) != ge::GRAPH_SUCCESS) {
MS_LOG(EXCEPTION) << "register summary callback failed!";
}
}
#endif
// 从图形管理器获取所有的图形包装器
std::vector<DfGraphWrapperPtr> wrappers = graph_manager_.GetAllGraphs();
if (wrappers.empty()) { // 若图形包装器为空,记录日志并直接返回
MS_LOG(INFO) << "The GraphManager is empty!!";
return;
}
#ifdef ENABLE_D
if (ms_context->backend_policy() != "ge") {
return;
}
for (auto &it : wrappers) { // 遍历所有图形包装器并将未保存的图形添加到GE会话中
std::set<string> saved_graph = graph_manager_.GetSavedGraphs();
auto iter_find = saved_graph.find(std::to_string(it->id_));
if (iter_find != saved_graph.end()) {
continue;
}
MS_LOG(INFO) << "Add the graph " << (*it).name_ << " to GE, it's id is: " << (*it).id_;
graph_manager_.AddSavedGraphs(std::to_string(it->id_));
(void)sess_->AddGraph(static_cast<uint32_t>(it->id_), *(it->graph_ptr_), it->options_);
}
#endif
}
// 该函数用于运行指定名称的图形Graph
Status GraphRunner::RunGraph(const RunOptions &options, const std::vector<GeTensorPtr> &inputs,
std::vector<GeTensorPtr> *outputs) {
std::string name = options.name; // 获取运行选项中的图形名称
if (name.empty()) { // 如果图形名称为空,记录错误日志并返回无效参数状态
MS_LOG(ERROR) << "The graph name is null";
return Status::INVALID_ARGUMENT;
}
// 从图形管理器获取指定名称的图形包装器
DfGraphWrapperPtr wrap_ptr = graph_manager_.GetGraphByName(name);
if (wrap_ptr == nullptr) {
MS_LOG(ERROR) << "Get graph form DfGraphManager failed!"; // 如果获取图形包装器失败,记录未找到状态的错误日志
return Status::NOT_FOUND;
}
if (wrap_ptr->graph_ptr_ == nullptr) { // 如果图形为空,记录警告日志并返回未找到状态
MS_LOG(WARNING) << "The graph is null";
return Status::NOT_FOUND;
}
// call ge::RunGraph() to exec a graph;
// 调用 ge::RunGraph() 来执行图形计算
std::vector<GeTensor> ge_inputs;
std::vector<GeTensor> ge_outputs;
// 将输入参数 'inputs' 转换为 'ge_inputs',用于调用 GE 接口
(void)std::transform(inputs.begin(), inputs.end(), std::back_inserter(ge_inputs),
[](const GeTensorPtr &i) { return *i; });
MS_LOG(INFO) << "Run the graph in GE with " << ge_inputs.size() << " inputs"; // 记录日志,表示正在运行 GE 图形,以及输入的数量
struct timeval start_time, end_time;
(void)gettimeofday(&start_time, nullptr);
#ifdef ENABLE_D
auto ms_context = MsContext::GetInstance();
MS_EXCEPTION_IF_NULL(ms_context);
if (ms_context->backend_policy() == "ge") {
if (sess_ == nullptr) {
MS_LOG(ERROR) << "The GE session is null, can't run the graph!"; // 如果 GE 会话为空,记录错误日志并返回执行失败状态
return Status::FAILED;
}
ge::Status ret = sess_->RunGraph(static_cast<uint32_t>(wrap_ptr->id_), ge_inputs, ge_outputs); // 调用 GE 接口运行图形
if (ret != ge::GRAPH_SUCCESS) {
MS_LOG(ERROR) << "Call GE RunGraph Failed, ret is: " << ret; // 如果运行图形失败,记录错误日志并返回执行失败状态
return Status::FAILED;
}
}
#else
ge_outputs.swap(ge_inputs); // 如果未启用 GE 后端,直接交换输入和输出,用于后续返回输出结果
#endif
(void)gettimeofday(&end_time, nullptr);
const uint64_t kUSecondInSecond = 1000000;
uint64_t cost = kUSecondInSecond * static_cast<uint64_t>(end_time.tv_sec - start_time.tv_sec);
cost += static_cast<uint64_t>(end_time.tv_usec - start_time.tv_usec);
MS_LOG(INFO) << "Call GE RunGraph Success in " << cost << " us, the GE outputs num is: " << ge_outputs.size();
// 记录日志,表示图形计算成功执行,并打印执行时间和输出数量
// 将 GE 输出结果转换为 'outputs',用于返回给调用者
(void)std::transform(ge_outputs.begin(), ge_outputs.end(), std::back_inserter(*outputs),
[](const GeTensor &ge_tensor) { return std::make_shared<GeTensor>(ge_tensor); });
return Status::SUCCESS; // 返回执行成功状态,并带有输出结果
}
// 该函数用于运行指定名称的图形,并将输入和输出都转换为 MeTensorPtr 类型
Status GraphRunner::RunGraph(const RunOptions &options, const std::vector<MeTensorPtr> &inputs,
std::vector<MeTensorPtr> *const outputs) {
std::vector<GeTensorPtr> ge_inputs; // 用于存储转换后的输入 GeTensorPtr
for (auto it : inputs) {
MS_EXCEPTION_IF_NULL(it);
MS_LOG(INFO) << "inputs tensor's data size is: " << (*it).DataSize(); // 打印输入 MeTensor 的数据大小
auto shape = (*it).shape();
std::string shape_str;
for (const auto &elem : shape) {
shape_str += std::to_string(elem);
shape_str += " ";
}
MS_LOG(INFO) << "inputs tensor's shape is: { " << shape_str << "}"; // 打印输入 MeTensor 的形状
// 将输入 MeTensor 转换为 GeTensor转换后的格式为 kOpFormat_NCHW
auto ge_tensor_ptr = TransformUtil::ConvertTensor(it, kOpFormat_NCHW);
if (ge_tensor_ptr != nullptr) {
ge_inputs.emplace_back(ge_tensor_ptr); // 将转换后的 GeTensorPtr 添加到 ge_inputs 中
} else { // 如果转换失败,记录日志并返回执行失败状态
MS_LOG(INFO) << "Convert input Me tensor to Ge tensor failed. Abort this graph";
return Status::FAILED;
}
}
std::vector<GeTensorPtr> ge_outputs; // 用于存储运行图形后的输出 GeTensorPtr
Status ret;
{
// Release GIL before calling into (potentially long-running) C++ code
// 释放 GIL然后调用 C++ 代码(可能是长时间运行的代码)
#ifndef ENABLE_LITE_ACL
py::gil_scoped_release release;
#endif
ret = RunGraph(options, ge_inputs, &ge_outputs); // 调用 RunGraph 函数运行图形计算
}
if (ret != Status::SUCCESS) {
return ret; // 如果运行图形失败,直接返回执行失败状态
} else {
// convert GeTensor to MeTensor
// 将输出 GeTensor 转换为 MeTensor并将转换后的 MeTensorPtr 添加到 outputs 中
for (auto &it : ge_outputs) {
auto tensor = TransformUtil::ConvertGeTensor(it);
if (tensor != nullptr) {
(void)outputs->emplace_back(tensor);
}
}
MS_LOG(INFO) << "Return Me tensor outputs num is: " << outputs->size(); // 打印返回的 MeTensor 数量
return Status::SUCCESS; // 返回执行成功状态,并带有输出结果
}
}
} // namespace transform
} // namespace mindspore

View File

@ -0,0 +1,187 @@
# 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.
# ============================================================================
"""Group Loss Scale Manager"""
from __future__ import absolute_import
from __future__ import division
from mindspore.nn.cell import Cell
import mindspore.common.dtype as mstype
from mindspore.ops import operations as P
from mindspore.common.tensor import Tensor
from mindspore.common.parameter import Parameter, ParameterTuple
__all__ = ["GroupLossScaleManager"]
class GroupLossScaleManager(Cell):
"""
Enhanced hybrid precision algorithm supports multi-layer application of different loss scales and
dynamic updating of loss scales.
增强型混合精度算法支持不同损耗规模的多层应用损失规模的动态更新
Args:
init_loss_scale (Number): The initialized loss scale value.
loss_scale_groups (List): The loss scale groups, which are divided from the param list.
Inputs:
- **x** (Tensor) - The output of last operator.
- **layer1** (Int) - Current network layer value.
- **layer2** (Int) - Last network layer value.
Outputs:
- **x** (Tensor) - The output of `_DynamicLossScale` operator.
Supported Platforms:
``Ascend``
Examples:
>>> import mindspore as ms
>>> from mindspore import boost, nn
>>>
>>> class Net(nn.Cell):
... def __init__(self, enhanced_amp, num_class=10, num_channel=1):
... super(Net, self).__init__()
... self.conv1 = nn.Conv2d(num_channel, 6, 5, pad_mode='valid')
... self.conv2 = nn.Conv2d(6, 16, 5, pad_mode='valid')
... self.fc1 = nn.Dense(16*5*5, 120, weight_init='ones')
... self.fc2 = nn.Dense(120, 84, weight_init='ones')
... self.fc3 = nn.Dense(84, num_class, weight_init='ones')
... self.relu = nn.ReLU()
... self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)
... self.flatten = nn.Flatten()
... self.enhanced_amp = enhanced_amp
...
... def construct(self, x):
... x = self.enhanced_amp(x, 0, 1)
... x = self.max_pool2d(self.relu(self.conv1(x)))
... x = self.max_pool2d(self.relu(self.conv2(x)))
... x = self.flatten(x)
... x = self.enhanced_amp(x, 1, 2)
... x = self.relu(self.fc1(x))
... x = self.relu(self.fc2(x))
... x = self.fc3(x)
... x = self.enhanced_amp(x, 2, 3)
... return x
>>>
>>> loss_scale_manager = boost.GroupLossScaleManager(4096, [])
>>> net = Net(loss_scale_manager)
>>> param_group1 = []
>>> param_group2 = []
>>> for param in net.trainable_params():
>>> if 'conv' in param.name:
>>> param_group1.append(param)
>>> else:
>>> param_group2.append(param)
>>> loss_scale_manager.loss_scale_groups = [param_group1, param_group2]
>>> loss = nn.SoftmaxCrossEntropyWithLogits()
>>> optim = nn.Momentum(params=net.trainable_params(), learning_rate=0.1, momentum=0.9)
>>> boost_config_dict = {"boost": {"mode": "manual", "less_bn": False, "grad_freeze": False, "adasum": False, \
>>> "grad_accumulation": False, "dim_reduce": False, "loss_scale_group": True}}
>>> model = ms.Model(net, loss_fn=loss, optimizer=optim, metrics=None, loss_scale_manager=loss_scale_manager, \
>>> boost_level="O1", boost_config_dict=boost_config_dict)
>>> # For details about how to build the dataset, please refer to the variable `dataset_train` in tutorial
>>> # document on the official website:
>>> # https://www.mindspore.cn/tutorials/zh-CN/master/beginner/quick_start.html
>>> dataset = create_custom_dataset()
>>> model.train(2, dataset)
"""
def __init__(self, init_loss_scale, loss_scale_groups):
super(GroupLossScaleManager, self).__init__()
self._loss_scale = init_loss_scale
self.loss_scale_groups = loss_scale_groups
self.loss_scale_number = 0
self.layer_loss_scale = None
self.dynamic_loss_scale = None
def set_loss_scale_status(self, loss_scale_number, init_loss_scale):
"""
Generate dynamic loss scale tuple and set overflow status list.
生成动态损失规模元组并设置溢出状态列表
Args:
loss_scale_number (int): The number of loss scale.
init_loss_scale (float): The initialized loss scale.
"""
# 初始化动态损失尺度管理器
self.loss_scale_number = loss_scale_number # 设置损失尺度的数量
# 创建一个包含动态损失尺度的列表 inner_list
inner_list = [P._DynamicLossScale(layer=x) for x in range(loss_scale_number + 1)] # pylint: disable=W0212
# 将 inner_list 转换为元组,作为 layer_loss_scale 的值
self.layer_loss_scale = tuple(inner_list)
# 创建动态损失尺度的参数元组 dynamic_loss_scale
self.dynamic_loss_scale = ParameterTuple(
Parameter(Tensor(1, mstype.float32), name='layer_loss_scale_{}'.format(x), requires_grad=False)
for x in range(loss_scale_number + 2))
# 初始化动态损失尺度的值
if isinstance(init_loss_scale, list):
# 如果 init_loss_scale 是列表,将列表中的值设置为动态损失尺度的初始值
for i, value in enumerate(init_loss_scale):
self.dynamic_loss_scale[i + 1].set_data(value)
else:
# 如果 init_loss_scale 不是列表,使用同一初始值设置所有动态损失尺度的值
for i in range(self.loss_scale_number):
self.dynamic_loss_scale[i + 1].set_data(init_loss_scale)
self.dynamic_loss_scale[i + 1].set_data(init_loss_scale)
def update_loss_scale_status(self, layer, update_ratio):
"""
Update dynamic loss scale.
更新动态损失规模
Args:
layer (int): Current layer.
update_ratio (float): The ratio of loss scale update.
Outputs:
float, new loss scale.
"""
# 增加层次计数器 layer
layer = layer + 1
# 计算新的损失尺度值 new_loss_scale它是当前层次的动态损失尺度乘以更新比例 update_ratio 的结果
new_loss_scale = self.dynamic_loss_scale[layer] * update_ratio
# 使用 P.Assign() 操作将新的损失尺度值 new_loss_scale 赋值给当前层次的动态损失尺度
P.Assign()(self.dynamic_loss_scale[layer], new_loss_scale)
# 返回新的损失尺度值 new_loss_scale用于后续的损失尺度管理
return new_loss_scale
def construct(self, x, layer1, layer2):
x = self.layer_loss_scale[layer1](x, self.dynamic_loss_scale[layer1] / self.dynamic_loss_scale[layer2])
return x
def get_loss_scale(self):
"""
Get loss scale value.
获取损失规模值
Returns:
bool, `loss_scale` value.
"""
return self._loss_scale
def get_update_cell(self):
"""
Returns the instance of :class:`mindspore.boost.GroupLossScaleManager`.
返回class:`mindspore.boost.GroupLossScaleManager`的实例
Returns:
:class:`mindspore.boost.GroupLossScaleManager`.
"""
return self

View File

@ -0,0 +1,68 @@
/**
* 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_declare/hcom_ops_declare.h"
#include <string>
namespace mindspore::transform {
// HCOMAllreduce
INPUT_MAP(HcomAllReduce) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
OUTPUT_MAP(HcomAllReduce) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
ATTR_MAP(HcomAllReduce) = {{"op", ATTR_DESC(reduction, AnyTraits<std::string>())},
{"group", ATTR_DESC(group, AnyTraits<std::string>())},
{"fusion", ATTR_DESC(fusion, AnyTraits<int64_t>())}};
//属性映射属性op类型为string属性group类型为string属性fusion类型为int64_t
REG_ADPT_DESC(HcomAllReduce, kNameAllReduce, ADPT_DESC(HcomAllReduce))
//注册HcomAllReduce操作的适配器描述kNameAllReduce返回的name变量
// HCOMBraodcast
INPUT_MAP(HcomBroadcast) = EMPTY_INPUT_MAP;
//输入映射,设为空
DYN_INPUT_MAP(HcomBroadcast) = {{1, DYN_INPUT_DESC(x)}};
//动态输入映射将索引为1的动态输入与名称为x的动态输入描述关联起来用于后续操作
DYN_OUTPUT_MAP(HcomBroadcast) = {{0, DYN_OUTPUT_DESC(y)}};
//动态输出映射将索引为0的动态输出与名称为y的动态输出描述关联起来用于后续操作
ATTR_MAP(HcomBroadcast) = {{"root_rank", ATTR_DESC(root_rank, AnyTraits<int64_t>())},
{"group", ATTR_DESC(group, AnyTraits<std::string>())}};
//属性映射属性root_rank类型为int64_t属性group类型为string
REG_ADPT_DESC(HcomBroadcast, kNameBroadcast, ADPT_DESC(HcomBroadcast))
//注册HcomBroadcast操作的适配器描述kNameBroadcast返回的name变量
// HcomAllGather
INPUT_MAP(HcomAllGather) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
OUTPUT_MAP(HcomAllGather) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
ATTR_MAP(HcomAllGather) = {{"group", ATTR_DESC(group, AnyTraits<std::string>())},
{"rank_size", ATTR_DESC(rank_size, AnyTraits<int64_t>())}};
//属性映射属性group类型为string属性rank_size类型为int64_t
REG_ADPT_DESC(HcomAllGather, kNameAllgather, ADPT_DESC(HcomAllGather))
//注册HcomAllGather操作的适配器描述kNameAllgather返回的name变量
// HCOMReduceScatter
INPUT_MAP(HcomReduceScatter) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
OUTPUT_MAP(HcomReduceScatter) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
ATTR_MAP(HcomReduceScatter) = {{"group", ATTR_DESC(group, AnyTraits<std::string>())},
{"op", ATTR_DESC(reduction, AnyTraits<std::string>())},
{"rank_size", ATTR_DESC(rank_size, AnyTraits<int64_t>())}};
//属性映射属性group类型为string属性op类型为string>属性rank_size类型为int64_t
REG_ADPT_DESC(HcomReduceScatter, kNameReduceScatter, ADPT_DESC(HcomReduceScatter))
//注册HcomReduceScatter操作的适配器描述kNameReduceScatter返回的name变量
} // namespace mindspore::transform

View File

@ -0,0 +1,88 @@
/**
* 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_declare/image_ops_declare.h"
#include <vector>
#include <string>
namespace mindspore::transform {
// ResizeNearestNeighborV2D
INPUT_MAP(ResizeNearestNeighborV2D) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(ResizeNearestNeighborV2D) = {
{"size", ATTR_DESC(size, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"align_corners", ATTR_DESC(align_corners, AnyTraits<bool>())}};
//属性映射属性size类型为int64_t属性align_corners类型为bool
OUTPUT_MAP(ResizeNearestNeighborV2D) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(ResizeNearestNeighborV2D, kNameResizeNearestNeighborD, ADPT_DESC(ResizeNearestNeighborV2D))
//注册ResizeNearestNeighborV2D操作的适配器描述kNameResizeNearestNeighborVD
// ResizeNearestNeighborV2
INPUT_MAP(ResizeNearestNeighborV2) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(size)}};
//输入映射x索引为1size索引为2
ATTR_MAP(ResizeNearestNeighborV2) = {{"align_corners", ATTR_DESC(align_corners, AnyTraits<bool>())},
{"half_pixel_centers", ATTR_DESC(half_pixel_centers, AnyTraits<bool>())}};
//属性映射属性align_corners类型为bool属性half_pixel_centers类型为bool
OUTPUT_MAP(ResizeNearestNeighborV2) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(ResizeNearestNeighborV2, kNameResizeNearestNeighborV2, ADPT_DESC(ResizeNearestNeighborV2))
//注册ResizeNearestNeighborV2操作的适配器描述kNameResizeNearestNeighborV2
// ResizeNearestNeighborV2Grad
INPUT_MAP(ResizeNearestNeighborV2Grad) = {{1, INPUT_DESC(grads)}, {2, INPUT_DESC(size)}};
//输入映射grads索引为1size索引为2
ATTR_MAP(ResizeNearestNeighborV2Grad) = {{"align_corners", ATTR_DESC(align_corners, AnyTraits<bool>())}};
//属性映射属性align_corners类型为bool
OUTPUT_MAP(ResizeNearestNeighborV2Grad) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(ResizeNearestNeighborV2Grad, kNameResizeNearestNeighborGrad, ADPT_DESC(ResizeNearestNeighborV2Grad))
//注册ResizeNearestNeighborV2Grad操作的适配器描述kNameResizeNearestNeighborGrad
// ResizeBilinearV2Grad
INPUT_MAP(ResizeBilinearV2Grad) = {{1, INPUT_DESC(grads)}, {2, INPUT_DESC(original_image)}};
//输入映射grads索引为1original_image索引为2
ATTR_MAP(ResizeBilinearV2Grad) = {{"align_corners", ATTR_DESC(align_corners, AnyTraits<bool>())}};
//属性映射属性align_corners类型为bool
OUTPUT_MAP(ResizeBilinearV2Grad) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(ResizeBilinearV2Grad, kNameResizeBilinearGrad, ADPT_DESC(ResizeBilinearV2Grad))
//注册ResizeBilinearV2Grad操作的适配器描述kNameResizeBilinearV2Grad
// ResizeBilinearV2
INPUT_MAP(ResizeBilinearV2) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(size)}};
//输入映射x索引为1size索引为2
ATTR_MAP(ResizeBilinearV2) = {{"align_corners", ATTR_DESC(align_corners, AnyTraits<bool>())}};
//属性映射属性align_corners类型为bool
OUTPUT_MAP(ResizeBilinearV2) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(ResizeBilinearV2, kNameResizeBilinear, ADPT_DESC(ResizeBilinearV2))
//注册ResizeBilinearV2操作的适配器描述kNameResizeBilinearV2
REG_ADPT_DESC(ResizeBilinearV2New, kNameResizeBilinearV2, ADPT_DESC(ResizeBilinearV2))
//注册ResizeBilinearV2New操作的适配器描述kNameResizeBilinearV2
// CropAndResize
INPUT_MAP(CropAndResize) = {
{1, INPUT_DESC(x)}, {2, INPUT_DESC(boxes)}, {3, INPUT_DESC(box_index)}, {4, INPUT_DESC(crop_size)}};
//输入映射x索引为1boxes索引为2box_index索引为3crop_size索引为4
ATTR_MAP(CropAndResize) = {{"extrapolation_value", ATTR_DESC(extrapolation_value, AnyTraits<float>())},
{"method", ATTR_DESC(method, AnyTraits<std::string>())}};
//属性映射属性extrapolation_value类型为float属性method类型为string
OUTPUT_MAP(CropAndResize) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(CropAndResize, kNameCropAndResize, ADPT_DESC(CropAndResize))
//注册CropAndResize操作的适配器描述kNameCropAndResize
} // namespace mindspore::transform

View File

@ -0,0 +1,46 @@
/**
* Copyright 2021 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/io_format_map.h"
namespace mindspore {
namespace transform {
// 定义一个名为 'IOFormatMap' 的类
// 静态成员变量 'io_format_map_',用于存储操作名称与其输入输出格式之间的映射关系
// 定义 'io_format_map_' 映射的初始化值
mindspore::HashMap<std::string, std::string> IOFormatMap::io_format_map_ = {{"BasicLSTMCell", "ND"},
{"BasicLSTMCellInputGrad", "ND"},
{"BasicLSTMCellCStateGrad", "ND"},
{"Dequant", "ND"},
{"DynamicGRUV2", "ND"},
{"DynamicGRUV2Grad", "ND"},
{"DynamicRNN", "ND"},
{"DynamicRNNGrad", "ND"},
{"MatMul", "ND"},
{"BatchMatMul", "ND"},
{"BatchMatMulV2", "ND"},
{"Quant", "ND"},
{"BasicLSTMCellWeightGrad", "HWCN"},
{"ExtractImagePatches", "NCHW"},
{"Conv3D", "format"},
{"MaxPool3D", "NCDHW"},
{"Conv3DBackpropFilter", "format"},
{"Conv3DBackpropInput", "format"},
{"Conv3DTranspose", "format"}};
// 静态成员函数 'get()',用于获取 'io_format_map_' 映射
mindspore::HashMap<std::string, std::string> &IOFormatMap::get() { return io_format_map_; }
} // namespace transform
} // namespace mindspore

View File

@ -0,0 +1,172 @@
# Copyright 2021 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.
# ============================================================================
"""less Batch Normalization"""
# 导入必要的库和模块
import numpy as np
from mindspore.nn.cell import Cell
from mindspore.nn.layer import Dense
from mindspore.ops import operations as P
from mindspore.common import Tensor, Parameter
from mindspore.common import dtype as mstype
from mindspore.common.initializer import initializer
__all__ = ["CommonHeadLastFN", "LessBN"]
# 定义LessBN模块包括两个类CommonHeadLastFN和LessBN
# 这两个类用于自动减少Batch NormalizationBN以提高网络性能并保持网络准确性。
# 定义一个名为CommonHeadLastFN的类用于最后一层的全连接操作
class CommonHeadLastFN(Cell):
r"""
The last full Normalization layer.
This layer implements the operation as:
.. math::
\text{inputs} = \text{norm}(\text{inputs})
\text{kernel} = \text{norm}(\text{kernel})
\text{outputs} = \text{multiplier} * (\text{inputs} * \text{kernel} + \text{bias}),
Args:
in_channels (int): The number of channels in the input space.
out_channels (int): The number of channels in the output space.
weight_init (Union[Tensor, str, Initializer, numbers.Number]): The trainable weight_init parameter. The dtype
is same as input x. The values of str refer to the function `initializer`. Default: 'normal'.
bias_init (Union[Tensor, str, Initializer, numbers.Number]): The trainable bias_init parameter. The dtype is
same as input x. The values of str refer to the function `initializer`. Default: 'zeros'.
has_bias (bool): Specifies whether the layer uses a bias vector. Default: True.
Supported Platforms:
``Ascend`` ``GPU`` ``CPU``
Examples:
>>> input = Tensor(np.array([[180, 234, 154], [244, 48, 247]]), mindspore.float32)
>>> net = CommonHeadLastFN(3, 4)
>>> output = net(input)
"""
def __init__(self,
in_channels,
out_channels,
weight_init='normal',
bias_init='zeros',
has_bias=True):
super(CommonHeadLastFN, self).__init__()
# 初始化权重参数
weight_shape = [out_channels, in_channels]
self.weight = Parameter(initializer(weight_init, weight_shape), requires_grad=True, name='weight')
# 定义L2范数归一化操作分别应用于输入x和权重kernel
self.x_norm = P.L2Normalize(axis=1)
self.w_norm = P.L2Normalize(axis=1)
# 定义矩阵相乘操作用于计算x和w的乘积
self.fc = P.MatMul(transpose_a=False, transpose_b=True)
# 初始化乘子参数
self.multiplier = Parameter(Tensor(np.ones([1]), mstype.float32), requires_grad=True, name='multiplier')
# 是否使用偏置项
self.has_bias = has_bias
if self.has_bias:
# 如果使用偏置项,初始化偏置参数
bias_shape = [out_channels]
self.bias_add = P.BiasAdd()
self.bias = Parameter(initializer(bias_init, bias_shape), requires_grad=True, name='bias')
def construct(self, x):
# 对输入x进行L2范数归一化
x = self.x_norm(x)
# 对权重kernel进行L2范数归一化
w = self.w_norm(self.weight)
# 计算x和w的矩阵相乘
x = self.fc(x, w)
if self.has_bias:
# 如果使用偏置项将偏置项添加到x中
x = self.bias_add(x, self.bias)
# 乘以乘子参数
x = self.multiplier * x
# 返回结果
return x
# 定义LessBN类用于自动减少Batch NormalizationBN以提高网络性能并保持准确性
class LessBN(Cell):
"""
Reduce the number of BN automatically to improve the network performance
and ensure the network accuracy.
Args:
network (Cell): Network to be modified.
fn_flag (bool): Replace FC with FN. default: False.
Examples:
>>> network = boost.LessBN(network)
"""
def __init__(self, network, fn_flag=False):
super(LessBN, self).__init__()
# 存储传入的网络
self.network = network
# 设置网络的"less_bn"属性
self.network.set_boost("less_bn")
# 更新网络的单元前缀
self.network.update_cell_prefix()
# 如果fn_flag为True将网络中的全连接层替换为FN层
if fn_flag:
self._convert_to_less_bn_net(self.network)
# 添加延迟内联标志,将网络的部分操作延迟到运行时执行
self.network.add_flags(defer_inline=True)
def _convert_dense(self, subcell):
"""
convert dense cell to FN cell
"""
prefix = subcell.param_prefix
# 创建新的FN层参数与原始全连接层相同
new_subcell = CommonHeadLastFN(subcell.in_channels,
subcell.out_channels,
subcell.weight,
subcell.bias,
False)
new_subcell.update_parameters_name(prefix + '.')
return new_subcell
def _convert_to_less_bn_net(self, net):
"""
convert network to less_bn network
"""
cells = net.name_cells()
dense_name = []
dense_list = []
# 遍历网络的所有单元
for name in cells:
subcell = cells[name]
if subcell == net:
continue
elif isinstance(subcell, (Dense)):
# 如果单元是全连接层,记录其名称和实例
dense_name.append(name)
dense_list.append(subcell)
else:
# 递归调用,继续查找子单元中的全连接层
self._convert_to_less_bn_net(subcell)
if dense_list:
# 如果存在全连接层将最后一个全连接层替换为FN层
new_subcell = self._convert_dense(dense_list[-1])
net.insert_child_to_cell(dense_name[-1], new_subcell)
def construct(self, *inputs):
# 前向传播方法,将输入传递给网络并返回结果
return self.network(*inputs)

View File

@ -0,0 +1,38 @@
/**
* 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_declare/logging_ops_declare.h"
namespace mindspore::transform {
// Print
INPUT_MAP(Print) = EMPTY_INPUT_MAP;
//输入映射,设为空
DYN_INPUT_MAP(Print) = {{1, DYN_INPUT_DESC(x)}};
//动态输入映射将索引为1的动态输入与名称为x的动态输入描述关联起来用于后续操作
ATTR_MAP(Print) = EMPTY_ATTR_MAP;
//属性映射,设为空
REG_ADPT_DESC(Print, kNamePrint, ADPT_DESC(Print))
//注册Print操作的适配器描述kNamePrint
INPUT_MAP(Assert) = {{1, INPUT_DESC(input_condition)}};
//输入映射input_condition索引为1
DYN_INPUT_MAP(Assert) = {{2, DYN_INPUT_DESC(input_data)}};
//动态输入映射将索引为2的动态输入与名称为input_data的动态输入描述关联起来用于后续操作
ATTR_MAP(Assert) = {{"summarize", ATTR_DESC(summarize, AnyTraits<int64_t>())}};
//属性映射属性summarize类型为int64_t
REG_ADPT_DESC(Assert, kNameAssert, ADPT_DESC(Assert))
//注册Assert操作的适配器描述kNameAssert
} // namespace mindspore::transform

View File

@ -0,0 +1,168 @@
/**
* Copyright 2021 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_declare/math_ops_declare.h"
#include <vector>
#include <string>
namespace mindspore::transform {
// ActsULQ
INPUT_MAP(ActsULQ) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(clamp_min)}, {3, INPUT_DESC(clamp_max)}};
//输入映射x索引为1clamp_min索引为2clamp_max索引为3
ATTR_MAP(ActsULQ) = {{"fixed_min", ATTR_DESC(fixed_min, AnyTraits<bool>())},
{"num_bits", ATTR_DESC(num_bits, AnyTraits<int64_t>())}};
//属性映射属性fixed_min类型为bool属性num_bits类型为int64_t
OUTPUT_MAP(ActsULQ) = {{0, OUTPUT_DESC(y)},
{1, OUTPUT_DESC(clamp_min_mask)},
{2, OUTPUT_DESC(clamp_max_mask)},
{3, OUTPUT_DESC(x_clamped_loss)}};
//输出映射y索引为0clamp_min_mask索引为1clamp_max_mask索引为2x_clamped_loss索引为3
REG_ADPT_DESC(ActsULQ, kNameActsULQ, ADPT_DESC(ActsULQ))
//注册ActsULQ操作的适配器描述kNameActsULQ
// ActsULQInputGrad
INPUT_MAP(ActsULQInputGrad) = {
{1, INPUT_DESC(y_grad)}, {2, INPUT_DESC(clamp_min_mask)}, {3, INPUT_DESC(clamp_max_mask)}};
//输入映射y_grad索引为1clamp_min_mask索引为2clamp_max_mask索引为3
ATTR_MAP(ActsULQInputGrad) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(ActsULQInputGrad) = {{0, OUTPUT_DESC(x_grad)}};
//输出映射x_grad索引为0
REG_ADPT_DESC(ActsULQInputGrad, kNameActsULQInputGrad, ADPT_DESC(ActsULQInputGrad))
//注册ActsULQInputGrad操作的适配器描述kNameActsULQInputGrad
// ActULQClampMaxGrad
INPUT_MAP(ActULQClampMaxGrad) = {
{1, INPUT_DESC(y_grad)}, {2, INPUT_DESC(clamp_max_mask)}, {3, INPUT_DESC(x_clamped_loss)}};
//输入映射y_grad索引为1clamp_max_mask索引为2x_clamped_loss索引为3
ATTR_MAP(ActULQClampMaxGrad) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(ActULQClampMaxGrad) = {{0, OUTPUT_DESC(clamp_max_grad)}};
//输出映射clamp_max_grad索引为0
REG_ADPT_DESC(ActULQClampMaxGrad, kNameActULQClampMaxGrad, ADPT_DESC(ActULQClampMaxGrad))
//注册ActsULQClampMaxGrad操作的适配器描述kNameActsULQClampMaxGrad
// ActULQClampMinGrad
INPUT_MAP(ActULQClampMinGrad) = {
{1, INPUT_DESC(y_grad)}, {2, INPUT_DESC(clamp_min_mask)}, {3, INPUT_DESC(x_clamped_loss)}};
//输入映射y_grad索引为1clamp__min_mask索引为2x_clamped_loss索引为3
ATTR_MAP(ActULQClampMinGrad) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(ActULQClampMinGrad) = {{0, OUTPUT_DESC(clamp_min_grad)}};
//输出映射clamp_min_grad索引为0
REG_ADPT_DESC(ActULQClampMinGrad, kNameActULQClampMinGrad, ADPT_DESC(ActULQClampMinGrad))
//注册ActsULQClampMinGrad操作的适配器描述kNameActsULQClampMinGrad
// HistogramFixedWidthD
INPUT_MAP(HistogramFixedWidthD) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(range)}};
//输入映射x索引为1range)索引为2
ATTR_MAP(HistogramFixedWidthD) = {{"nbins", ATTR_DESC(nbins, AnyTraits<int64_t>())},
{"dtype", ATTR_DESC(dtype, AnyTraits<int64_t>())}};
//属性映射属性nbins类型为int64_t属性dtype类型为int64_t
OUTPUT_MAP(HistogramFixedWidthD) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(HistogramFixedWidthD, kNameHistogramFixedWidthD, ADPT_DESC(HistogramFixedWidthD))
//注册HistogramFixedWidthD操作的适配器描述kNameHistogramFixedWidthD
// IFMR
INPUT_MAP(IFMR) = {
{1, INPUT_DESC(data)}, {2, INPUT_DESC(data_min)}, {3, INPUT_DESC(data_max)}, {4, INPUT_DESC(cumsum)}};
//输入映射data索引为1data_min索引为2data_max索引为3cumsum索引为4
ATTR_MAP(IFMR) = {{"min_percentile", ATTR_DESC(min_percentile, AnyTraits<float>())},
{"max_percentile", ATTR_DESC(max_percentile, AnyTraits<float>())},
{"search_range", ATTR_DESC(search_range, AnyTraits<std::vector<float>>())},
{"search_step", ATTR_DESC(search_step, AnyTraits<float>())}};
//属性映射属性min_percentile类型为float属性max_percentile类型为float属性search_range类型为float属性search_step类型为float
OUTPUT_MAP(IFMR) = {{0, OUTPUT_DESC(scale)}, {1, OUTPUT_DESC(offset)}};
//输出映射scale索引为0offset索引为1
REG_ADPT_DESC(IFMR, kNameIFMR, ADPT_DESC(IFMR))
//注册IFMR操作的适配器描述kNameIFMR
// NLLLoss
INPUT_MAP(NLLLoss) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(target)}, {3, INPUT_DESC(weight)}};
//输入映射x索引为1target索引为2weight索引为3
ATTR_MAP(NLLLoss) = {{"reduction", ATTR_DESC(reduction, AnyTraits<std::string>())}};
//属性映射属性reduction类型为string
OUTPUT_MAP(NLLLoss) = {{0, OUTPUT_DESC(y)}, {1, OUTPUT_DESC(total_weight)}};
//输出映射y索引为0total_weight索引为1
REG_ADPT_DESC(NLLLoss, kNameNLLLoss, ADPT_DESC(NLLLoss))
//注册NLLLoss操作的适配器描述kNameNLLLoss
// NLLLossGrad
INPUT_MAP(NLLLossGrad) = {{1, INPUT_DESC(x)},
{2, INPUT_DESC(y_grad)},
{3, INPUT_DESC(target)},
{4, INPUT_DESC(weight)},
{5, INPUT_DESC(total_weight)}};
//输入映射x索引为1y_grad索引为2target索引为3weight索引为4total_weight索引为5
ATTR_MAP(NLLLossGrad) = {{"reduction", ATTR_DESC(reduction, AnyTraits<std::string>())}};
//属性映射属性reduction类型为string
OUTPUT_MAP(NLLLossGrad) = {{0, OUTPUT_DESC(x_grad)}};
//输出映射x_grad索引为0
REG_ADPT_DESC(NLLLossGrad, kNameNLLLossGrad, ADPT_DESC(NLLLossGrad))
//注册NLLLosGrad操作的适配器描述kNameNLLLossGrad
// Erf
INPUT_MAP(Erf) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(Erf) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(Erf) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Erf, kNameErf, ADPT_DESC(Erf))
//注册Erf操作的适配器描述kNameErf
// Erfc
INPUT_MAP(Erfc) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(Erfc) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(Erfc) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Erfc, kNameErfc, ADPT_DESC(Erfc))
//注册Erfc操作的适配器描述kNameErfc
// WtsARQ
INPUT_MAP(WtsARQ) = {{1, INPUT_DESC(w)}, {2, INPUT_DESC(w_min)}, {3, INPUT_DESC(w_max)}};
//输入映射x索引为1w_min索引为2w_max索引为3
ATTR_MAP(WtsARQ) = {{"num_bits", ATTR_DESC(num_bits, AnyTraits<int64_t>())},
{"offset_flag", ATTR_DESC(offset_flag, AnyTraits<bool>())}};
//输入映射num_bits索引为1offset_flag索引为2
OUTPUT_MAP(WtsARQ) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(WtsARQ, kNameWtsARQ, ADPT_DESC(WtsARQ))
//注册WtsARQ操作的适配器描述kNameWtsARQ
// IsFinite
INPUT_MAP(IsFinite) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(IsFinite) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(IsFinite) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(IsFinite, kNameIsFinite, ADPT_DESC(IsFinite))
//注册IsFinite操作的适配器描述kNameIsFinite
// IsNan
INPUT_MAP(IsNan) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(IsNan) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(IsNan) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(IsNan, kNameIsNan, ADPT_DESC(IsNan))
//注册IsNan操作的适配器描述kNameIsNan
} // namespace mindspore::transform

View File

@ -0,0 +1,160 @@
/**
* Copyright 2019-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 "transform/graph_ir/op_declare/matrix_calculation_ops_declare.h"
namespace mindspore::transform {
// TensorScatterUpdate
INPUT_MAP(TensorScatterUpdate) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(updates)}};
ATTR_MAP(TensorScatterUpdate) = EMPTY_ATTR_MAP;
OUTPUT_MAP(TensorScatterUpdate) = {{0, OUTPUT_DESC(y)}};
REG_ADPT_DESC(TensorScatterUpdate, kNameTensorScatterUpdate, ADPT_DESC(TensorScatterUpdate))
// ScatterUpdate
INPUT_MAP(ScatterUpdate) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(updates)}};
ATTR_MAP(ScatterUpdate) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
OUTPUT_MAP(ScatterUpdate) = {{0, OUTPUT_DESC(var)}};
REG_ADPT_DESC(ScatterUpdate, kNameScatterUpdate, ADPT_DESC(ScatterUpdate))
// ScatterNdUpdate
INPUT_MAP(ScatterNdUpdate) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(updates)}};
ATTR_MAP(ScatterNdUpdate) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
OUTPUT_MAP(ScatterNdUpdate) = {{0, OUTPUT_DESC(var)}};
REG_ADPT_DESC(ScatterNdUpdate, kNameScatterNdUpdate, ADPT_DESC(ScatterNdUpdate))
// ScatterMax
INPUT_MAP(ScatterMax) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(updates)}};
ATTR_MAP(ScatterMax) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
OUTPUT_MAP(ScatterMax) = {{0, OUTPUT_DESC(var)}};
REG_ADPT_DESC(ScatterMax, kNameScatterMax, ADPT_DESC(ScatterMax))
// ScatterMin
INPUT_MAP(ScatterMin) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(updates)}};
ATTR_MAP(ScatterMin) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
OUTPUT_MAP(ScatterMin) = {{0, OUTPUT_DESC(var)}};
REG_ADPT_DESC(ScatterMin, kNameScatterMin, ADPT_DESC(ScatterMin))
// ScatterAdd
INPUT_MAP(ScatterAdd) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(updates)}};
ATTR_MAP(ScatterAdd) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
OUTPUT_MAP(ScatterAdd) = {{0, OUTPUT_DESC(var)}};
REG_ADPT_DESC(ScatterAdd, kNameScatterAdd, ADPT_DESC(ScatterAdd))
// ScatterSub
INPUT_MAP(ScatterSub) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(updates)}};
ATTR_MAP(ScatterSub) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
OUTPUT_MAP(ScatterSub) = {{0, OUTPUT_DESC(var)}};
REG_ADPT_DESC(ScatterSub, kNameScatterSub, ADPT_DESC(ScatterSub))
// ScatterMul
INPUT_MAP(ScatterMul) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(updates)}};
ATTR_MAP(ScatterMul) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
OUTPUT_MAP(ScatterMul) = {{0, OUTPUT_DESC(var)}};
REG_ADPT_DESC(ScatterMul, kNameScatterMul, ADPT_DESC(ScatterMul))
// ScatterDiv
INPUT_MAP(ScatterDiv) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(updates)}};
ATTR_MAP(ScatterDiv) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
OUTPUT_MAP(ScatterDiv) = {{0, OUTPUT_DESC(var)}};
REG_ADPT_DESC(ScatterDiv, kNameScatterDiv, ADPT_DESC(ScatterDiv))
// ScatterNdAdd
INPUT_MAP(ScatterNdAdd) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(updates)}};
ATTR_MAP(ScatterNdAdd) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
OUTPUT_MAP(ScatterNdAdd) = {{0, OUTPUT_DESC(var)}};
REG_ADPT_DESC(ScatterNdAdd, kNameScatterNdAdd, ADPT_DESC(ScatterNdAdd))
// ScatterNdSub
INPUT_MAP(ScatterNdSub) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(updates)}};
ATTR_MAP(ScatterNdSub) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
OUTPUT_MAP(ScatterNdSub) = {{0, OUTPUT_DESC(var)}};
REG_ADPT_DESC(ScatterNdSub, kNameScatterNdSub, ADPT_DESC(ScatterNdSub))
// MatMul
INPUT_MAP(MatMul) = {{1, INPUT_DESC(x1)}, {2, INPUT_DESC(x2)}, {3, INPUT_DESC(bias)}};
ATTR_MAP(MatMul) = {{"transpose_x1", ATTR_DESC(transpose_x1, AnyTraits<bool>())},
{"transpose_x2", ATTR_DESC(transpose_x2, AnyTraits<bool>())}};
OUTPUT_MAP(MatMul) = {{0, OUTPUT_DESC(y)}};
REG_ADPT_DESC(MatMul, kNameMatMul, ADPT_DESC(MatMul))
// MatMulV2
INPUT_MAP(MatMulV2) = {{1, INPUT_DESC(x1)}, {2, INPUT_DESC(x2)}, {3, INPUT_DESC(bias)}};
ATTR_MAP(MatMulV2) = {{"transpose_a", ATTR_DESC(transpose_x1, AnyTraits<bool>())},
{"transpose_b", ATTR_DESC(transpose_x2, AnyTraits<bool>())}};
OUTPUT_MAP(MatMulV2) = {{0, OUTPUT_DESC(y)}};
REG_ADPT_DESC(MatMulV2, prim::kPrimMatMul->name(), ADPT_DESC(MatMulV2))
// MatrixDiag
INPUT_MAP(MatrixDiag) = {{1, INPUT_DESC(x)}};
ATTR_MAP(MatrixDiag) = EMPTY_ATTR_MAP;
OUTPUT_MAP(MatrixDiag) = {{0, OUTPUT_DESC(y)}};
REG_ADPT_DESC(MatrixDiag, kNameMatrixDiagD, ADPT_DESC(MatrixDiag))
// MatrixDiagPartD
INPUT_MAP(MatrixDiagPartD) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(assist)}};
ATTR_MAP(MatrixDiagPartD) = EMPTY_ATTR_MAP;
OUTPUT_MAP(MatrixDiagPartD) = {{0, OUTPUT_DESC(y)}};
REG_ADPT_DESC(MatrixDiagPartD, kNameMatrixDiagPartD, ADPT_DESC(MatrixDiagPartD))
// MatrixSetDiagD
INPUT_MAP(MatrixSetDiagD) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(diagonal)}, {3, INPUT_DESC(assist)}};
ATTR_MAP(MatrixSetDiagD) = EMPTY_ATTR_MAP;
OUTPUT_MAP(MatrixSetDiagD) = {{0, OUTPUT_DESC(y)}};
REG_ADPT_DESC(MatrixSetDiagD, kNameMatrixSetDiagD, ADPT_DESC(MatrixSetDiagD))
// DiagPart
INPUT_MAP(DiagPart) = {{1, INPUT_DESC(x)}};
ATTR_MAP(DiagPart) = EMPTY_ATTR_MAP;
OUTPUT_MAP(DiagPart) = {{0, OUTPUT_DESC(y)}};
REG_ADPT_DESC(DiagPart, kNameDiagPart, ADPT_DESC(DiagPart))
// BatchMatMul
INPUT_MAP(BatchMatMul) = {{1, INPUT_DESC(x1)}, {2, INPUT_DESC(x2)}};
ATTR_MAP(BatchMatMul) = {{"transpose_x1", ATTR_DESC(adj_x1, AnyTraits<bool>())},
{"transpose_x2", ATTR_DESC(adj_x2, AnyTraits<bool>())}};
OUTPUT_MAP(BatchMatMul) = {{0, OUTPUT_DESC(y)}};
// BatchMatMul->BatchMatMulV2
INPUT_MAP(BatchMatMulV2) = {{1, INPUT_DESC(x1)}, {2, INPUT_DESC(x2)}};
ATTR_MAP(BatchMatMulV2) = {{"transpose_x1", ATTR_DESC(adj_x1, AnyTraits<bool>())},
{"transpose_x2", ATTR_DESC(adj_x2, AnyTraits<bool>())}};
OUTPUT_MAP(BatchMatMulV2) = {{0, OUTPUT_DESC(y)}};
REG_ADPT_DESC(BatchMatMul, kNameBatchMatMul, ADPT_DESC(BatchMatMul))
REG_ADPT_DESC(BatchMatMulV2, kNameBatchMatMulV2, ADPT_DESC(BatchMatMulV2))
// L2Loss
INPUT_MAP(L2Loss) = {{1, INPUT_DESC(x)}};
ATTR_MAP(L2Loss) = EMPTY_ATTR_MAP;
OUTPUT_MAP(L2Loss) = {{0, OUTPUT_DESC(y)}};
REG_ADPT_DESC(L2Loss, kNameL2Loss, ADPT_DESC(L2Loss))
// ScatterElements
INPUT_MAP(ScatterElements) = {{1, INPUT_DESC(data)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(updates)}};
ATTR_MAP(ScatterElements) = {{"axis", ATTR_DESC(axis, AnyTraits<int64_t>())}};
OUTPUT_MAP(ScatterElements) = {{0, OUTPUT_DESC(y)}};
REG_ADPT_DESC(ScatterElements, kNameTensorScatterElements, ADPT_DESC(ScatterElements))
// FullyConnection
INPUT_MAP(FullyConnection) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(w)}, {3, INPUT_DESC(b)}, {4, INPUT_DESC(offset_w)}};
ATTR_MAP(FullyConnection) = {{"num_output", ATTR_DESC(num_output, AnyTraits<int64_t>())},
{"transpose", ATTR_DESC(transpose, AnyTraits<bool>())},
{"axis", ATTR_DESC(axis, AnyTraits<int64_t>())},
{"offset_x", ATTR_DESC(offset_x, AnyTraits<int64_t>())}};
OUTPUT_MAP(FullyConnection) = {{0, OUTPUT_DESC(y)}};
REG_ADPT_DESC(FullyConnection, kNameFullConnection, ADPT_DESC(FullyConnection))
} // namespace mindspore::transform

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,99 @@
/**
* 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_declare/nn_batch_norm_ops_declare.h"
#include <vector>
#include <string>
namespace mindspore::transform {
// BatchNorm
INPUT_MAP(BatchNorm) = {{1, INPUT_DESC(x)},
{2, INPUT_DESC(scale)},
{3, INPUT_DESC(offset)},
{4, INPUT_DESC(mean)},
{5, INPUT_DESC(variance)}};
//输入映射x索引为1scale索引为2offset索引为3mean索引为4variance索引为5
ATTR_MAP(BatchNorm) = {{"format", ATTR_DESC(data_format, AnyTraits<std::string>())},
{"epsilon", ATTR_DESC(epsilon, AnyTraits<float>())},
{"is_training", ATTR_DESC(is_training, AnyTraits<bool>())}};
//属性映射属性format类型为string属性epsilon类型为float属性format类型为bool
OUTPUT_MAP(BatchNorm) = {{0, OUTPUT_DESC(y)},
{1, OUTPUT_DESC(batch_mean)},
{2, OUTPUT_DESC(batch_variance)},
{3, OUTPUT_DESC(reserve_space_1)},
{4, OUTPUT_DESC(reserve_space_2)}};
//输出映射y索引为0batch_mean索引为1batch_variance索引为2reserve_space_1索引为3reserve_space_2索引为4
// BNInference is BatchNorm for caffe
INPUT_MAP(BNInference) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(mean)}, {3, INPUT_DESC(variance)},
{4, INPUT_DESC(momentum)}, {5, INPUT_DESC(scale)}, {6, INPUT_DESC(offset)}};
//输入映射x索引为1mean索引为2variance索引为3momentum索引为4scale索引为5offset索引为5
ATTR_MAP(BNInference) = {{"epsilon", ATTR_DESC(epsilon, AnyTraits<float>())},
{"use_global_stats", ATTR_DESC(use_global_stats, AnyTraits<bool>())},
{"mode", ATTR_DESC(mode, AnyTraits<int64_t>())}};
//属性映射属性epsilon类型为float属性use_global_stats类型为bool属性mode类型为bool
OUTPUT_MAP(BNInference) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(BNInference, kNameBNInference, ADPT_DESC(BNInference))
//注册BNInference操作的适配器描述kNameBNInference
REG_ADPT_DESC(BatchNorm, kNameBatchNorm, ADPT_DESC(BatchNorm))
//注册BatchNorm操作的适配器描述kNameBatchNorm
REG_ADPT_DESC(FusedBatchNorm, kNameFusedBatchNorm, ADPT_DESC(BatchNorm))
//注册FusedBatchNorm操作的适配器描述kNameFusedBatchNorm
// BatchNormGrad
INPUT_MAP(BatchNormGrad) = {{1, INPUT_DESC(y_backprop)},
{2, INPUT_DESC(x)},
{3, INPUT_DESC(scale)},
{4, INPUT_DESC(reserve_space_1)},
{5, INPUT_DESC(reserve_space_2)}};
//输入映射y_backprop索引为1x索引为2scale索引为3reserve_space_1索引为4reserve_space_2索引为5
ATTR_MAP(BatchNormGrad) = {{"format", ATTR_DESC(data_format, AnyTraits<std::string>())},
{"epsilon", ATTR_DESC(epsilon, AnyTraits<float>())},
{"is_training", ATTR_DESC(is_training, AnyTraits<bool>())}};
//属性映射属性format类型为string属性epsilon类型为float属性format类型为bool
OUTPUT_MAP(BatchNormGrad) = {{0, OUTPUT_DESC(x_backprop)},
{1, OUTPUT_DESC(scale_backprop)},
{2, OUTPUT_DESC(offset_backprop)},
{3, OUTPUT_DESC(reserve_space_4)},
{4, OUTPUT_DESC(reserve_space_5)}};
//输出映射x_backprop索引为0scale_backprop索引为1offset_backprop索引为2reserve_space_4索引为3reserve_space_5索引为4
REG_ADPT_DESC(BatchNormGrad, kNameBatchNormGrad, ADPT_DESC(BatchNormGrad))
//注册BatchNormGrad操作的适配器描述kNameBatchNormGrad
// L2NormalizeGrad
INPUT_MAP(L2NormalizeGrad) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(y)}, {3, INPUT_DESC(dy)}};
//输入映射x索引为1y索引为2dy索引为3
ATTR_MAP(L2NormalizeGrad) = {
{"axis", ATTR_DESC(dim, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"epsilon", ATTR_DESC(eps, AnyTraits<float>())}};
//属性映射属性axis类型为int64_t属性epsilon类型为float
OUTPUT_MAP(L2NormalizeGrad) = {{0, OUTPUT_DESC(dx)}};
//输出映射x_backprop索引为0
REG_ADPT_DESC(L2NormalizeGrad, kNameL2NormalizeGrad, ADPT_DESC(L2NormalizeGrad))
//注册L2NormalizeGrad操作的适配器描述kNameL2NormalizeGrad
// L2Normalize
INPUT_MAP(L2Normalize) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(L2Normalize) = {
{"axis", ATTR_DESC(axis, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"epsilon", ATTR_DESC(eps, AnyTraits<float>())}};
//属性映射属性axis类型为int64_t属性epsilon类型为float
OUTPUT_MAP(L2Normalize) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(L2Normalize, kNameL2Normalize, ADPT_DESC(L2Normalize))
//注册L2Normalize操作的适配器描述kNameL2Normalize
} // namespace mindspore::transform

View File

@ -0,0 +1,262 @@
/**
* 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_declare/nn_calculation_ops_declare.h"
#include <vector>
#include <string>
namespace mindspore::transform {
// BiasAddGrad
INPUT_MAP(BiasAddGrad) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(BiasAddGrad) = {{"format", ATTR_DESC(data_format, AnyTraits<std::string>())}};
//属性映射,属性format类型为string
OUTPUT_MAP(BiasAddGrad) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(BiasAddGrad, prim::kPrimBiasAddGrad->name(), ADPT_DESC(BiasAddGrad))
//注册BiasAddGrad操作的适配器描述kPrimBiasAddGrad返回的name变量
// Conv2D
INPUT_MAP(Conv2D) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(filter)}, {3, INPUT_DESC(bias)}};
//输入映射x索引为1filter索引为2bias索引为3
ATTR_MAP(Conv2D) = {
{"stride", ATTR_DESC(strides, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"pad_list", ATTR_DESC(pads, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"dilation", ATTR_DESC(dilations, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())},
{"group", ATTR_DESC(groups, AnyTraits<int64_t>())},
};
//属性映射属性stride类型为int64_t属性pad_list类型为int64_t属性dilations类型为int64_t属性format类型为string属性group类型为int64_t
OUTPUT_MAP(Conv2D) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Conv2D, prim::kPrimConv2D->name(), ADPT_DESC(Conv2D))
//注册Conv2D操作的适配器描述kPrimConv2D返回的name变量
// Conv2DBackpropInputD
INPUT_MAP(Conv2DBackpropInputD) = {{1, INPUT_DESC(out_backprop)}, {2, INPUT_DESC(filter)}};
//输入映射out_backprop索引为1filter索引为2
INPUT_ATTR_MAP(Conv2DBackpropInputD) = {
{3, ATTR_DESC(input_size, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
//输入属性映射将索引为3的输入与属性为input_size的变量相关联用于反卷积操作的输入属性映射
ATTR_MAP(Conv2DBackpropInputD) = {
{"pad_list", ATTR_DESC(pads, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"stride", ATTR_DESC(strides, AnyTraits<std::vector<int64_t>>())},
{"dilation", ATTR_DESC(dilations, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())},
{"group", ATTR_DESC(groups, AnyTraits<int64_t>())},
};
//属性映射属性pad_list类型为int64_t属性stride类型为int64_t属性dilations类型为int64_t属性format类型为string属性group类型为int64_t
OUTPUT_MAP(Conv2DBackpropInputD) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Conv2DBackpropInputD, prim::kPrimConv2DBackpropInput->name(), ADPT_DESC(Conv2DBackpropInputD))
//注册Conv2DBackpropInputD操作的适配器描述kPrimConv2DBackpropInput返回的name变量
// Conv2DBackpropInput for tf inference
INPUT_MAP(Conv2DBackpropInput) = {{1, INPUT_DESC(input_size)}, {2, INPUT_DESC(filter)}, {3, INPUT_DESC(out_backprop)}};
//输入映射input_size索引为1filter索引为2out_backprop索引为3
ATTR_MAP(Conv2DBackpropInput) = {
{"stride", ATTR_DESC(strides, AnyTraits<std::vector<int64_t>>())},
{"dilation", ATTR_DESC(dilations, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"pad_list", ATTR_DESC(pads, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"data_format", ATTR_DESC(data_format, AnyTraits<std::string>())},
};
//属性映射属性stride类型为int64_t属性pad_list类型为int64_t属性dilations类型为int64_t属性pad_list类型为int64_t属性data_format类型为string
OUTPUT_MAP(Conv2DBackpropInput) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Conv2DBackpropInput, kNameConv2DBackpropInputV2, ADPT_DESC(Conv2DBackpropInput))
//注册Conv2DBackpropInput操作的适配器描述kNameConv2DBackpropInputV2返回的name变量
// Deconvolution for caffe inference
INPUT_MAP(Deconvolution) = {
{1, INPUT_DESC(x)}, {2, INPUT_DESC(filter)}, {3, INPUT_DESC(bias)}, {4, INPUT_DESC(offset_w)}};
//输入映射x索引为1filter索引为2bias索引为3offset_w索引为4
ATTR_MAP(Deconvolution) = {
{"stride", ATTR_DESC(strides, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"pad_list", ATTR_DESC(pads, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"dilation", ATTR_DESC(dilations, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"group", ATTR_DESC(groups, AnyTraits<int64_t>())},
{"format", ATTR_DESC(data_format, AnyTraits<string>())},
{"offset", ATTR_DESC(offset_x, AnyTraits<int64_t>())}};
//属性映射属性stride类型为int64_t属性pad_list类型为int64_t属性dilations类型为int64_t
//属性groups类型为int64_t属性format类型为string属性offset类型为int64_t
OUTPUT_MAP(Deconvolution) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Deconvolution, kNameDeconvolution, ADPT_DESC(Deconvolution))
//注册Deconvolution操作的适配器描述kNameDeconvolution,返回的name变量
REG_ADPT_DESC(Conv2DTranspose, kConv2DTransposeOpName, ADPT_DESC(Conv2DBackpropInputD))
//注册Conv2DTranspose操作的适配器描述kConv2DTransposeOpName返回的name变量
// Conv2DTransposeD for tf onnx inference
INPUT_MAP(Conv2DTransposeD) = {
{1, INPUT_DESC(x)}, {2, INPUT_DESC(filter)}, {3, INPUT_DESC(bias)}, {4, INPUT_DESC(offset_w)}};
//输入映射x索引为1filter索引为2bias索引为3offset_w索引为4
ATTR_MAP(Conv2DTransposeD) = {
{"input_size", ATTR_DESC(input_size, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"stride", ATTR_DESC(strides, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"pad_list", ATTR_DESC(pads, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"dilation", ATTR_DESC(dilations, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"group", ATTR_DESC(groups, AnyTraits<int64_t>())},
{"data_format", ATTR_DESC(data_format, AnyTraits<string>())},
{"output_paddings", ATTR_DESC(output_padding, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"offset", ATTR_DESC(offset_x, AnyTraits<int64_t>())}};
//属性映射属性input_size类型为int64_t属性strides类型为int64_t属性pad_list类型为int64_t属性dilations类型为int64_t
//属性groups类型为int64_t属性data_format类型为string属性output_paddings类型为int64_t属性offset类型为int64_t
OUTPUT_MAP(Conv2DTransposeD) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Conv2DTransposeD, kNameConv2DTransposeD, ADPT_DESC(Conv2DTransposeD))
//注册Conv2DTransposeD操作的适配器描述kNameConv2DTransposeD返回的name变量
// Conv2DBackpropFilterD
INPUT_MAP(Conv2DBackpropFilterD) = {{1, INPUT_DESC(out_backprop)}, {2, INPUT_DESC(x)}};
//输入映射out_backprop索引为1x索引为2
INPUT_ATTR_MAP(Conv2DBackpropFilterD) = {
{3, ATTR_DESC(filter_size, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
ATTR_MAP(Conv2DBackpropFilterD) = {
{"pad_list", ATTR_DESC(pads, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"stride", ATTR_DESC(strides, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"dilation", ATTR_DESC(dilations, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())},
{"group", ATTR_DESC(groups, AnyTraits<int64_t>())},
};
//属性映射属性pad_list类型为int64_t属性stride类型为int64_t属性dilations类型为int64_t属性groups类型为int64_t属性group类型为int64_t
OUTPUT_MAP(Conv2DBackpropFilterD) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Conv2DBackpropFilterD, prim::kPrimConv2DBackpropFilter->name(), ADPT_DESC(Conv2DBackpropFilterD))
//注册Conv2DBackpropFilterD操作的适配器描述kPrimConv2DBackpropFilter返回的name变量
// Conv3DTransposeD
INPUT_MAP(Conv3DTransposeD) = {
{1, INPUT_DESC(x)}, {2, INPUT_DESC(filter)}, {3, INPUT_DESC(bias)}, {4, INPUT_DESC(offset_w)}};
//输入映射x索引为1filter索引为2bias索引为3offset_w索引为4
ATTR_MAP(Conv3DTransposeD) = {
{"input_size", ATTR_DESC(input_size, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"pad_list", ATTR_DESC(pads, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"dilations", ATTR_DESC(dilations, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"groups", ATTR_DESC(groups, AnyTraits<int64_t>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())},
{"output_padding", ATTR_DESC(output_padding, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
};
//属性映射属性input_size类型为int64_t属性strides类型为int64_t属性pad_list类型为int64_t属性dilations类型为int64_t
//属性groups类型为int64_t属性format类型为int64_t属性output_padding类型为int64_t
OUTPUT_MAP(Conv3DTransposeD) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Conv3DTransposeD, kNameConv3DTransposeD, ADPT_DESC(Conv3DTransposeD))
//注册Conv3DTransposeD操作的适配器描述kNameConv3DTransposeD返回的name变量
// Conv3D
INPUT_MAP(Conv3D) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(filter)}, {3, INPUT_DESC(bias)}, {4, INPUT_DESC(offset_w)}};
//输入映射x索引为1filter索引为2bias索引为3offset_w索引为4
ATTR_MAP(Conv3D) = {
{"strides", ATTR_DESC(strides, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"pad_list", ATTR_DESC(pads, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"dilations", ATTR_DESC(dilations, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"groups", ATTR_DESC(groups, AnyTraits<int64_t>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())},
{"offset_x", ATTR_DESC(offset_x, AnyTraits<int64_t>())},
};
//属性映射属性strides类型为int64_t属性pad_list类型为int64_t属性dilations类型为int64_t属性groups类型为int64_t属性format类型为int64_t属性offset_x类型为int64_t
OUTPUT_MAP(Conv3D) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Conv3D, kNameConv3D, ADPT_DESC(Conv3D))
//注册Conv3D操作的适配器描述kNameConv3D返回的name变量
// Conv3DBackpropInputD
INPUT_MAP(Conv3DBackpropInputD) = {{1, INPUT_DESC(out_backprop)}, {2, INPUT_DESC(filter)}};
//输入映射out_backprop索引为1filter索引为2
INPUT_ATTR_MAP(Conv3DBackpropInputD) = {
{3, ATTR_DESC(input_size, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
ATTR_MAP(Conv3DBackpropInputD) = {
{"pad_list", ATTR_DESC(pads, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<std::vector<int64_t>>())},
{"dilations", ATTR_DESC(dilations, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())},
{"groups", ATTR_DESC(groups, AnyTraits<int64_t>())},
};
//属性映射属性strides类型为int64_t属性pad_list类型为int64_t属性dilations类型为int64_t属性groups类型为int64_t属性format类型为int64_t
OUTPUT_MAP(Conv3DBackpropInputD) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Conv3DBackpropInputD, kNameConv3DBackpropInputD, ADPT_DESC(Conv3DBackpropInputD))
//注册Conv3DBackpropInputD操作的适配器描述kNameConv3DBackpropInputD返回的name变量
// Conv3DBackpropFilterD
INPUT_MAP(Conv3DBackpropFilterD) = {{1, INPUT_DESC(out_backprop)}, {2, INPUT_DESC(x)}};
//输入映射out_backprop索引为1filter索引为2
INPUT_ATTR_MAP(Conv3DBackpropFilterD) = {
{3, ATTR_DESC(filter_size, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
ATTR_MAP(Conv3DBackpropFilterD) = {
{"strides", ATTR_DESC(strides, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"pad_list", ATTR_DESC(pads, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"dilations", ATTR_DESC(dilations, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"groups", ATTR_DESC(groups, AnyTraits<int64_t>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())},
};
//属性映射属性strides类型为int64_t属性pad_list类型为int64_t属性dilations类型为int64_t属性groups类型为int64_t属性format类型为int64_t
OUTPUT_MAP(Conv3DBackpropFilterD) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Conv3DBackpropFilterD, kNameConv3DBackpropFilterD, ADPT_DESC(Conv3DBackpropFilterD))
//注册Conv3DBackpropFilterD操作的适配器描述kNameConv3DBackpropFilterD返回的name变量
// DepthwiseConv2D
INPUT_MAP(DepthwiseConv2D) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(filter)}, {3, INPUT_DESC(bias)}};
//输入映射x索引为1filter索引为2bias索引为3
ATTR_MAP(DepthwiseConv2D) = {
{"stride", ATTR_DESC(strides, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"pad_list", ATTR_DESC(pads, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"dilation", ATTR_DESC(dilations, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())},
};
//属性映射属性strides类型为int64_t属性pad_list类型为int64_t属性dilations类型为int64_t属性format类型为int64_t
OUTPUT_MAP(DepthwiseConv2D) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(DepthwiseConv2D, prim::kPrimDepthwiseConv2dNative->name(), ADPT_DESC(DepthwiseConv2D))
//注册DepthwiseConv2D操作的适配器描述kPrimDepthwiseConv2dNative返回的name变量
// DepthwiseConv2DBackpropInputD
INPUT_MAP(DepthwiseConv2DBackpropInputD) = {{2, INPUT_DESC(filter)}, {3, INPUT_DESC(out_backprop)}};
//输入映射filter索引为2out_backprop索引为3
INPUT_ATTR_MAP(DepthwiseConv2DBackpropInputD) = {
{1, ATTR_DESC(input_size, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
ATTR_MAP(DepthwiseConv2DBackpropInputD) = {
{"stride", ATTR_DESC(strides, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"pad_list", ATTR_DESC(pads, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"dilation", ATTR_DESC(dilations, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
};
//属性映射属性strides类型为int64_t属性pad_list类型为int64_t属性dilations类型为int64_t
OUTPUT_MAP(DepthwiseConv2DBackpropInputD) = {{0, OUTPUT_DESC(input_grad)}};
//输出映射input_grad索引为0
REG_ADPT_DESC(DepthwiseConv2DBackpropInputD, prim::kPrimDepthwiseConv2dNativeBackpropInput->name(),
ADPT_DESC(DepthwiseConv2DBackpropInputD))
//注册DepthwiseConv2DBackpropInputD操作的适配器描述kPrimDepthwiseConv2dNativeBackpropInput返回的name变量
// DepthwiseConv2DBackpropFilterD
INPUT_MAP(DepthwiseConv2DBackpropFilterD) = {{1, INPUT_DESC(input)}, {3, INPUT_DESC(out_backprop)}};
//输入映射input索引为1out_backprop索引为3
INPUT_ATTR_MAP(DepthwiseConv2DBackpropFilterD) = {
{2, ATTR_DESC(filter_size, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
ATTR_MAP(DepthwiseConv2DBackpropFilterD) = {
{"stride", ATTR_DESC(strides, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"pad_list", ATTR_DESC(pads, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"dilation", ATTR_DESC(dilations, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
};
//属性映射属性strides类型为int64_t属性pads类型为int64_t属性dilations类型为int64_t
OUTPUT_MAP(DepthwiseConv2DBackpropFilterD) = {{0, OUTPUT_DESC(filter_grad)}};
//输出映射filter_grad索引为0
REG_ADPT_DESC(DepthwiseConv2DBackpropFilterD, prim::kPrimDepthwiseConv2dNativeBackpropFilter->name(),
ADPT_DESC(DepthwiseConv2DBackpropFilterD))
//注册DepthwiseConv2DBackpropFilterD操作的适配器描述kPrimDepthwiseConv2dNativeBackpropFilter返回的name变量
} // namespace mindspore::transform

View File

@ -0,0 +1,115 @@
/**
* Copyright 2019-2021 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_declare/nn_detect_ops_declare.h"
#include <vector>
#include <string>
namespace mindspore::transform {
// BoundingBoxEncode
INPUT_MAP(BoundingBoxEncode) = {
{1, INPUT_DESC(anchor_box)},
{2, INPUT_DESC(ground_truth_box)},
};
//输入映射anchor_box索引为1ground_truth_box索引为2
ATTR_MAP(BoundingBoxEncode) = {
{"means", ATTR_DESC(means, AnyTraits<std::vector<float>>(), AnyTraits<float>())},
{"stds", ATTR_DESC(stds, AnyTraits<std::vector<float>>(), AnyTraits<float>())},
};
//属性映射属性means类型为float属性stds类型为float
OUTPUT_MAP(BoundingBoxEncode) = {{0, OUTPUT_DESC(delats)}};
//输出映射delats索引为0
REG_ADPT_DESC(BoundingBoxEncode, kNameBoundingBoxEncode, ADPT_DESC(BoundingBoxEncode))
//注册BoundingBoxEncode操作的适配器描述KNameBoundingBoxEncode
// BoundingBoxDecode
INPUT_MAP(BoundingBoxDecode) = {
{1, INPUT_DESC(rois)},
{2, INPUT_DESC(deltas)},
};
//输入映射rois索引为1deltas索引为2
ATTR_MAP(BoundingBoxDecode) = {
{"means", ATTR_DESC(means, AnyTraits<std::vector<float>>(), AnyTraits<float>())},
{"stds", ATTR_DESC(stds, AnyTraits<std::vector<float>>(), AnyTraits<float>())},
{"max_shape", ATTR_DESC(max_shape, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"wh_ratio_clip", ATTR_DESC(wh_ratio_clip, AnyTraits<float>())},
};
//属性映射属性means类型为float属性stds类型为float属性max_shape类型为int64_t属性wh_ratio_clip类型为float
OUTPUT_MAP(BoundingBoxDecode) = {{0, OUTPUT_DESC(bboxes)}};
//输出映射bboxes索引为0
REG_ADPT_DESC(BoundingBoxDecode, kNameBoundingBoxDecode, ADPT_DESC(BoundingBoxDecode))
//注册BoundingBoxDecode操作的适配器描述KNameBoundingBoxDecode
// Iou
INPUT_MAP(Iou) = {{1, INPUT_DESC(bboxes)}, {2, INPUT_DESC(gtboxes)}};
//输入映射bboxes索引为1gtboxes索引为2
ATTR_MAP(Iou) = {{"mode", ATTR_DESC(mode, AnyTraits<std::string>())}};
//属性映射属性mode类型为string
OUTPUT_MAP(Iou) = {{0, OUTPUT_DESC(overlap)}};
//输出映射overlap索引为0
REG_ADPT_DESC(Iou, kNameIOU, ADPT_DESC(Iou))
//注册IOU操作的适配器描述KNameIOU
// CheckValid
INPUT_MAP(CheckValid) = {{1, INPUT_DESC(bbox_tensor)}, {2, INPUT_DESC(img_metas)}};
//输入映射bbox_tensor索引为1img_metas索引为2
ATTR_MAP(CheckValid) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(CheckValid) = {{0, OUTPUT_DESC(valid_tensor)}};
//输出映射CheckValid索引为0
REG_ADPT_DESC(CheckValid, kNameCheckValid, ADPT_DESC(CheckValid))
//注册CheckValid操作的适配器描述KNameCheckValid
// Sort
INPUT_MAP(Sort) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(Sort) = {{"axis", ATTR_DESC(axis, AnyTraits<int64_t>())},
{"descending", ATTR_DESC(descending, AnyTraits<bool>())}};
//属性映射属性axis类型为int64_t属性descending类型为bool
OUTPUT_MAP(Sort) = {{0, OUTPUT_DESC(y1)}, {1, OUTPUT_DESC(y2)}};
//输出映射y1索引为0y2索引为1
REG_ADPT_DESC(Sort, kNameSort, ADPT_DESC(Sort))
//注册Sort操作的适配器描述KNameSort
// ROIAlign
INPUT_MAP(ROIAlign) = {{1, INPUT_DESC(features)}, {2, INPUT_DESC(rois)}};
//输入映射features索引为1rois索引为2
OUTPUT_MAP(ROIAlign) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
ATTR_MAP(ROIAlign) = {{"pooled_height", ATTR_DESC(pooled_height, AnyTraits<int64_t>())},
{"pooled_width", ATTR_DESC(pooled_width, AnyTraits<int64_t>())},
{"spatial_scale", ATTR_DESC(spatial_scale, AnyTraits<float>())},
{"sample_num", ATTR_DESC(sample_num, AnyTraits<int64_t>())},
{"roi_end_mode", ATTR_DESC(roi_end_mode, AnyTraits<int64_t>())}};
//属性映射属性pooled_height类型为int64_t属性pooled_width类型为int64_t属性spatial_scale类型为float属性sample_num类型为int64_t属性roi_end_mode类型为int64_t
REG_ADPT_DESC(ROIAlign, kNameROIAlign, ADPT_DESC(ROIAlign))
//注册ROIAlign操作的适配器描述KNameROIAlign
// ROIAlignGrad
INPUT_MAP(ROIAlignGrad) = {{1, INPUT_DESC(ydiff)}, {2, INPUT_DESC(rois)}};
//输入映射ydiff索引为1rois索引为2
OUTPUT_MAP(ROIAlignGrad) = {{0, OUTPUT_DESC(xdiff)}};
//输出映射xdiff索引为0
ATTR_MAP(ROIAlignGrad) = {
{"xdiff_shape", ATTR_DESC(xdiff_shape, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
{"pooled_height", ATTR_DESC(pooled_height, AnyTraits<int64_t>())},
{"pooled_width", ATTR_DESC(pooled_width, AnyTraits<int64_t>())},
{"spatial_scale", ATTR_DESC(spatial_scale, AnyTraits<float>())},
{"sample_num", ATTR_DESC(sample_num, AnyTraits<int64_t>())}};
//属性映射属性xdiff_shape类型为int64_t属性pooled_height类型为int64_t属性pooled_width类型为int64_t属性spatial_scale类型为float属性sample_num类型为int64_t
REG_ADPT_DESC(ROIAlignGrad, kNameROIAlignGrad, ADPT_DESC(ROIAlignGrad))
//注册ROIAlignGrad操作的适配器描述KNameROIAlignGrad
} // namespace mindspore::transform

View File

@ -0,0 +1,245 @@
/**
* Copyright 2019-2021 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_declare/nn_norm_ops_declare.h"
#include <vector>
#include <string>
namespace mindspore::transform {
// SoftmaxV2
INPUT_MAP(SoftmaxV2) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(SoftmaxV2) = {
{"axis", ATTR_DESC(axes, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())},
};
//属性映射属性axis类型为int64_t
OUTPUT_MAP(SoftmaxV2) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(SoftmaxV2, kNameSoftmax, ADPT_DESC(SoftmaxV2))
//注册SoftmaxV2操作的适配器描述KNameSoftmax
// SoftmaxGrad
INPUT_MAP(SoftmaxGrad) = {{1, INPUT_DESC(softmax)}, {2, INPUT_DESC(grad_softmax)}};
//输入映射softmax索引为1grad_softmax索引为2
OUTPUT_MAP(SoftmaxGrad) = {{0, OUTPUT_DESC(grad_x)}};
//输出映射SoftmaxGrad索引为0
ATTR_MAP(SoftmaxGrad) = EMPTY_ATTR_MAP;
//属性映射,设为空
REG_ADPT_DESC(SoftmaxGrad, kNameSoftmaxGrad, ADPT_DESC(SoftmaxGrad))
//注册SoftmaxGrad操作的适配器描述KNameSoftmax
// SoftmaxCrossEntropyWithLogits
INPUT_MAP(SoftmaxCrossEntropyWithLogits) = {{1, INPUT_DESC(features)}, {2, INPUT_DESC(labels)}};
//输入映射features索引为1labels索引为2
ATTR_MAP(SoftmaxCrossEntropyWithLogits) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(SoftmaxCrossEntropyWithLogits) = {{0, OUTPUT_DESC(loss)}, {1, OUTPUT_DESC(backprop)}};
//输出映射loss索引为0backprop索引为1
REG_ADPT_DESC(SoftmaxCrossEntropyWithLogits, prim::kPrimSoftmaxCrossEntropyWithLogits->name(),
ADPT_DESC(SoftmaxCrossEntropyWithLogits))
//注册SoftmaxCrossEntropyWithLogits操作的适配器描述SoftmaxCrossEntropyWithLogits
// SmoothL1Loss
INPUT_MAP(SmoothL1Loss) = {{1, INPUT_DESC(predict)}, {2, INPUT_DESC(label)}};
//输入映射predict索引为1labels索引为2
ATTR_MAP(SmoothL1Loss) = {{"beta", ATTR_DESC(sigma, AnyTraits<float>())}};
//属性映射属性beta类型为float
OUTPUT_MAP(SmoothL1Loss) = {{0, OUTPUT_DESC(loss)}};
//输出映射SmoothL1loss索引为0
REG_ADPT_DESC(SmoothL1Loss, kNameSmoothL1Loss, ADPT_DESC(SmoothL1Loss))
//注册SmoothL1Loss操作的适配器描述kNameSmoothL1Loss
// SmoothL1LossGrad
INPUT_MAP(SmoothL1LossGrad) = {{1, INPUT_DESC(predict)}, {2, INPUT_DESC(label)}, {3, INPUT_DESC(dout)}};
//输入映射predict索引为1labels索引为2dout索引为3
ATTR_MAP(SmoothL1LossGrad) = {{"beta", ATTR_DESC(sigma, AnyTraits<float>())}};
//属性映射属性beta类型为float
OUTPUT_MAP(SmoothL1LossGrad) = {{0, OUTPUT_DESC(gradient)}};
//输出映射gradient索引为0
REG_ADPT_DESC(SmoothL1LossGrad, kNameSmoothL1LossGrad, ADPT_DESC(SmoothL1LossGrad))
//注册SmoothL1LossGrad操作的适配器描述kNameSmoothL1LossGrad
// SigmoidCrossEntropyWithLogits
INPUT_MAP(SigmoidCrossEntropyWithLogits) = {{1, INPUT_DESC(predict)}, {2, INPUT_DESC(target)}};
//输入映射predict索引为1labels索引为2
ATTR_MAP(SigmoidCrossEntropyWithLogits) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(SigmoidCrossEntropyWithLogits) = {{0, OUTPUT_DESC(loss)}};
//输出映射loss索引为0
REG_ADPT_DESC(SigmoidCrossEntropyWithLogits, kNameSigmoidCrossEntropyWithLogits,
ADPT_DESC(SigmoidCrossEntropyWithLogits))
//注册SigmoidCrossEntropyWithLogits操作的适配器描述kNameSigmoidCrossEntropyWithLogits
// SigmoidCrossEntropyWithLogitsGrad
INPUT_MAP(SigmoidCrossEntropyWithLogitsGrad) = {
{1, INPUT_DESC(predict)}, {2, INPUT_DESC(target)}, {3, INPUT_DESC(dout)}};
//输入映射predict索引为1target索引为2dout索引为3
ATTR_MAP(SigmoidCrossEntropyWithLogitsGrad) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(SigmoidCrossEntropyWithLogitsGrad) = {{0, OUTPUT_DESC(gradient)}};
//输出映射gradient索引为0
REG_ADPT_DESC(SigmoidCrossEntropyWithLogitsGrad, kNameSigmoidCrossEntropyWithLogitsGrad,
ADPT_DESC(SigmoidCrossEntropyWithLogitsGrad))
//注册SigmoidCrossEntropyWithLogitsGrad操作的适配器描述kNameSigmoidCrossEntropyWithLogitsGrad
// SigmoidCrossEntropyWithLogitsV2
INPUT_MAP(SigmoidCrossEntropyWithLogitsV2) = {
{1, INPUT_DESC(predict)}, {2, INPUT_DESC(target)}, {3, INPUT_DESC(weight)}, {4, INPUT_DESC(pos_weight)}};
//输入映射predict索引为1target索引为2weight索引为3pos_weight索引为4
ATTR_MAP(SigmoidCrossEntropyWithLogitsV2) = {{"reduction", ATTR_DESC(reduction, AnyTraits<std::string>())}};
//属性映射属性reduction类型为string
OUTPUT_MAP(SigmoidCrossEntropyWithLogitsV2) = {{0, OUTPUT_DESC(loss)}};
//输出映射loss索引为0
REG_ADPT_DESC(SigmoidCrossEntropyWithLogitsV2, kNameSigmoidCrossEntropyWithLogitsV2,
ADPT_DESC(SigmoidCrossEntropyWithLogitsV2))
//注册SigmoidCrossEntropyWithLogitsV2操作的适配器描述kNameSigmoidCrossEntropyWithLogitsV2
// LogSoftmaxGrad
INPUT_MAP(LogSoftmaxGrad) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(grad)}};
//输入映射x索引为1grad索引为2
ATTR_MAP(LogSoftmaxGrad) = {
{"axis", ATTR_DESC(axis, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
//属性映射属性axis类型为int64_t
OUTPUT_MAP(LogSoftmaxGrad) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(LogSoftmaxGrad, prim::kPrimLogSoftmaxGrad->name(), ADPT_DESC(LogSoftmaxGrad))
//注册LogSoftmaxGrad操作的适配器描述kPrimLogSoftmaxGrad
// LogSoftmaxV2
INPUT_MAP(LogSoftmaxV2) = {{1, INPUT_DESC(logits)}};
//输入映射logits索引为1
ATTR_MAP(LogSoftmaxV2) = {
{"axis", ATTR_DESC(axes, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
//属性映射属性axes类型为int64_t
OUTPUT_MAP(LogSoftmaxV2) = {{0, OUTPUT_DESC(logsoftmax)}};
//输出映射logsoftmax索引为0
REG_ADPT_DESC(LogSoftmaxV2, prim::kPrimLogSoftmax->name(), ADPT_DESC(LogSoftmaxV2))
//注册LogSoftmaxV2操作的适配器描述kPrimLogSoftmax
// LayerNorm
INPUT_MAP(LayerNorm) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(gamma)}, {3, INPUT_DESC(beta)}};
//输入映射x索引为1gamma索引为2beta索引为3
ATTR_MAP(LayerNorm) = {{"begin_norm_axis", ATTR_DESC(begin_norm_axis, AnyTraits<int64_t>())},
{"begin_params_axis", ATTR_DESC(begin_params_axis, AnyTraits<int64_t>())},
{"epsilon", ATTR_DESC(epsilon, AnyTraits<float>())}};
//属性映射属性begin_norm_axis类型为int64_t属性begin_params_axis类型为int64_t属性epsilon类型为float
OUTPUT_MAP(LayerNorm) = {{0, OUTPUT_DESC(y)}, {1, OUTPUT_DESC(mean)}, {2, OUTPUT_DESC(variance)}};
//输出映射y索引为0mean索引为1variance索引为2
REG_ADPT_DESC(LayerNorm, prim::kPrimLayerNorm->name(), ADPT_DESC(LayerNorm))
//注册LayerNorm操作的适配器描述kPrimLayerNorm
// LayerNormGrad
INPUT_MAP(LayerNormGrad) = {
{1, INPUT_DESC(x)}, {2, INPUT_DESC(dy)}, {3, INPUT_DESC(variance)}, {4, INPUT_DESC(mean)}, {5, INPUT_DESC(gamma)}};
//输入映射x索引为1dy索引为2variance索引为3mean索引为4gamma索引为5
ATTR_MAP(LayerNormGrad) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(LayerNormGrad) = {{0, OUTPUT_DESC(pd_x)}, {1, OUTPUT_DESC(pd_gamma)}, {2, OUTPUT_DESC(pd_beta)}};
//输出映射pd_x索引为0pd_gamma索引为1pd_beta索引为2
REG_ADPT_DESC(LayerNormGrad, prim::kPrimLayerNormGrad->name(), ADPT_DESC(LayerNormGrad))
//注册LayerNormGrad操作的适配器描述kPrimLayerNormGrad
// LRN
INPUT_MAP(LRN) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(LRN) = {{"depth_radius", ATTR_DESC(depth_radius, AnyTraits<int64_t>())},
{"bias", ATTR_DESC(bias, AnyTraits<float>())},
{"alpha", ATTR_DESC(alpha, AnyTraits<float>())},
{"beta", ATTR_DESC(beta, AnyTraits<float>())},
{"norm_region", ATTR_DESC(norm_region, AnyTraits<string>())}};
//属性映射属性depth_radius类型为int64_t属性bias类型为float属性alpha类型为float属性beta类型为float属性norm_region类型为float
OUTPUT_MAP(LRN) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(LRN, kNameLRN, ADPT_DESC(LRN))
//注册LRN操作的适配器描述kNameLRN
// LRNGrad
INPUT_MAP(LRNGrad) = {{1, INPUT_DESC(grads)}, {2, INPUT_DESC(x)}, {3, INPUT_DESC(y)}};
//输入映射grads索引为1x索引为2y索引为3
ATTR_MAP(LRNGrad) = {{"depth_radius", ATTR_DESC(depth_radius, AnyTraits<int64_t>())},
{"bias", ATTR_DESC(bias, AnyTraits<float>())},
{"alpha", ATTR_DESC(alpha, AnyTraits<float>())},
{"beta", ATTR_DESC(beta, AnyTraits<float>())}};
//属性映射属性depth_radius类型为int64_t属性bias类型为float属性alpha类型为float属性beta类型为float
OUTPUT_MAP(LRNGrad) = {{0, OUTPUT_DESC(z)}};
//输出映射z索引为0
REG_ADPT_DESC(LRNGrad, kNameLRNGrad, ADPT_DESC(LRNGrad))
//注册LRNGrad操作的适配器描述kNameLRNGrad
// DropoutDoMask
INPUT_MAP(DropOutDoMask) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(mask)}, {3, INPUT_DESC(keep_prob)}};
//输入映射x索引为1mask索引为2keep_prob索引为3
ATTR_MAP(DropOutDoMask) = EMPTY_ATTR_MAP;
//属性映射,设为空
OUTPUT_MAP(DropOutDoMask) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(DropOutDoMask, kNameDropoutDoMask, ADPT_DESC(DropOutDoMask))
//注册DropOutDoMask操作的适配器描述kNameDropOutDoMask
// BinaryCrossEntropy
INPUT_MAP(BinaryCrossEntropy) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(y)}, {3, INPUT_DESC(weight)}};
//输入映射x索引为1y索引为2weight索引为3
ATTR_MAP(BinaryCrossEntropy) = {{"reduction", ATTR_DESC(reduction, AnyTraits<std::string>())}};
//属性映射属性reduction类型为string
OUTPUT_MAP(BinaryCrossEntropy) = {{0, OUTPUT_DESC(output)}};
//输出映射output索引为0
REG_ADPT_DESC(BinaryCrossEntropy, kNameBinaryCrossEntropy, ADPT_DESC(BinaryCrossEntropy))
//注册BinaryCrossEntropy操作的适配器描述kNameBinaryCrossEntropy
// BinaryCrossEntropyGrad
INPUT_MAP(BinaryCrossEntropyGrad) = {
{1, INPUT_DESC(x)}, {2, INPUT_DESC(y)}, {3, INPUT_DESC(grad_output)}, {4, INPUT_DESC(weight)}};
//输入映射x索引为1y索引为2grad_output索引为3weight索引为3
ATTR_MAP(BinaryCrossEntropyGrad) = {{"reduction", ATTR_DESC(reduction, AnyTraits<std::string>())}};
//属性映射属性reduction类型为string
OUTPUT_MAP(BinaryCrossEntropyGrad) = {{0, OUTPUT_DESC(output)}};
//输出映射output索引为0
REG_ADPT_DESC(BinaryCrossEntropyGrad, kNameBinaryCrossEntropyGrad, ADPT_DESC(BinaryCrossEntropyGrad))
//注册BinaryCrossEntropyGrad操作的适配器描述kNameBinaryCrossEntropyGrad
// Centralization
INPUT_MAP(Centralization) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(Centralization) = {{"axes", ATTR_DESC(axes, AnyTraits<std::vector<int64_t>>())}};
//属性映射属性axes类型为int64_t
OUTPUT_MAP(Centralization) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Centralization, kNameCentralization, ADPT_DESC(Centralization))
//注册Centralization操作的适配器描述kNameCentralization
// Scale
INPUT_MAP(Scale) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(scale)}, {3, INPUT_DESC(bias)}};
//输入映射x索引为1scale索引为2bias索引为3
ATTR_MAP(Scale) = {{"axis", ATTR_DESC(axis, AnyTraits<int64_t>())},
{"num_axes", ATTR_DESC(num_axes, AnyTraits<int64_t>())},
{"scale_from_blob", ATTR_DESC(scale_from_blob, AnyTraits<bool>())}};
//属性映射属性axes类型为int64_t属性num_axes类型为int64_t属性scale_from_blob类型为bool
OUTPUT_MAP(Scale) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Scale, kNameScale, ADPT_DESC(Scale))
//注册Scale操作的适配器描述kNameScale
// KlDivLossGrad
INPUT_MAP(KlDivLossGrad) = {{1, INPUT_DESC(grad)}, {2, INPUT_DESC(input)}, {3, INPUT_DESC(target)}};
//输入映射grad索引为1input索引为2target索引为3
ATTR_MAP(KlDivLossGrad) = {{"reduction", ATTR_DESC(reduction, AnyTraits<std::string>())},
{"log_target", ATTR_DESC(log_target, AnyTraits<bool>())}};
//属性映射属性reduction类型为string属性log_target类型为bool
OUTPUT_MAP(KlDivLossGrad) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(KlDivLossGrad, kNameKlDivLossGrad, ADPT_DESC(KlDivLossGrad))
//注册KlDivLossGrad操作的适配器描述kNameKlDivLossGrad
} // namespace mindspore::transform

View File

@ -0,0 +1,240 @@
/**
* Copyright 2019-2021 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_declare/nn_pooling_ops_declare.h"
#include <vector>
namespace mindspore::transform {
// MaxPool
INPUT_MAP(MaxPool) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(MaxPool) = {{"kernel_size", ATTR_DESC(ksize, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"pad_mode", ATTR_DESC(padding, AnyTraits<std::string>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())}};
// 属性映射,有四个属性,"kernel_size""strides"类型为int64_t和std::vector<int64_t>型,"pad_mode""format"类型为std::string型
OUTPUT_MAP(MaxPool) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(MaxPool, kNameMaxPool, ADPT_DESC(MaxPool))
// MaxPool3D
INPUT_MAP(MaxPool3D) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(MaxPool3D) = {{"kernel_size", ATTR_DESC(ksize, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"pad_mode", ATTR_DESC(padding, AnyTraits<std::string>())},
{"pad_list", ATTR_DESC(pads, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"dilation", ATTR_DESC(dilation, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"ceil_mode", ATTR_DESC(ceil_mode, AnyTraits<int64_t>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())}};
// 属性映射,有七个属性,"kernel_size""pad_list""strides""format""ceil_mode"类型为int64_t和std::vector<int64_t>型,"pad_mode""format"类型为std::string型
OUTPUT_MAP(MaxPool3D) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(MaxPool3D, kNameMaxPool3D, ADPT_DESC(MaxPool3D))
// 注册MaxPool3D操作的适配器描述kNameMaxPool3D
// MaxPool3DGrad
INPUT_MAP(MaxPool3DGrad) = {{1, INPUT_DESC(orig_x)}, {2, INPUT_DESC(orig_y)}, {3, INPUT_DESC(grads)}};
// 输入映射orig_x的索引为1orig_y的索引为2grads索引为3
ATTR_MAP(MaxPool3DGrad) = {{"kernel_size", ATTR_DESC(ksize, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"pad_list", ATTR_DESC(pads, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())}};
// 属性映射,有四个属性,"kernel_size""strides""pad_list"类型为int64_t和std::vector<int64_t>型,"format"类型为std::string型
OUTPUT_MAP(MaxPool3DGrad) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(MaxPool3DGrad, kNameMaxPool3DGrad, ADPT_DESC(MaxPool3DGrad))
// 注册MaxPool3DGrad操作的适配器描述kNameMaxPool3DGrad
// MaxPool3DGradGrad
INPUT_MAP(MaxPool3DGradGrad) = {{1, INPUT_DESC(orig_x)}, {2, INPUT_DESC(orig_y)}, {3, INPUT_DESC(grads)}};
// 输入映射orig_x的索引为1orig_y的索引为2grads索引为3
ATTR_MAP(MaxPool3DGradGrad) = {
{"kernel_size", ATTR_DESC(ksize, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"pad_list", ATTR_DESC(pads, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())}};
// 属性映射,有四个属性,"kernel_size""strides""pad_list"类型为int64_t和std::vector<int64_t>型,"format"类型为std::string型
OUTPUT_MAP(MaxPool3DGradGrad) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(MaxPool3DGradGrad, kNameMaxPool3DGradGrad, ADPT_DESC(MaxPool3DGradGrad))
// 注册MaxPool3DGradGrad操作的适配器描述kNameMaxPool3DGradGrad
// AvgPool
INPUT_MAP(AvgPool) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(AvgPool) = {{"kernel_size", ATTR_DESC(ksize, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"pad_mode", ATTR_DESC(padding, AnyTraits<std::string>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())}};
// 属性映射,有四个属性,"kernel_size""strides""pad_list"类型为int64_t和std::vector<int64_t>型,"format"类型为std::string型
OUTPUT_MAP(AvgPool) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(AvgPool, kNameAvgPool, ADPT_DESC(AvgPool))
// 注册AvgPool操作的适配器描述kNameAvgPool
// MaxPoolGrad
INPUT_MAP(MaxPoolGrad) = {{1, INPUT_DESC(x1)}, {2, INPUT_DESC(x2)}, {3, INPUT_DESC(grad)}};
// 输入映射orig_x的索引为1orig_y的索引为2grads索引为3
ATTR_MAP(MaxPoolGrad) = {{"kernel_size", ATTR_DESC(ksize, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"pad_mode", ATTR_DESC(padding, AnyTraits<std::string>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())}};
// 属性映射,有四个属性,"kernel_size""strides""pad_list"类型为int64_t和std::vector<int64_t>型,"format"类型为std::string型
OUTPUT_MAP(MaxPoolGrad) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(MaxPoolGrad, kNameMaxPoolGrad, ADPT_DESC(MaxPoolGrad))
// 注册MaxPoolGrad操作的适配器描述kNameMaxPoolGrad
// MaxPoolGradGrad
INPUT_MAP(MaxPoolGradGrad) = {{1, INPUT_DESC(x1)}, {2, INPUT_DESC(x2)}, {3, INPUT_DESC(grad)}};
// 输入映射orig_x的索引为1orig_y的索引为2grads索引为3
ATTR_MAP(MaxPoolGradGrad) = {{"kernel_size", ATTR_DESC(ksize, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"pad_mode", ATTR_DESC(padding, AnyTraits<std::string>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())}};
// 属性映射,有四个属性,"kernel_size""strides""pad_list"类型为int64_t和std::vector<int64_t>型,"format"类型为std::string型
OUTPUT_MAP(MaxPoolGradGrad) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(MaxPoolGradGrad, kNameMaxPoolGradGrad, ADPT_DESC(MaxPoolGradGrad))
// 注册MaxPoolGradGrad操作的适配器描述kNameMaxPoolGradGrad
// avgpoolgrad
INPUT_MAP(AvgPoolGrad) = {{1, INPUT_DESC(orig_input_shape)}, {2, INPUT_DESC(input_grad)}};
// 输入映射orig_input_shape的索引为1input_grad的索引为2
ATTR_MAP(AvgPoolGrad) = {{"kernel_size", ATTR_DESC(ksize, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"pad_mode", ATTR_DESC(padding, AnyTraits<std::string>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())}};
// 属性映射,有四个属性,"kernel_size""strides""pad_list"类型为int64_t和std::vector<int64_t>型,"format"类型为std::string型
OUTPUT_MAP(AvgPoolGrad) = {{0, OUTPUT_DESC(out_grad)}};
// 输出映射out_grad索引为0
REG_ADPT_DESC(AvgPoolGrad, kNameAvgPoolGrad, ADPT_DESC(AvgPoolGrad))
// 注册AvgPoolGrad操作的适配器描述kNameAvgPoolGrad
// MaxPoolWithArgmax
INPUT_MAP(MaxPoolWithArgmax) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(MaxPoolWithArgmax) = {
{"kernel_size", ATTR_DESC(ksize, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"pad_mode", ATTR_DESC(padding, AnyTraits<std::string>())}};
// 属性映射,有三个属性,"kernel_size""strides"类型为int64_t和std::vector<int64_t>型,"pad_mode"类型为std::string型
OUTPUT_MAP(MaxPoolWithArgmax) = {{0, OUTPUT_DESC(y)}, {1, OUTPUT_DESC(argmax)}};
// 输出映射y索引为0argmax索引为1
REG_ADPT_DESC(MaxPoolWithArgmax, kNameMaxPoolWithArgmax, ADPT_DESC(MaxPoolWithArgmax))
// 注册MaxPoolWithArgmax操作的适配器描述kNameMaxPoolWithArgmax
// MaxPoolGradWithArgmax
INPUT_MAP(MaxPoolGradWithArgmax) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(grad)}, {3, INPUT_DESC(argmax)}};
// 输入映射x的索引为1grad的索引为2argmax索引为3
ATTR_MAP(MaxPoolGradWithArgmax) = {
{"kernel_size", ATTR_DESC(ksize, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"pad_mode", ATTR_DESC(padding, AnyTraits<std::string>())}};
// 属性映射,有三个属性,"kernel_size""strides"类型为int64_t和std::vector<int64_t>型,"pad_mode"类型为std::string型
OUTPUT_MAP(MaxPoolGradWithArgmax) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(MaxPoolGradWithArgmax, kNameMaxPoolGradWithArgmax, ADPT_DESC(MaxPoolGradWithArgmax))
// 注册MaxPoolGradWithArgmax操作的适配器描述kNameMaxPoolGradWithArgmax
// MaxPoolGradGradWithArgmax
INPUT_MAP(MaxPoolGradGradWithArgmax) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(grad)}, {3, INPUT_DESC(argmax)}};
// 输入映射x的索引为1grad的索引为2argmax索引为3
ATTR_MAP(MaxPoolGradGradWithArgmax) = {
{"kernel_size", ATTR_DESC(ksize, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"pad_mode", ATTR_DESC(padding, AnyTraits<std::string>())}};
// 属性映射,有三个属性,"kernel_size""strides"类型为int64_t和std::vector<int64_t>型,"pad_mode"类型为std::string型
OUTPUT_MAP(MaxPoolGradGradWithArgmax) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(MaxPoolGradGradWithArgmax, kNameMaxPoolGradGradWithArgmax, ADPT_DESC(MaxPoolGradGradWithArgmax))
// 注册MaxPoolGradGradWithArgmax操作的适配器描述kNameMaxPoolGradGradWithArgmax
// Pooling
INPUT_MAP(Pooling) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(Pooling) = {{"mode", ATTR_DESC(mode, AnyTraits<int64_t>())},
{"global", ATTR_DESC(global_pooling, AnyTraits<bool>())},
{"kernel_size", ATTR_DESC(window, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(stride, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"pad", ATTR_DESC(pad, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"dilation", ATTR_DESC(dilation, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"round_mode", ATTR_DESC(ceil_mode, AnyTraits<int64_t>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())}};
//属性映射,有八个属性,"kernel_size""strides""pad""dilation"类型为int64_t和std::vector<int64_t>型,"format"类型为std::string型
//"mode""round_mode"类型为int64_t型"global"类型为bool型
OUTPUT_MAP(Pooling) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(Pooling, kNamePooling, ADPT_DESC(Pooling))
// 注册Pooling操作的适配器描述kNamePooling
// MaxPoolV3
INPUT_MAP(MaxPoolV3) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(MaxPoolV3) = {{"kernel_size", ATTR_DESC(ksize, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"padding_mode", ATTR_DESC(padding_mode, AnyTraits<std::string>())},
{"pad", ATTR_DESC(pads, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())},
{"global", ATTR_DESC(global_pooling, AnyTraits<bool>())},
{"ceil_mode", ATTR_DESC(ceil_mode, AnyTraits<bool>())}};
// 属性映射,有七个属性,"kernel_size""strides""pad"类型为int64_t和std::vector<int64_t>型,"format"类型为std::string型
//"round_mode"类型为int64_t型"global""ceil_mode"类型为bool型
OUTPUT_MAP(MaxPoolV3) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(MaxPoolV3, kNameMaxPoolV3, ADPT_DESC(MaxPoolV3))
// 注册MaxPoolV3操作的适配器描述kNameMaxPoolV3
// AvgPoolV2
INPUT_MAP(AvgPoolV2) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(AvgPoolV2) = {{"kernel_size", ATTR_DESC(ksize, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"strides", ATTR_DESC(strides, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"padding_mode", ATTR_DESC(padding_mode, AnyTraits<std::string>())},
{"pad", ATTR_DESC(pads, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{"format", ATTR_DESC(data_format, AnyTraits<std::string>())},
{"global", ATTR_DESC(global_pooling, AnyTraits<bool>())},
{"ceil_mode", ATTR_DESC(ceil_mode, AnyTraits<bool>())}};
// 属性映射,有七个属性,"kernel_size""strides""pad"类型为int64_t和std::vector<int64_t>型,"format"类型为std::string型
//"round_mode"类型为int64_t型"global""ceil_mode"类型为bool型
OUTPUT_MAP(AvgPoolV2) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(AvgPoolV2, kNameAvgPoolV2, ADPT_DESC(AvgPoolV2))
// 注册AvgPoolV2操作的适配器描述kNameAvgPoolV2
// GlobalAveragePool
INPUT_MAP(GlobalAveragePool) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(GlobalAveragePool) = EMPTY_ATTR_MAP;
//属性映射,空
OUTPUT_MAP(GlobalAveragePool) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(GlobalAveragePool, kNameGlobalAvgPool, ADPT_DESC(GlobalAveragePool))
// 注册GlobalAveragePool操作的适配器描述kNameGlobalAvgPool
// Upsample
INPUT_MAP(Upsample) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(Upsample) = {{"scale", ATTR_DESC(scale, AnyTraits<float>())},
{"stride_h", ATTR_DESC(stride_h, AnyTraits<int64_t>())},
{"stride_w", ATTR_DESC(stride_w, AnyTraits<int64_t>())}};
// 属性映射,有三个属性,"stride_h""stride_w"类型为int64_t型"scale"类型为float型
OUTPUT_MAP(Upsample) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(Upsample, kNameUpsample, ADPT_DESC(Upsample))
// 注册Upsample操作的适配器描述kNameUpsample
} // namespace mindspore::transform

View File

@ -0,0 +1,315 @@
/**
* Copyright 2019-2021 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_declare/nn_training_ops_declare.h"
namespace mindspore::transform {
// ApplyMomentum
INPUT_MAP(ApplyMomentum) = {
{1, INPUT_DESC(var)}, {2, INPUT_DESC(accum)}, {3, INPUT_DESC(lr)}, {4, INPUT_DESC(grad)}, {5, INPUT_DESC(momentum)}};
// 输入映射有四个输入accum索引为2lr索引为3grad索引为4momentum索引为5
ATTR_MAP(ApplyMomentum) = {{"use_nesterov", ATTR_DESC(use_nesterov, AnyTraits<bool>())},
{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
// 属性映射,有两个属性"use_nesterov""use_locking"类型未bool型
OUTPUT_MAP(ApplyMomentum) = {{0, OUTPUT_DESC(var)}};'
//输出映射var的索引为0
REG_ADPT_DESC(ApplyMomentum, kNameApplyMomentum, ADPT_DESC(ApplyMomentum))
// 注册ApplyMomentum操作的适配器描述kNameApplyMomentum
//
// LarsV2Update
INPUT_MAP(LarsV2Update) = {{1, INPUT_DESC(w)},
{2, INPUT_DESC(g)},
{3, INPUT_DESC(w_square_sum)},
{4, INPUT_DESC(g_square_sum)},
{5, INPUT_DESC(weight_decay)},
{6, INPUT_DESC(learning_rate)}};
// 输入映射有六个输入w索引为1g索引为2w_square_sum索引为3g_square_sum索引为4weight_decay索引为5learning_rate索引为6
ATTR_MAP(LarsV2Update) = {{"epsilon", ATTR_DESC(epsilon, AnyTraits<float>())},
{"hyperpara", ATTR_DESC(hyperpara, AnyTraits<float>())},
{"use_clip", ATTR_DESC(use_clip, AnyTraits<bool>())}};
// 属性映射,有三个属性,"epsilon""hyperpara"类型为float型"use_clip"类型为bool型
OUTPUT_MAP(LarsV2Update) = {{0, OUTPUT_DESC(g_new)}};
// 输出映射g_new的索引为0
REG_ADPT_DESC(LarsV2Update, kNameLARSUpdate, ADPT_DESC(LarsV2Update))
// 注册LarsV2Update操作的适配器描述kNameLARSUpdate
// ApplyAdam
INPUT_MAP(ApplyAdam) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(m)}, {3, INPUT_DESC(v)},
{4, INPUT_DESC(beta1_power)}, {5, INPUT_DESC(beta2_power)}, {6, INPUT_DESC(lr)},
{7, INPUT_DESC(beta1)}, {8, INPUT_DESC(beta2)}, {9, INPUT_DESC(epsilon)},
{10, INPUT_DESC(grad)}};
// 输入映射有十个输入var索引为1m索引为2v索引为3beta1_power索引为4beta2_power索引为5lr索引为6
// betal索引为7beta2索引为8epsilon索引为9grad索引为10
ATTR_MAP(ApplyAdam) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())},
{"use_nesterov", ATTR_DESC(use_nesterov, AnyTraits<bool>())}};
// 属性映射,有两个属性"use_locking""use_nesterov"类型为bool型
OUTPUT_MAP(ApplyAdam) = {{0, OUTPUT_DESC(var)}};
// 输出映射var的索引为0
// ApplyAdamD
INPUT_MAP(ApplyAdamD) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(m)}, {3, INPUT_DESC(v)},
{4, INPUT_DESC(beta1_power)}, {5, INPUT_DESC(beta2_power)}, {6, INPUT_DESC(lr)},
{7, INPUT_DESC(beta1)}, {8, INPUT_DESC(beta2)}, {9, INPUT_DESC(epsilon)},
{10, INPUT_DESC(grad)}};
// 输入映射有十个输入var索引为1m索引为2v索引为3beta1_power索引为4beta2_power索引为5lr索引为6
// betal索引为7beta2索引为8epsilon索引为9grad索引为10
ATTR_MAP(ApplyAdamD) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())},
{"use_nesterov", ATTR_DESC(use_nesterov, AnyTraits<bool>())}};
// 属性映射,有两个属性"use_locking""use_nesterov"类型为bool型
OUTPUT_MAP(ApplyAdamD) = {{0, OUTPUT_DESC(var)}, {1, OUTPUT_DESC(m)}, {2, OUTPUT_DESC(v)}};
// 输出映射共三个var的索引为0m索引为1v索引为2
REG_ADPT_DESC(ApplyAdamD, kNameApplyAdam, ADPT_DESC(ApplyAdamD))
// 注册ApplyAdamD操作的适配器描述kNameApplyAdam
REG_ADPT_DESC(ApplyAdam, kNameApplyAdam, ADPT_DESC(ApplyAdam))
// 注册ApplyAdam操作的适配器描述kNameApplyAdam
// ApplyAdagradD
INPUT_MAP(ApplyAdagradD) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(accum)}, {3, INPUT_DESC(lr)}, {4, INPUT_DESC(grad)}};
// 输入映射有四个输入var索引为1accum索引为2lr索引为3grad索引为4
ATTR_MAP(ApplyAdagradD) = {{"update_slots", ATTR_DESC(update_slots, AnyTraits<bool>())},
{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
// 属性映射,有两个属性"use_locking""use_nesterov"类型为bool型
OUTPUT_MAP(ApplyAdagradD) = {{0, OUTPUT_DESC(var)}, {1, OUTPUT_DESC(accum)}};
// 输出映射共两个var的索引为0accum索引为1
REG_ADPT_DESC(ApplyAdagradD, kNameApplyAdagrad, ADPT_DESC(ApplyAdagradD))
// 注册ApplyAdagradD操作的适配器描述 kNameApplyAdagrad
//
// ApplyAdagradV2D
INPUT_MAP(ApplyAdagradV2D) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(accum)}, {3, INPUT_DESC(lr)}, {4, INPUT_DESC(grad)}};
// 输入映射有四个输入var索引为1accum索引为2lr索引为3grad索引为4
ATTR_MAP(ApplyAdagradV2D) = {{"epsilon", ATTR_DESC(epsilon, AnyTraits<float>())},
{"update_slots", ATTR_DESC(update_slots, AnyTraits<bool>())},
{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
// 属性映射,有三个属性,"epsilon"类型为float型"update_slots""use_locking"类型为bool型
OUTPUT_MAP(ApplyAdagradV2D) = {{0, OUTPUT_DESC(var)}, {1, OUTPUT_DESC(accum)}};
// 输出映射共两个var的索引为0accum索引为1
REG_ADPT_DESC(ApplyAdagradV2D, kNameApplyAdagradV2D, ADPT_DESC(ApplyAdagradV2D))
// 注册ApplyAdagradV2D操作的适配器描述 kNameApplyAdagradV2D
// ApplyAddSignD
INPUT_MAP(ApplyAddSignD) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(m)}, {3, INPUT_DESC(lr)},
{4, INPUT_DESC(alpha)}, {5, INPUT_DESC(sign_decay)}, {6, INPUT_DESC(beta)},
{7, INPUT_DESC(grad)}};
// 输入映射有七个输入var索引为1m索引为2lr索引为3alpha索引为4sign_decay索引为5beta索引为6grad索引为7
ATTR_MAP(ApplyAddSignD) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
//属性映射,有一个属性,"use_locking"类型为bool型
OUTPUT_MAP(ApplyAddSignD) = {{0, OUTPUT_DESC(var)}, {1, OUTPUT_DESC(m)}};
// 输出映射共两个var的索引为0m索引为1
REG_ADPT_DESC(ApplyAddSignD, kNameApplyAddSignD, ADPT_DESC(ApplyAddSignD))
// 注册ApplyAddSignD操作的适配器描述kNameApplyAddSignD
// SparseApplyAdagradV2D
INPUT_MAP(SparseApplyAdagradV2D) = {
{1, INPUT_DESC(var)}, {2, INPUT_DESC(accum)}, {3, INPUT_DESC(grad)}, {4, INPUT_DESC(indices)}};
// 输入映射有四个输入var索引为1accum索引为2grad索引为3indices索引为4
ATTR_MAP(SparseApplyAdagradV2D) = {{"lr", ATTR_DESC(lr, AnyTraits<float>())},
{"epsilon", ATTR_DESC(epsilon, AnyTraits<float>())},
{"update_slots", ATTR_DESC(update_slots, AnyTraits<bool>())},
{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
// 属性映射,有四个属性,"lr""epsilon"类型为float型"update_slots""use_locking"类型为bool型
OUTPUT_MAP(SparseApplyAdagradV2D) = {{0, OUTPUT_DESC(var)}, {1, OUTPUT_DESC(accum)}};
// 输出映射共两个var的索引为0accum索引为1
REG_ADPT_DESC(SparseApplyAdagradV2D, kNameSparseApplyAdagradV2D, ADPT_DESC(SparseApplyAdagradV2D))
// 注册SparseApplyAdagradV2D操作的适配器描述kNameSparseApplyAdagradV2D
// DataFormatDimMap
INPUT_MAP(DataFormatDimMap) = {{1, INPUT_DESC(x)}};
// 输入映射x索引为1
ATTR_MAP(DataFormatDimMap) = {{"src_format", ATTR_DESC(src_format, AnyTraits<std::string>())},
{"dst_format", ATTR_DESC(dst_format, AnyTraits<std::string>())}};
// 属性映射,有两个属性,"src_format""dst_format"类型为td::string型
OUTPUT_MAP(DataFormatDimMap) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(DataFormatDimMap, kNameDataFormatDimMap, ADPT_DESC(DataFormatDimMap))
// 注册DataFormatDimMap操作的适配器描述kNameDataFormatDimMap
// ApplyAdadeltaD
INPUT_MAP(ApplyAdadeltaD) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(accum)}, {3, INPUT_DESC(accum_update)},
{4, INPUT_DESC(lr)}, {5, INPUT_DESC(rho)}, {6, INPUT_DESC(epsilon)},
{7, INPUT_DESC(grad)}};
// 输入映射有七个输入var索引为1accum索引为2accum_update索引为3lr索引为4rho索引为5epsilon索引为6grad索引为7
ATTR_MAP(ApplyAdadeltaD) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
// 属性映射,有一个属性,"use_locking"类型为bool型
OUTPUT_MAP(ApplyAdadeltaD) = {{0, OUTPUT_DESC(var)}, {1, OUTPUT_DESC(accum)}, {2, OUTPUT_DESC(accum_update)}};
// 输出映射共三个var的索引为0accum索引为1accum_update索引为2
REG_ADPT_DESC(ApplyAdadeltaD, kNameApplyAdadelta, ADPT_DESC(ApplyAdadeltaD))
// 注册ApplyAdadeltaD操作的适配器描述 kNameApplyAdadelta
// ApplyAdaMaxD
INPUT_MAP(ApplyAdaMaxD) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(m)}, {3, INPUT_DESC(v)},
{4, INPUT_DESC(beta1_power)}, {5, INPUT_DESC(lr)}, {6, INPUT_DESC(beta1)},
{7, INPUT_DESC(beta2)}, {8, INPUT_DESC(epsilon)}, {9, INPUT_DESC(grad)}};
// 输入映射有十个输入var索引为1m索引为2v索引为3beta1_power索引为4lr索引为5
// betal索引为6beta2索引为7epsilon索引为8grad索引为9
ATTR_MAP(ApplyAdaMaxD) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
// 属性映射,有一个属性,"use_locking"类型为bool型
OUTPUT_MAP(ApplyAdaMaxD) = {{0, OUTPUT_DESC(var)}, {1, OUTPUT_DESC(m)}, {2, OUTPUT_DESC(v)}};
// 输出映射共三个var的索引为0m索引为1v索引为2
REG_ADPT_DESC(ApplyAdaMaxD, kNameApplyAdaMax, ADPT_DESC(ApplyAdaMaxD))
// 注册ApplyAdaMaxD操作的适配器描述 kNameApplyAdaMax
// ApplyGradientDescent
INPUT_MAP(ApplyGradientDescent) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(alpha)}, {3, INPUT_DESC(delta)}};
// 输入映射有三个输入var索引为1alpha索引为2delta索引为3
ATTR_MAP(ApplyGradientDescent) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
// 属性映射,有一个属性,"use_locking"类型为bool型
OUTPUT_MAP(ApplyGradientDescent) = {{0, OUTPUT_DESC(var)}};
// 输出映射var的索引为0
REG_ADPT_DESC(ApplyGradientDescent, kNameApplyGradientDescent, ADPT_DESC(ApplyGradientDescent))
// 注册ApplyGradientDescent操作的适配器描述kNameApplyGradientDescent
// ApplyPowerSignD
INPUT_MAP(ApplyPowerSignD) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(m)}, {3, INPUT_DESC(lr)},
{4, INPUT_DESC(logbase)}, {5, INPUT_DESC(sign_decay)}, {6, INPUT_DESC(beta)},
{7, INPUT_DESC(grad)}};
// 输入映射有七个输入var索引为1m索引为2lr索引为3logbase索引为4sign_decay索引为5
// beta索引为6grad索引为7
ATTR_MAP(ApplyPowerSignD) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
// 属性映射,有一个属性,"use_locking"类型为bool型
OUTPUT_MAP(ApplyPowerSignD) = {{0, OUTPUT_DESC(var)}, {1, OUTPUT_DESC(m)}};
// 输出映射共两个var的索引为0m索引为1
REG_ADPT_DESC(ApplyPowerSignD, kNameApplyPowerSign, ADPT_DESC(ApplyPowerSignD))
// 注册ApplyPowerSignD操作的适配器描述kNameApplyPowerSign
// ApplyProximalGradientDescent
INPUT_MAP(ApplyProximalGradientDescent) = {
{1, INPUT_DESC(var)}, {2, INPUT_DESC(alpha)}, {3, INPUT_DESC(l1)}, {4, INPUT_DESC(l2)}, {5, INPUT_DESC(delta)}};
// 输入映射有五个输入var索引为1alpha索引为2l1索引为3l2索引为4delta索引为5
ATTR_MAP(ApplyProximalGradientDescent) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
// 属性映射,有一个属性,"use_locking"类型为bool型
OUTPUT_MAP(ApplyProximalGradientDescent) = {{0, OUTPUT_DESC(var)}};
// 输出映射var的索引为0
REG_ADPT_DESC(ApplyProximalGradientDescent, kNameApplyProximalGradientDescent, ADPT_DESC(ApplyProximalGradientDescent))
// 注册ApplyProximalGradientDescent操作的适配器描述kNameApplyProximalGradientDescent
//
// SGD
INPUT_MAP(SGD) = {{1, INPUT_DESC(parameters)}, {2, INPUT_DESC(gradient)}, {3, INPUT_DESC(learning_rate)},
{4, INPUT_DESC(accum)}, {5, INPUT_DESC(momentum)}, {6, INPUT_DESC(stat)}};
// 输入映射有六个输入parameters索引为1gradient索引为2lr索引为3logbase索引为4sign_decay索引为5stat索引为6
ATTR_MAP(SGD) = {{"dampening", ATTR_DESC(dampening, AnyTraits<float>())},
{"weight_decay", ATTR_DESC(weight_decay, AnyTraits<float>())},
{"nesterov", ATTR_DESC(nesterov, AnyTraits<bool>())}};
// 属性映射,有三个属性,"dampening""weight_decay"类型为float型"nesterov"类型为bool型
OUTPUT_MAP(SGD) = {{0, OUTPUT_DESC(parameters)}};
// 输出映射parameters的索引为0
REG_ADPT_DESC(SGD, kNameSGD, ADPT_DESC(SGD))
// 注册SGD操作的适配器描述kNameSGD
// SparseApplyAdagradD
INPUT_MAP(SparseApplyAdagradD) = {
{1, INPUT_DESC(var)}, {2, INPUT_DESC(accum)}, {3, INPUT_DESC(grad)}, {4, INPUT_DESC(indices)}};
// 输入映射有四个输入var索引为1accum索引为2grad索引为3indices索引为4
ATTR_MAP(SparseApplyAdagradD) = {{"lr", ATTR_DESC(lr, AnyTraits<float>())},
{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
// 属性映射,有两个属性,"lr"类型为float型"use_locking"类型为bool型
OUTPUT_MAP(SparseApplyAdagradD) = {{0, OUTPUT_DESC(var)}};
// 输出映射var的索引为0
REG_ADPT_DESC(SparseApplyAdagradD, kNameSparseApplyAdagrad, ADPT_DESC(SparseApplyAdagradD))
// 注册SparseApplyAdagradD操作的适配器描述 kNameSparseApplyAdagrad
// ApplyProximalAdagradD
INPUT_MAP(ApplyProximalAdagradD) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(accum)}, {3, INPUT_DESC(lr)},
{4, INPUT_DESC(l1)}, {5, INPUT_DESC(l2)}, {6, INPUT_DESC(grad)}};
// 输入映射有六个输入var索引为1accum索引为2lr索引为3l1索引为4l2索引为5grad索引为6
ATTR_MAP(ApplyProximalAdagradD) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
// 属性映射,有一个属性,"use_locking"类型为bool型
OUTPUT_MAP(ApplyProximalAdagradD) = {{0, OUTPUT_DESC(var)}, {1, OUTPUT_DESC(accum)}};
// 输出映射var的索引为0accum的索引为1
REG_ADPT_DESC(ApplyProximalAdagradD, kNameApplyProximalAdagrad, ADPT_DESC(ApplyProximalAdagradD))
// 注册ApplyProximalAdagradD操作的适配器描述kNameApplyProximalAdagrad
//
// SparseApplyProximalAdagradD
INPUT_MAP(SparseApplyProximalAdagradD) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(accum)}, {3, INPUT_DESC(lr)},
{4, INPUT_DESC(l1)}, {5, INPUT_DESC(l2)}, {6, INPUT_DESC(grad)},
{7, INPUT_DESC(indices)}};
// 输入映射有七个输入var索引为1accum索引为2lr索引为3l1索引为4l2索引为5grad索引为6indices索引为7
ATTR_MAP(SparseApplyProximalAdagradD) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
// 属性映射,有一个属性,"use_locking"类型为bool型
OUTPUT_MAP(SparseApplyProximalAdagradD) = {{0, OUTPUT_DESC(var)}, {1, OUTPUT_DESC(accum)}};
// 输出映射var的索引为0accum的索引为1
REG_ADPT_DESC(SparseApplyProximalAdagradD, kNameSparseApplyProximalAdagradD, ADPT_DESC(SparseApplyProximalAdagradD))
// 注册SparseApplyProximalAdagradD操作的适配器描述kNameSparseApplyProximalAdagradD
// SparseApplyFtrlD
INPUT_MAP(SparseApplyFtrlD) = {{1, INPUT_DESC(var)},
{2, INPUT_DESC(accum)},
{3, INPUT_DESC(linear)},
{4, INPUT_DESC(grad)},
{5, INPUT_DESC(indices)}};
// 输入映射有五个输入var索引为1accum索引为2linear索引为3grad索引为4indices索引为5
ATTR_MAP(SparseApplyFtrlD) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())},
{"lr", ATTR_DESC(lr, AnyTraits<float>())},
{"l1", ATTR_DESC(l1, AnyTraits<float>())},
{"l2", ATTR_DESC(l2, AnyTraits<float>())},
{"lr_power", ATTR_DESC(lr_power, AnyTraits<float>())}};
// 属性映射,有五个属性,"use_locking""lr""l1""l2""lr_power"类型为float型
OUTPUT_MAP(SparseApplyFtrlD) = {{0, OUTPUT_DESC(var)}};
// 输出映射var的索引为0
REG_ADPT_DESC(SparseApplyFtrlD, kNameSparseApplyFtrlD, ADPT_DESC(SparseApplyFtrlD))
// 注册SparseApplyFtrlD操作的适配器描述kNameSparseApplyFtrlD
// SparseApplyFtrlV2D
INPUT_MAP(SparseApplyFtrlV2D) = {{1, INPUT_DESC(var)},
{2, INPUT_DESC(accum)},
{3, INPUT_DESC(linear)},
{4, INPUT_DESC(grad)},
{5, INPUT_DESC(indices)}};
// 输入映射有五个输入var索引为1accum索引为2linear索引为3grad索引为4indices索引为5
ATTR_MAP(SparseApplyFtrlV2D) = {{"lr", ATTR_DESC(lr, AnyTraits<float>())}, {"l1", ATTR_DESC(l1, AnyTraits<float>())}};
// 属性映射,有两个属性,"l1""l2"类型为float型
OUTPUT_MAP(SparseApplyFtrlV2D) = {{0, OUTPUT_DESC(var)}, {1, OUTPUT_DESC(accum)}, {2, OUTPUT_DESC(linear)}};
// 输出映射var的索引为0accum的索引为1linear索引为2
REG_ADPT_DESC(SparseApplyFtrlV2D, kNameSparseApplyFtrlV2D, ADPT_DESC(SparseApplyFtrlV2D))
// 注册SparseApplyFtrlV2D操作的适配器描述 kNameSparseApplyFtrlV2D
// ApplyFtrl
INPUT_MAP(ApplyFtrl) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(accum)}, {3, INPUT_DESC(linear)},
{4, INPUT_DESC(grad)}, {5, INPUT_DESC(lr)}, {6, INPUT_DESC(l1)},
{7, INPUT_DESC(l2)}, {8, INPUT_DESC(lr_power)}};
// 输入映射有八个输入var索引为1accum索引为2linear索引为3grad索引为4lr索引为5l1索引为6l2索引为7lr_power索引为8
ATTR_MAP(ApplyFtrl) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
// 属性映射,有一个属性,"use_locking"类型为bool型
OUTPUT_MAP(ApplyFtrl) = {{0, OUTPUT_DESC(var)}};
// 输出映射var的索引为0
REG_ADPT_DESC(ApplyFtrl, kNameApplyFtrl, ADPT_DESC(ApplyFtrl))
// 注册ApplyFtrl操作的适配器描述kNameApplyFtrl
// ApplyRMSPropD
INPUT_MAP(ApplyRMSPropD) = {
{1, INPUT_DESC(var)}, {2, INPUT_DESC(ms)}, {3, INPUT_DESC(mom)}, {4, INPUT_DESC(lr)}, {5, INPUT_DESC(grad)}};
// 输入映射有五个输入var索引为1ms索引为2mom索引为3lr索引为4grad索引为5
INPUT_ATTR_MAP(ApplyRMSPropD) = {{6, ATTR_DESC(rho, AnyTraits<float>())},
{7, ATTR_DESC(momentum, AnyTraits<float>())},
{8, ATTR_DESC(epsilon, AnyTraits<float>())}};
//输入属性映射共3个rho索引为6momentum索引为7epsilon索引为8
ATTR_MAP(ApplyRMSPropD) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}}
// 属性映射,有一个属性,"use_locking"类型为bool型;
OUTPUT_MAP(ApplyRMSPropD) = {{0, OUTPUT_DESC(var)}};
// 输出映射var的索引为0
REG_ADPT_DESC(ApplyRMSPropD, kNameApplyRMSProp, ADPT_DESC(ApplyRMSPropD))
// 注册ApplyRMSPropD操作的适配器描述 kNameApplyRMSProp
// ApplyCenteredRMSProp
INPUT_MAP(ApplyCenteredRMSProp) = {{1, INPUT_DESC(var)}, {2, INPUT_DESC(mg)}, {3, INPUT_DESC(ms)},
{4, INPUT_DESC(mom)}, {5, INPUT_DESC(grad)}, {6, INPUT_DESC(lr)},
{7, INPUT_DESC(rho)}, {8, INPUT_DESC(momentum)}, {9, INPUT_DESC(epsilon)}};
// 输入映射有九个输入var索引为1mg索引为2ms索引为3mom索引为4grad索引为5lr索引为6rho索引为7momentum索引为8epsilon索引为9
ATTR_MAP(ApplyCenteredRMSProp) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
// 输入属性映射rho索引为6momentum索引为7epsilon索引为8
OUTPUT_MAP(ApplyCenteredRMSProp) = {{0, OUTPUT_DESC(var)}};
// 输出映射var的索引为0
REG_ADPT_DESC(ApplyCenteredRMSProp, kNameApplyCenteredRMSProp, ADPT_DESC(ApplyCenteredRMSProp))
// 注册ApplyCenteredRMSProp操作的适配器描述kNameApplyCenteredRMSProp
} // namespace mindspore::transform

View File

@ -0,0 +1,290 @@
/**
* Copyright 2019-2021 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_declare/nonlinear_fuc_ops_declare.h"
namespace mindspore::transform {
// Relu
INPUT_MAP(Relu) = {{1, INPUT_DESC(x)}};
//输入映射x的索引为1
ATTR_MAP(Relu) = EMPTY_ATTR_MAP;
//属性映射,空
OUTPUT_MAP(Relu) = {{0, OUTPUT_DESC(y)}};
//输出映射y的索引为0
REG_ADPT_DESC(Relu, prim::kPrimRelu->name(), ADPT_DESC(Relu))
// 注册Relu操作的适配器描述prim::kPrimRelu->name()
// ReluV2
INPUT_MAP(ReluV2) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(ReluV2) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(ReluV2) = {{0, OUTPUT_DESC(y)}, {1, OUTPUT_DESC(mask)}};
// 输出映射y的索引为0mask索引为1
REG_ADPT_DESC(ReluV2, kNameReluV2, ADPT_DESC(ReluV2))
// 注册ReluV2操作的适配器描述kNameReluV2
// Elu
INPUT_MAP(Elu) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(Elu) = {{"alpha", ATTR_DESC(alpha, AnyTraits<float>())}};
// 属性映射,属性"alpha"的类型为float
OUTPUT_MAP(Elu) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(Elu, kNameElu, ADPT_DESC(Elu))
// 注册Elu操作的适配器描述kNameElu
// EluGrad
INPUT_MAP(EluGrad) = {{1, INPUT_DESC(grads)}, {2, INPUT_DESC(activations)}};
// 输入映射有两个x的索引为1activations索引为2
ATTR_MAP(EluGrad) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(EluGrad) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(EluGrad, kNameEluGrad, ADPT_DESC(EluGrad))
// 注册EluGrad操作的适配器描述kNameEluGrad
// PRelu
INPUT_MAP(PRelu) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(weight)}};
// 输入映射有两个x的索引为1weight索引为2
ATTR_MAP(PRelu) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(PRelu) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(PRelu, kNamePrelu, ADPT_DESC(PRelu))
// 注册PRelu操作的适配器描述kNamePrelu
// PReluGrad
INPUT_MAP(PReluGrad) = {{1, INPUT_DESC(grads)}, {2, INPUT_DESC(features)}, {3, INPUT_DESC(weights)}};
// 输入映射有三个grads的索引为1features索引为2weights索引为3
ATTR_MAP(PReluGrad) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(PReluGrad) = {{0, OUTPUT_DESC(dx)}, {1, OUTPUT_DESC(da)}};
// 输出映射dx的索引为0da索引为1
REG_ADPT_DESC(PReluGrad, kNamePreluGrad, ADPT_DESC(PReluGrad))
// 注册PReluGrad操作的适配器描述kNamePreluGrad
// Selu
INPUT_MAP(Selu) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(Selu) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(Selu) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(Selu, kNameSelu, ADPT_DESC(Selu))
// 注册Selu操作的适配器描述kNameSelu
// Sigmoid
INPUT_MAP(Sigmoid) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(Sigmoid) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(Sigmoid) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(Sigmoid, kNameSigmoid, ADPT_DESC(Sigmoid))
// 注册Sigmoid操作的适配器描述kNameSigmoid
// SigmoidGrad
INPUT_MAP(SigmoidGrad) = {{1, INPUT_DESC(y)}, {2, INPUT_DESC(dy)}};
// 输入映射有两个y的索引为1dy索引为2
ATTR_MAP(SigmoidGrad) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(SigmoidGrad) = {{0, OUTPUT_DESC(z)}};
// 输出映射y的索引为0
REG_ADPT_DESC(SigmoidGrad, kNameSigmoidGrad, ADPT_DESC(SigmoidGrad))
// 注册SigmoidGrad操作的适配器描述kNameSigmoidGrad
// HardSwish
INPUT_MAP(HardSwish) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(HardSwish) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(HardSwish) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(HardSwish, kNameHSwish, ADPT_DESC(HardSwish))
// 注册HardSwish操作的适配器描述kNameHSwish
// HardSwishGrad
INPUT_MAP(HardSwishGrad) = {{1, INPUT_DESC(grad)}, {2, INPUT_DESC(x)}};
// 输入映射有两个grad的索引为1x索引为2
ATTR_MAP(HardSwishGrad) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(HardSwishGrad) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(HardSwishGrad, kNameHSwishGrad, ADPT_DESC(HardSwishGrad))
// 注册HardSwishGrad操作的适配器描述kNameHSwishGrad
// HSigmoid
INPUT_MAP(HardSigmoid) = {{1, INPUT_DESC(input_x)}};
// 输入映射input_x的索引为1
ATTR_MAP(HardSigmoid) = {{"alpha", ATTR_DESC(alpha, AnyTraits<float>())},
{"beta", ATTR_DESC(beta, AnyTraits<float>())}};
// 属性映射,属性"alpha""beta"的类型为float
OUTPUT_MAP(HardSigmoid) = {{0, OUTPUT_DESC(output_y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(HardSigmoid, kNameHSigmoid, ADPT_DESC(HardSigmoid))
// 注册HardSigmoid操作的适配器描述kNameHSigmoid
// Relu6
INPUT_MAP(Relu6) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(Relu6) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(Relu6) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(Relu6, kNameReLU6, ADPT_DESC(Relu6))
// 注册Relu6操作的适配器描述kNameReLU6
// Relu6Grad
INPUT_MAP(Relu6Grad) = {{1, INPUT_DESC(gradients)}, {2, INPUT_DESC(features)}};
// 输入映射有两个gradients的索引为1features索引为2
ATTR_MAP(Relu6Grad) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(Relu6Grad) = {{0, OUTPUT_DESC(backprops)}};
// 输出映射backprops的索引为0
REG_ADPT_DESC(Relu6Grad, kNameReLU6Grad, ADPT_DESC(Relu6Grad))
// 注册Relu6Grad操作的适配器描述kNameReLU6Grad
// Softsign
INPUT_MAP(Softsign) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(Softsign) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(Softsign) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(Softsign, kNameSoftsign, ADPT_DESC(Softsign))
// 注册Softsign操作的适配器描述kNameSoftsign
// Softplus
INPUT_MAP(Softplus) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(Softplus) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(Softplus) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(Softplus, kNameSoftplus, ADPT_DESC(Softplus))
// 注册Softplus操作的适配器描述 kNameSoftplus
// SoftplusGrad
INPUT_MAP(SoftplusGrad) = {{1, INPUT_DESC(gradients)}, {2, INPUT_DESC(features)}};
// 输入映射有两个gradients的索引为1features索引为2
ATTR_MAP(SoftplusGrad) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(SoftplusGrad) = {{0, OUTPUT_DESC(backprops)}};
// 输出映射backprops的索引为0
REG_ADPT_DESC(SoftplusGrad, kNameSoftplusGrad, ADPT_DESC(SoftplusGrad))
// 注册SoftplusGrad操作的适配器描述kNameSoftplusGrad
// ReluGrad
INPUT_MAP(ReluGrad) = {{1, INPUT_DESC(gradients)}, {2, INPUT_DESC(features)}};
// 输入映射有两个gradients的索引为1features索引为2
ATTR_MAP(ReluGrad) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(ReluGrad) = {{0, OUTPUT_DESC(backprops)}};
// 输出映射backprops的索引为0
REG_ADPT_DESC(ReluGrad, prim::kPrimReluGrad->name(), ADPT_DESC(ReluGrad))
// 注册ReluGrad操作的适配器描述prim::kPrimReluGrad->name()
// ReluGradV2
INPUT_MAP(ReluGradV2) = {{1, INPUT_DESC(gradients)}, {2, INPUT_DESC(mask)}};
// 输入映射有两个gradients的索引为1mask索引为2
ATTR_MAP(ReluGradV2) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(ReluGradV2) = {{0, OUTPUT_DESC(backprops)}};
// 输出映射backprops的索引为0
REG_ADPT_DESC(ReluGradV2, kNameReluGradV2, ADPT_DESC(ReluGradV2))
// 注册ReluGradV2操作的适配器描述kNameReluGradV2
// Tanh
INPUT_MAP(Tanh) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(Tanh) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(Tanh) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(Tanh, prim::kPrimTanh->name(), ADPT_DESC(Tanh))
// 注册Tanh操作的适配器描述prim::kPrimTanh->name()
// TanhGrad
INPUT_MAP(TanhGrad) = {{1, INPUT_DESC(y)}, {2, INPUT_DESC(dy)}};
// 输入映射有两个y的索引为1dy索引为2
ATTR_MAP(TanhGrad) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(TanhGrad) = {{0, OUTPUT_DESC(z)}};
// 输出映射z的索引为0
REG_ADPT_DESC(TanhGrad, prim::kPrimTanhGrad->name(), ADPT_DESC(TanhGrad))
// 注册NPUTanhGrad操作的适配器描述prim::kPrimTanhGrad->name()
// Mish
INPUT_MAP(Mish) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(Mish) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(Mish) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(Mish, kNameMish, ADPT_DESC(Mish))
// 注册Mish操作的适配器描述kNameMish
// GeLU
INPUT_MAP(Gelu) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(Gelu) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(Gelu) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(Gelu, prim::kPrimGeLU->name(), ADPT_DESC(Gelu))
// 注册Gelu操作的适配器描述prim::kPrimGeLU->name()
// GeLUGrad
INPUT_MAP(GeluGrad) = {{1, INPUT_DESC(dy)}, {2, INPUT_DESC(x)}, {3, INPUT_DESC(y)}};
// 输入映射有三个x的索引为1activations索引为2y索引为3
ATTR_MAP(GeluGrad) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(GeluGrad) = {{0, OUTPUT_DESC(z)}};
// 输出映射z的索引为0
REG_ADPT_DESC(GeluGrad, prim::kPrimGeLUGrad->name(), ADPT_DESC(GeluGrad))
// 注册GeluGrad操作的适配器描述prim::kPrimGeLUGrad->name()
// FastGeLU
INPUT_MAP(FastGelu) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(FastGelu) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(FastGelu) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(FastGelu, prim::kPrimFastGeLU->name(), ADPT_DESC(FastGelu))
// 注册FastGelu操作的适配器描述 prim::kPrimFastGeLU->name()
// FastGeLUGrad
INPUT_MAP(FastGeluGrad) = {{1, INPUT_DESC(dy)}, {2, INPUT_DESC(x)}};
// 输入映射有两个dy的索引为1x索引为2
ATTR_MAP(FastGeluGrad) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(FastGeluGrad) = {{0, OUTPUT_DESC(z)}};
// 输出映射z的索引为0
REG_ADPT_DESC(FastGeluGrad, prim::kPrimFastGeLUGrad->name(), ADPT_DESC(FastGeluGrad))
// 注册FastGeluGrad操作的适配器描述 prim::kPrimFastGeLUGrad->name()
// LeakyRelu
INPUT_MAP(LeakyRelu) = {{1, INPUT_DESC(x)}};
// 输入映射x的索引为1
ATTR_MAP(LeakyRelu) = {{"alpha", ATTR_DESC(negative_slope, AnyTraits<float>())}};
// 属性映射,属性"alpha"的类型为float
OUTPUT_MAP(LeakyRelu) = {{0, OUTPUT_DESC(y)}};
// 输出映射y的索引为0
REG_ADPT_DESC(LeakyRelu, prim::kPrimLeakyRelu->name(), ADPT_DESC(LeakyRelu))
// 注册LeakyRelu操作的适配器描述 prim::kPrimLeakyRelu->name()
} // namespace mindspore::transform

View File

@ -0,0 +1,49 @@
/**
* 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_declare/npu_loss_scale_ops_declare.h"
namespace mindspore::transform {
// NPUGetFloatStatus
INPUT_MAP(NPUGetFloatStatus) = {{1, INPUT_DESC(addr)}};
// 输入映射addr索引为1
OUTPUT_MAP(NPUGetFloatStatus) = {{0, OUTPUT_DESC(data)}};
// 输出映射data索引为0
ATTR_MAP(NPUGetFloatStatus) = EMPTY_ATTR_MAP;
//属性映射,空
REG_ADPT_DESC(NPUGetFloatStatus, kNameNPUGetFloatStatus, ADPT_DESC(NPUGetFloatStatus))
// 注册NPUGetFloatStatus操作的适配器描述kNameNPUGetFloatStatus
// NPUAllocFloatStatus
INPUT_MAP(NPUAllocFloatStatus) = EMPTY_INPUT_MAP;
// 输入映射,空
ATTR_MAP(NPUAllocFloatStatus) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(NPUAllocFloatStatus) = {{0, OUTPUT_DESC(data)}};
// 输出映射data索引为0
REG_ADPT_DESC(NPUAllocFloatStatus, kNameNPUAllocFloatStatus, ADPT_DESC(NPUAllocFloatStatus))
// 注册NPUAllocFloatStatus操作的适配器描述kNameNPUAllocFloatStatus
// NPUClearFloatStatus
INPUT_MAP(NPUClearFloatStatus) = {{1, INPUT_DESC(addr)}};
// 输入映射addr索引为1
OUTPUT_MAP(NPUClearFloatStatus) = {{0, OUTPUT_DESC(data)}};
// 输出映射data索引为0
ATTR_MAP(NPUClearFloatStatus) = EMPTY_ATTR_MAP;
//属性映射,空
REG_ADPT_DESC(NPUClearFloatStatus, kNameNPUClearFloatStatus, ADPT_DESC(NPUClearFloatStatus))
// 注册NPUClearFloatStatus操作的适配器描述kNameNPUClearFloatStatus
} // namespace mindspore::transform

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,824 @@
/**
* Copyright 2019-2021 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.h"
#include "utils/check_convert_utils.h"
namespace mindspore {
namespace transform {
// 静态函数 CustomInferFunc
// 参数const Operator &,一个操作的引用
// 返回uint32_t一个无符号整数
static uint32_t CustomInferFunc(const Operator &) { return 0; } // 这个函数返回固定值 0可以根据具体需求实现不同的逻辑来计算返回值
// 该函数用于判断给定的操作是否为自定义操作
// 参数opOperatorPtr类型的操作指针
// 返回bool类型表示给定操作是否为自定义操作
bool OpAdapterImpl::IsCustomOp(const OperatorPtr &op) {
MS_EXCEPTION_IF_NULL(op); // 检查操作指针是否为空,若为空则抛出异常
auto it = cus_input_map_->find(op->GetOpType()); // 在自定义操作映射表中查找给定操作的类型
if (it == cus_input_map_->end()) {
return false; // 若在映射表中未找到该操作类型则返回false表示该操作不是自定义操作
}
return true; // 若在映射表中找到了该操作类型则返回true表示该操作是自定义操作
}
// 该函数用于生成自定义操作的输入映射表
// 参数opCusOperatorPtr类型的自定义操作指针
// 参数primPrimitivePtr类型的操作原语指针
// 返回Status类型表示操作执行的状态
Status OpAdapterImpl::GenerateCustomOpInputMap(const CusOperatorPtr &op, const PrimitivePtr &prim) {
MS_EXCEPTION_IF_NULL(op); // 检查自定义操作指针是否为空,若为空则抛出异常
MS_EXCEPTION_IF_NULL(prim); // 检查操作原语指针是否为空,若为空则抛出异常
// Create the map of custom op from input index to input name.
// 创建用于存储自定义操作输入映射的 map键为输入索引值为输入名称
mindspore::HashMap<int, std::string> input_map;
auto value = prim->GetAttr("input_names"); // 获取操作原语中名为 "input_names" 的属性值
if (value == nullptr) { // 如果获取的属性值为空,表示该自定义操作没有输入映射
(*cus_output_map_)[prim->name()] = input_map; //将一个空的映射存储到 cus_output_map_ 中
return NOT_FOUND; //返回 NOT_FOUND 状态
}
// 将属性值转换为 std::vector<std::string> 类型
auto input_names = GetValue<const std::vector<std::string>>(value);
for (size_t i = 0; i < input_names.size(); ++i) { // 遍历输入名称列表,将索引与输入名称的映射存储到 input_map 中,并将输入名称注册到自定义操作中
// input_map begin form 1
// 输入索引从 1 开始
input_map[i + 1] = input_names[i];
op->CustomInputRegister(input_names[i]);
}
// 如果在 cus_input_map_ 中未找到该自定义操作的输入映射,则将 input_map 存储到 cus_input_map_ 中
if (cus_input_map_->find(prim->name()) == cus_input_map_->end()) {
(*cus_input_map_)[prim->name()] = input_map;
}
return SUCCESS; // 操作执行成功,返回 SUCCESS 状态
}
// 该函数用于生成自定义操作的输出映射表
// 参数opCusOperatorPtr类型的自定义操作指针
// 参数primPrimitivePtr类型的操作原语指针
// 返回Status类型表示操作执行的状态
Status OpAdapterImpl::GenerateCustomOpOutputMap(const CusOperatorPtr &op, const PrimitivePtr &prim) {
MS_EXCEPTION_IF_NULL(op); // 检查自定义操作指针是否为空,若为空则抛出异常
MS_EXCEPTION_IF_NULL(prim); // 检查操作原语指针是否为空,若为空则抛出异常
// Create the map of custom op from output index to output name.
// 创建用于存储自定义操作输出映射的 map键为输出索引值为输出名称
mindspore::HashMap<int, std::string> output_map;
// 获取操作原语中名为 "output_names" 的属性值
auto value = prim->GetAttr("output_names");
if (value == nullptr) { // 如果获取的属性值为空,表示该自定义操作没有输出映射
// generate a empty output_map for it
(*cus_output_map_)[prim->name()] = output_map; //将一个空的映射存储到 cus_output_map_ 中
return NOT_FOUND; //返回 NOT_FOUND 状态
}
// 将属性值转换为 std::vector<std::string> 类型
auto output_names = GetValue<const std::vector<std::string>>(value);
for (size_t i = 0; i < output_names.size(); ++i) { // 遍历输出名称列表,将索引与输出名称的映射存储到 output_map 中,并将输出名称注册到自定义操作中
// output_map begin form 0
// 输出索引从 0 开始
output_map[i] = output_names[i];
op->CustomOutputRegister(output_names[i]);
}
// 如果在 cus_output_map_ 中未找到该自定义操作的输出映射,则将 output_map 存储到 cus_output_map_ 中
if (cus_output_map_->find(prim->name()) == cus_output_map_->end()) {
(*cus_output_map_)[prim->name()] = output_map;
}
return SUCCESS; // 操作执行成功,返回 SUCCESS 状态
}
// 该函数用于生成自定义操作
// 参数anfAnfNodePtr类型的节点指针
// 返回OperatorPtr类型表示生成的自定义操作指针
OperatorPtr OpAdapterImpl::GenerateCustomOp(const AnfNodePtr anf) {
MS_EXCEPTION_IF_NULL(anf); // 检查节点指针是否为空,若为空则抛出异常
auto node = anf->cast<CNodePtr>(); // 将节点转换为 CNodePtr 类型
if (node == nullptr) { // 如果转换失败,返回空指针
return nullptr;
}
if (node->inputs().empty()) { // 如果节点输入为空,抛出异常
MS_LOG(EXCEPTION) << "length of node inputs is empty";
}
auto prim = GetValueNode<PrimitivePtr>(node->inputs()[0]); // 获取节点的原语指针
MS_EXCEPTION_IF_NULL(prim); // 检查原语指针是否为空,若为空则抛出异常
// 创建 ge::CustomOperator 类型的自定义操作,并传入节点的全名和原语的名称
auto op = std::make_shared<ge::CustomOperator>(node->fullname_with_scope(), prim->name());
// 生成自定义操作的输入映射表,并注册到自定义操作中
if (GenerateCustomOpInputMap(op, prim) != SUCCESS) {
MS_LOG(WARNING) << "Custom op node has no input_names, op[" << prim->name() << "].";
}
// 生成自定义操作的输出映射表,并注册到自定义操作中
if (GenerateCustomOpOutputMap(op, prim) != SUCCESS) {
MS_LOG(WARNING) << "Custom op node has no output_names, op[" << prim->name() << "].";
}
// 注册自定义推理函数
op->CustomInferFuncRegister(CustomInferFunc);
// 返回生成的自定义操作指针
return op;
}
// 该函数用于设置操作的子图函数
// 参数opOperatorPtr类型的操作指针
// 参数indexint类型的索引值
// 参数branchesstd::shared_ptr<std::vector<DfGraph>>类型的子图指针
// 返回Status类型表示操作执行的状态
Status OpAdapterImpl::SetOpSubgraphFunc(const OperatorPtr &op, int index,
const std::shared_ptr<std::vector<DfGraph>> &branches) {
MS_EXCEPTION_IF_NULL(op); // 检查操作指针是否为空,若为空则抛出异常
auto it = dyn_subgraph_map_.find(index); // 在动态子图映射表中查找给定索引的映射
if (it != dyn_subgraph_map_.end()) { // 如果找到了映射
auto size = branches->size(); // 获取子图指针中的子图数量
it->second.create_dyn_subgraph(op, static_cast<unsigned int>(size)); // 创建操作的动态子图
for (size_t i = 0; i < size; i++) { // 设置操作的子图
it->second.set_subgraph(op, static_cast<unsigned int>(i), std::make_shared<DfGraph>((*branches)[i]));
}
return SUCCESS; // 操作执行成功,返回 SUCCESS 状态
}
return NOT_FOUND; // 未找到对应的映射,返回 NOT_FOUND 状态
}
// 该函数用于设置自定义操作的输入
// 参数opCusOperatorPtr类型的自定义操作指针
// 参数indexint类型的输入索引
// 参数inputOperatorPtr类型的输入操作指针
// 返回Status类型表示操作执行的状态
Status OpAdapterImpl::SetCustomOpInput(const CusOperatorPtr &op, int index, const OperatorPtr &input) {
MS_EXCEPTION_IF_NULL(op); // 检查自定义操作指针是否为空,若为空则抛出异常
MS_EXCEPTION_IF_NULL(input); // 检查输入操作指针是否为空,若为空则抛出异常
auto it = cus_input_map_->find(op->GetOpType()); // 在自定义操作输入映射表中查找给定自定义操作类型的映射
if (it == cus_input_map_->end()) { // 如果未找到映射,则返回 NOT_FOUND 状态
return NOT_FOUND;
}
mindspore::HashMap<int, std::string> &input_map = it->second; // 获取自定义操作输入映射表
if ((input_map.find(index) != input_map.end())) { // 如果在输入映射表中找到给定索引的映射
MS_LOG(DEBUG) << "Link op " << input->GetName() << " to " << op->GetName() << ":" << input_map[index];
(void)op->SetInput(input_map[index], *input); // 设置自定义操作的输入
return SUCCESS; // 操作执行成功,返回 SUCCESS 状态
}
return NOT_FOUND; // 未找到给定索引的映射,返回 NOT_FOUND 状态
}
// 该函数用于设置普通操作的输入
// 参数opOperatorPtr类型的普通操作指针
// 参数indexint类型的输入索引
// 参数inputOperatorPtr类型的输入操作指针
// 返回Status类型表示操作执行的状态
Status OpAdapterImpl::SetNormalOpInput(const OperatorPtr &op, int index, const OperatorPtr &input) {
MS_EXCEPTION_IF_NULL(op); // 检查普通操作指针是否为空,若为空则抛出异常
auto it = input_map_.find(index); // 在输入映射表中查找给定索引的映射
if (input != nullptr && it != input_map_.end()) { // 如果输入操作指针不为空,并且找到了索引的映射
MS_LOG(DEBUG) << "Link op " << input->GetName() << " to " << op->GetName() << ":" << it->second.name;
it->second.set_op(op, input); // 设置普通操作的输入
return SUCCESS; // 操作执行成功,返回 SUCCESS 状态
}
return NOT_FOUND; // 输入操作指针为空或未找到给定索引的映射,返回 NOT_FOUND 状态
}
// 该函数用于设置操作的输入
// 参数opOperatorPtr类型的操作指针
// 参数indexint类型的输入索引
// 参数inputOperatorPtr类型的输入操作指针
// 返回int类型表示操作执行的状态其中非负数为成功状态负数为失败状态
int OpAdapterImpl::setInput(const OperatorPtr &op, int index, const OperatorPtr &input) {
if (IsCustomOp(op)) { // 如果是自定义操作
auto cus_op = std::dynamic_pointer_cast<CustomOperator>(op); // 将操作指针转换为自定义操作指针
return static_cast<int>(SetCustomOpInput(cus_op, index, input)); // 调用 SetCustomOpInput 设置自定义操作的输入,并返回状态
} else { // 如果是普通操作
return static_cast<int>(SetNormalOpInput(op, index, input));// 调用 SetNormalOpInput 设置普通操作的输入,并返回状态
}
}
// 该函数用于设置自定义操作的输入
// 参数opCusOperatorPtr类型的自定义操作指针
// 参数indexint类型的输入索引
// 参数handleOutHandler类型的输出处理器
// 返回Status类型表示操作执行的状态
Status OpAdapterImpl::SetCustomOpInput(const CusOperatorPtr &op, int index, const OutHandler &handle) {
MS_EXCEPTION_IF_NULL(op); // 检查自定义操作指针是否为空,若为空则抛出异常
auto it = cus_input_map_->find(op->GetOpType()); // 在输入映射表中查找给定自定义操作类型的映射
if (it == cus_input_map_->end()) { // 如果未找到给定自定义操作类型的映射
return NOT_FOUND; // 返回 NOT_FOUND 状态,表示未找到该类型的自定义操作
}
mindspore::HashMap<int, std::string> &input_map = it->second; // 获取输入映射表中该自定义操作类型的映射
if ((handle.op != nullptr) && (input_map.find(index) != input_map.end())) { // 如果输出处理器中的操作指针不为空,并且找到了给定索引的映射
if (handle.out.empty()) { // 如果输出处理器中输出名称为空
MS_LOG(DEBUG) << "Link op " << handle.op->GetName() << " to " << op->GetName() << ":" << input_map[index];
(void)op->SetInput(input_map[index], *(handle.op)); // 设置自定义操作的输入
} else { // 如果输出处理器中输出名称不为空
MS_LOG(DEBUG) << "Link op " << handle.op->GetName() << ":" << handle.out << " to " << op->GetName() << ":"
<< input_map[index];
(void)op->SetInput(input_map[index], *(handle.op), handle.out); // 设置自定义操作的输入和输出名称
}
return SUCCESS; // 操作执行成功,返回 SUCCESS 状态
}
return NOT_FOUND; // 输出处理器中的操作指针为空或未找到给定索引的映射,返回 NOT_FOUND 状态
}
// 该函数用于设置普通操作的输入
// 参数opOperatorPtr类型的操作指针
// 参数indexint类型的输入索引
// 参数handleOutHandler类型的输出处理器
// 返回Status类型表示操作执行的状态
Status OpAdapterImpl::SetNormalOpInput(const OperatorPtr &op, int index, const OutHandler &handle) {
MS_EXCEPTION_IF_NULL(op); // 检查操作指针是否为空,若为空则抛出异常
auto it = input_map_.find(index); // 在输入映射表中查找给定索引的映射
if ((handle.op != nullptr) && (it != input_map_.end())) { // 如果输出处理器中的操作指针不为空,并且找到了给定索引的映射
if (handle.out.empty()) { // 如果输出处理器中输出名称为空
MS_LOG(DEBUG) << "Link op " << handle.op->GetName() << " to " << op->GetName() << ":" << it->second.name;
it->second.set_op(op, handle.op); // 设置普通操作的输入
} else { // 如果输出处理器中输出名称不为空
MS_LOG(DEBUG) << "Link op " << handle.op->GetName() << ":" << handle.out << " to " << op->GetName() << ":"
<< it->second.name;
it->second.set_handle(op, handle); // 设置普通操作的输入和输出处理器
}
return SUCCESS; // 操作执行成功,返回 SUCCESS 状态
}
return NOT_FOUND; // 输出处理器中的操作指针为空或未找到给定索引的映射,返回 NOT_FOUND 状态
}
// 该函数用于设置操作的输入
// 参数opOperatorPtr类型的操作指针
// 参数indexint类型的输入索引
// 参数handleOutHandler类型的输出处理器
// 返回int类型表示操作执行的结果
int OpAdapterImpl::setInput(const OperatorPtr &op, int index, const OutHandler &handle) {
if (IsCustomOp(op)) { // 如果是自定义操作
auto cus_op = std::dynamic_pointer_cast<CustomOperator>(op); // 将操作指针转换为自定义操作指针
return static_cast<int>(SetCustomOpInput(cus_op, index, handle)); // 调用 SetCustomOpInput 函数设置自定义操作的输入,并将结果转换为整数返回
} else { // 如果不是自定义操作
return static_cast<int>(SetNormalOpInput(op, index, handle)); // 调用 SetNormalOpInput 函数设置普通操作的输入,并将结果转换为整数返回
}
}
// 该函数用于设置操作的动态输入
// 参数opOperatorPtr类型的操作指针
// 参数indexint类型的输入索引
// 参数handler_vecstd::shared_ptr<std::vector<OutHandler>>类型的输出处理器向量
// 返回int类型表示操作执行的结果
int OpAdapterImpl::setInput(const OperatorPtr &op, int index,
const std::shared_ptr<std::vector<OutHandler>> &handler_vec) {
MS_EXCEPTION_IF_NULL(handler_vec); // 检查输出处理器向量的有效性
if (IsCustomOp(op)) { // 如果是自定义操作
MS_LOG(ERROR) << "Custom Op do not support dynamic input"; // 输出错误信息,自定义操作不支持动态输入
return static_cast<int>(FAILED); // 返回执行失败的状态码
}
MS_EXCEPTION_IF_NULL(op); // 检查操作指针的有效性
auto it = dyn_input_map_.find(index); // 查找对应索引的动态输入信息
if (it != dyn_input_map_.end()) { // 如果找到了对应索引的动态输入信息
it->second.create_dyn_input(op, static_cast<unsigned int>(handler_vec->size())); // 创建动态输入
for (unsigned int i = 0; i < handler_vec->size(); ++i) { // 遍历输出处理器向量
OutHandler h = (*handler_vec)[i]; // 获取输出处理器
MS_EXCEPTION_IF_NULL(h.op); // 检查输出处理器的操作指针有效性
if (h.out.empty()) { // 如果输出处理器中没有指定输出名称
MS_LOG(DEBUG) << "Link op " << h.op->GetName() << " to " << op->GetName() << ":" << it->second.name;
// 输出调试信息,将输出处理器中的操作链接为动态输入的一部分
it->second.set_op(op, (i), h.op);
} else { // 如果输出处理器中指定了输出名称
MS_LOG(DEBUG) << "Link op " << h.op->GetName() << ":" << h.out << " to " << op->GetName() << ":"
<< it->second.name;
// 输出调试信息,将输出处理器中的输出链接为动态输入的一部分
it->second.set_handle(op, i, h);
}
}
return 0; // 返回执行成功的状态码
}
return static_cast<int>(NOT_FOUND); // 返回未找到的状态码
}
// 该函数用于获取操作的输出处理器
// 参数opOperatorPtr类型的操作指针
// 参数indexint类型的输出索引
// 返回OutHandler类型的输出处理器
OutHandler OpAdapterImpl::getOutput(const OperatorPtr &op, int index) {
MS_EXCEPTION_IF_NULL(op);// 检查操作指针的有效性
if (IsCustomOp(op)) { // 如果是自定义操作
return getCustomOutput(op, index); // 调用 getCustomOutput 函数获取自定义操作的输出处理器
}
return getNormalOutput(op, index); // 否则,调用 getNormalOutput 函数获取普通操作的输出处理器
}
// 该函数用于获取自定义操作的输出处理器
// 参数opOperatorPtr类型的操作指针
// 参数indexint类型的输出索引
// 返回OutHandler类型的输出处理器
OutHandler OpAdapterImpl::getCustomOutput(const OperatorPtr &op, int index) {
MS_EXCEPTION_IF_NULL(op); // 检查操作指针的有效性
auto it = cus_output_map_->find(op->GetOpType());
if (it == cus_output_map_->end()) { // 查找自定义操作的输出映射
MS_LOG(ERROR) << "OpAdpator(" << op->GetName() << ") has both OUTPUT is not supported!"; // 如果没有找到输出映射,输出错误日志
return OutHandler(); // 返回空的输出处理器
}
mindspore::HashMap<int, std::string> &output_map = it->second; // 获取输出映射
if ((output_map.find(index) != output_map.end())) { // 检查是否找到输出索引对应的输出名称
return OutHandler(op, output_map[index]); // 如果找到,创建并返回输出处理器
}
MS_LOG(ERROR) << "OpAdpator(" << op->GetName() << ") has no OUTPUT index(" << index << ")!"; // 如果没有找到输出索引,输出错误日志
return OutHandler(); // 返回空的输出处理器
}
// 该函数用于获取普通操作的输出处理器
// 参数opOperatorPtr类型的操作指针
// 参数indexint类型的输出索引
// 返回OutHandler类型的输出处理器
OutHandler OpAdapterImpl::getNormalOutput(const OperatorPtr &op, int index) {
MS_EXCEPTION_IF_NULL(op); // 检查操作指针的有效性
if (!dyn_output_map_.empty() && !output_map_.empty()) { // 检查是否同时存在动态输出映射和普通输出映射
MS_LOG(ERROR) << "OpAdpator(" << op->GetName() << ") has both OUTPUT and DYN_OUTPUT is not supported!"; // 如果同时存在动态输出映射和普通输出映射,输出错误日志
return OutHandler(); // 返回空的输出处理器
}
auto it = output_map_.find(index); // 在普通输出映射中查找指定的输出索引
if (it != output_map_.end()) { // 如果找到了输出索引
return OutHandler(op, it->second.name); // 创建并返回输出处理器
} else if (!dyn_output_map_.empty()) { // 如果普通输出映射为空,但动态输出映射不为空
return OutHandler(op, dyn_output_map_.begin()->second.name + std::to_string(index)); // 根据动态输出映射的第一个输出名称构造输出处理器
} else { // 如果既没有普通输出映射,也没有动态输出映射
MS_LOG(ERROR) << "OpAdpator(" << op->GetName() << ") has no OUTPUT and DYN_OUTPUT index(" << index << ")!"; // 输出错误日志
return OutHandler(); // 返回空的输出处理器
}
}
// 该函数用于更新单个输出的描述符
// 参数opOperatorPtr类型的操作指针
// 参数shpabstract::BaseShapePtr类型的输出形状指针
// 参数typeTypePtr类型的输出数据类型
// 参数formatstring类型的输出数据格式
// 返回Status类型的状态SUCCESS表示成功FAILED表示失败
Status OpAdapterImpl::UpdateSingleOutputDesc(const OperatorPtr &op, const abstract::BaseShapePtr &shp,
const TypePtr &type, const std::string &format) {
MS_EXCEPTION_IF_NULL(type); // 检查输出数据类型的有效性
auto desc = CreateOutputDesc(dyn_cast<abstract::Shape>(shp), type, format);
if (desc == nullptr) { // 检查输出描述符是否为空
MS_LOG(ERROR) << "Update output descriptor failed!"; // 输出错误日志
return FAILED; // 返回失败状态
}
if (IsCustomOp(op)) { // 检查是否为自定义操作
if (cus_output_map_->find(op->GetOpType()) == cus_output_map_->end() ||
((*cus_output_map_)[op->GetOpType()].empty())) { // 检查是否存在自定义输出映射,并且不为空
MS_LOG(ERROR) << "This op does not create custom output map"; // 输出错误日志
return FAILED; // 返回失败状态
}
auto cus_op = std::dynamic_pointer_cast<CustomOperator>(op); // 将操作指针转换为自定义操作指针
MS_EXCEPTION_IF_NULL(cus_op); // 检查自定义操作指针的有效性
mindspore::HashMap<int, std::string> output_map = (*cus_output_map_)[op->GetOpType()]; // 获取自定义输出映射
(void)cus_op->UpdateOutputDesc(output_map[0], *desc); // 更新自定义操作的输出描述符
} else { // 如果不是自定义操作
if (output_map_.empty()) { // 检查普通输出映射是否为空
MS_LOG(INFO) << "This op does not have output map"; // 输出提示信息
return FAILED; // 返回失败状态
}
output_map_.begin()->second.update_out_desc(op, *desc); // 更新普通操作的输出描述符
}
return SUCCESS; // 返回成功状态
}
// 该函数用于获取自定义操作的输出数量
// 参数cus_opCusOperatorPtr类型的自定义操作指针
// 返回size_t类型的输出数量表示自定义操作的输出数量
size_t OpAdapterImpl::GetCustomOpOutputSize(const CusOperatorPtr &cus_op) {
MS_EXCEPTION_IF_NULL(cus_op); // 检查自定义操作指针的有效性
if (cus_output_map_->find(cus_op->GetOpType()) == cus_output_map_->end()) { // 检查是否存在自定义输出映射
MS_LOG(ERROR) << "This op does not create custom output map"; // 输出错误日志
return 0; // 返回0表示自定义操作的输出数量为0
}
size_t output_size = (*cus_output_map_)[cus_op->GetOpType()].size(); // 获取自定义操作的输出数量
return output_size; // 返回自定义操作的输出数量
}
// 该函数用于创建输出的GeTensorDesc对象用于描述输出的形状、数据类型和格式。
// 参数:
// - shape_ptr: abstract::ShapePtr类型的形状指针表示输出的形状。
// - type: TypePtr类型的类型指针表示输出的数据类型。
// - format: std::string类型的格式字符串表示输出的数据格式。
// 返回:
// - std::shared_ptr<GeTensorDesc>类型的指针表示输出的GeTensorDesc对象。
std::shared_ptr<GeTensorDesc> OpAdapterImpl::CreateOutputDesc(const abstract::ShapePtr &shape_ptr, const TypePtr &type,
const std::string &format) {
if (type == nullptr) { // 检查输出的数据类型是否为空
MS_LOG(ERROR) << "Type ptr is nullptr"; // 输出错误日志
return nullptr; // 返回空指针,表示创建输出描述失败
}
TypeId me_type = type->type_id(); // 获取输出的数据类型ID
if (kObjectTypeTensorType == me_type) { // 如果输出类型是TensorType
me_type = dyn_cast<TensorType>(type)->element()->type_id(); // 获取Tensor元素的数据类型ID
}
// 调用TransformUtil::GetGeTensorDesc函数创建GeTensorDesc对象并返回
return TransformUtil::GetGeTensorDesc((shape_ptr == nullptr) ? ShapeVector{} : shape_ptr->shape(), me_type, format);
}
// 该函数用于更新多输出的输出描述。
// 参数:
// - op: OperatorPtr类型的指针表示要更新输出描述的运算符。
// - shp: abstract::BaseShapePtr类型的形状指针表示输出的形状。
// - type: TypePtr类型的类型指针表示输出的数据类型。
// - format: std::string类型的格式字符串表示输出的数据格式。
// 返回:
// - Status类型表示更新输出描述的操作状态。
Status OpAdapterImpl::UpdateMultiOutputDesc(const OperatorPtr &op, const abstract::BaseShapePtr &shp,
const TypePtr &type, const std::string &format) {
auto tuple_shp = dyn_cast<abstract::TupleShape>(shp); // 转换成TupleShape类型
MS_EXCEPTION_IF_NULL(tuple_shp);
size_t output_size = 0;
bool is_custom_op = IsCustomOp(op); // 检查是否为自定义运算符
if (is_custom_op) {
output_size = GetCustomOpOutputSize(std::dynamic_pointer_cast<CustomOperator>(op)); // 获取自定义运算符的输出数量
} else {
output_size = output_map_.size(); // 获取普通运算符的输出数量
}
if (output_size == 0) { // 如果输出数量为0返回失败状态
MS_LOG(INFO) << "This op does not have output map";
return FAILED;
}
if (output_size != tuple_shp->shape().size()) { // 检查输出数量是否与TupleShape的大小相等
MS_LOG(ERROR) << "output_map is not equal tuple_shape size";
return FAILED; // 如果输出数量不相等,返回失败状态
}
for (size_t i = 0; i < tuple_shp->shape().size(); ++i) {
auto tuple_type = dyn_cast<Tuple>(type); // 转换成Tuple类型
MS_EXCEPTION_IF_NULL(tuple_type);
TypePtr type_elem = tuple_type->elements()[i]; // 获取Tuple中第i个元素的类型
// 调用CreateOutputDesc函数创建GeTensorDesc对象
auto desc = CreateOutputDesc(dyn_cast<abstract::Shape>(tuple_shp->shape()[i]), type_elem, format);
if (desc == nullptr) {
MS_LOG(ERROR) << "Create output descriptor failed!";
return FAILED; // 如果创建输出描述失败,返回失败状态
}
if (is_custom_op) { // 如果是自定义运算符
// 调用CustomOperator的UpdateOutputDesc函数更新输出描述
(void)std::dynamic_pointer_cast<CustomOperator>(op)->UpdateOutputDesc((*cus_output_map_)[op->GetOpType()][i],
*desc);
} else {
auto it = output_map_.find(i);
if (it != output_map_.end()) {
it->second.update_out_desc(op, *desc); // 更新普通运算符的输出描述
}
}
}
return SUCCESS; // 返回成功状态
}
// 该函数用于创建GeTensorDesc对象表示给定AnfNode的描述。
// 参数:
// - node: AnfNodePtr类型的指针表示要创建描述的节点。
// - format: std::string类型的格式字符串表示描述的数据格式。
// 返回:
// - std::shared_ptr<GeTensorDesc>类型的指针表示创建的GeTensorDesc对象。
std::shared_ptr<GeTensorDesc> OpAdapterImpl::CreateNodeDesc(const AnfNodePtr &node, const std::string &format) {
MS_EXCEPTION_IF_NULL(node);
TypeId me_type = node->Type()->type_id(); // 获取节点的数据类型
if (kObjectTypeTensorType == me_type) {
me_type = dyn_cast<TensorType>(node->Type())->element()->type_id();
}
// 检查数据类型是否有效如果无效则返回nullptr
if (me_type <= kNumberTypeBegin || me_type >= kNumberTypeEnd) {
return nullptr;
}
std::vector<int64_t> shape;
auto shape_ptr = dyn_cast<abstract::Shape>(node->Shape());
if (shape_ptr != nullptr) { // 获取节点的形状
shape = shape_ptr->shape();
}
// 调用TransformUtil的GetGeTensorDesc函数创建GeTensorDesc对象
auto desc = TransformUtil::GetGeTensorDesc(shape, me_type, format);
// 检查是否成功创建GeTensorDesc对象如果失败返回nullptr
if (desc == nullptr) {
MS_LOG(ERROR) << "Update output descriptor failed!";
return nullptr;
}
return desc; // 返回创建的GeTensorDesc对象的指针
}
// 该函数用于更新普通算子的输入描述。
// 参数:
// - op: OperatorPtr类型的指针表示要更新输入描述的算子。
// - node: AnfNodePtr类型的指针表示算子对应的CNode节点。
// - format: std::string类型的格式字符串表示描述的数据格式。
void OpAdapterImpl::UpdateNormalOpInputDesc(const OperatorPtr &op, const AnfNodePtr &node, const std::string format) {
if (op == nullptr) { //检查算子是否为空,如果为空则打印错误日志并返回
MS_LOG(ERROR) << "op is nullptr";
return;
}
MS_EXCEPTION_IF_NULL(node);
auto inputs = node->cast<CNodePtr>()->inputs(); //遍历CNode节点的输入从第二个输入开始因为第一个输入是算子本身
for (size_t i = 1; i < inputs.size(); ++i) { // 对于输入节点,查找是否有对应的输入描述
auto it = input_map_.find(i);
if (it != input_map_.end()) { //如果找到则调用CreateNodeDesc函数创建新的输入描述并使用该描述更新输入节点的描述。
auto desc = CreateNodeDesc(inputs[i], format);
if (desc == nullptr) { // 如果创建描述失败,则继续处理下一个输入节点。
continue;
}
it->second.update_input_desc(op, *desc);
}
}
}
// 该函数用于更新自定义算子的输入描述。
// 参数:
// - op: CusOperatorPtr类型的指针表示要更新输入描述的自定义算子。
// - node: AnfNodePtr类型的指针表示自定义算子对应的CNode节点。
// - format: std::string类型的格式字符串表示描述的数据格式。
void OpAdapterImpl::UpdateCustomOpInputDesc(const CusOperatorPtr &op, const AnfNodePtr &node,
const std::string format) {
if (op == nullptr) { //检查算子是否为空,如果为空则打印错误日志并返回
MS_LOG(ERROR) << "op is nullptr";
return;
}
MS_EXCEPTION_IF_NULL(node);
//检查自定义算子是否创建了输入映射,如果未创建则打印错误日志并返回
if (cus_input_map_->find(op->GetOpType()) == cus_input_map_->end() || ((*cus_input_map_)[op->GetOpType()].empty())) {
MS_LOG(ERROR) << "This op does not create custom input map";
return;
}
//遍历CNode节点的输入从第二个输入开始因为第一个输入是算子本身
mindspore::HashMap<int, std::string> &input_map = (*cus_input_map_)[op->GetOpType()];
auto inputs = node->cast<CNodePtr>()->inputs();
for (size_t i = 1; i < inputs.size(); ++i) { // 对于输入节点,查找是否有对应的输入描述
if (input_map.find(i) != input_map.end()) { //如果找到则调用CreateNodeDesc函数创建新的输入描述并使用该描述更新自定义算子的输入描述。
auto desc = CreateNodeDesc(inputs[i], format);
if (desc == nullptr) { // 如果创建描述失败,则继续处理下一个输入节点。
continue;
}
(void)op->UpdateInputDesc(input_map[i], *desc);
}
}
}
// 该函数用于更新算子的输入描述。
// 参数:
// - op: OperatorPtr类型的指针表示要更新输入描述的算子。
// - node: AnfNodePtr类型的指针表示算子对应的CNode节点。
void OpAdapterImpl::updateInputDesc(const OperatorPtr &op, const AnfNodePtr &node) {
MS_EXCEPTION_IF_NULL(op); //检查算子和节点是否为空,如果为空则抛出异常。
MS_EXCEPTION_IF_NULL(node);
std::string format = GetOpIOFormat(node); //获取节点的数据格式即IO格式通过调用GetOpIOFormat函数。
if (IsCustomOp(op)) { //检查算子是否为自定义算子
auto cus_op = std::dynamic_pointer_cast<CustomOperator>(op); //如果是则将算子转换为CustomOperator类型
UpdateCustomOpInputDesc(cus_op, node, format); //调用UpdateCustomOpInputDesc函数来更新输入描述
} else { //如果不是自定义算子则调用UpdateNormalOpInputDesc函数来更新输入描述。
UpdateNormalOpInputDesc(op, node, format);
}
}
// 该函数用于根据输出的形状和数据类型信息更新运算符的输出描述。
// 参数:
// - op: 指向OperatorPtr的指针表示需要更新输出描述的运算符。
// - shp: 指向BaseShapePtr的指针表示输出的形状信息。
// - type: 指向TypePtr的指针表示输出的数据类型信息。
// - node: 指向AnfNodePtr的指针表示与运算符对应的CNode节点。
void OpAdapterImpl::updateOutputDesc(const OperatorPtr &op, const abstract::BaseShapePtr &shp, const TypePtr &type,
const AnfNodePtr &node) {
if (op == nullptr) { //检查运算符和节点指针是否为空,如果为空,则会引发异常
MS_LOG(ERROR) << "op is nullptr";
return;
}
MS_EXCEPTION_IF_NULL(node);
MS_LOG(INFO) << "Op name is " << op->GetName() << " anf is " << node->DebugString();
auto normal_shape_ptr = dyn_cast<abstract::Shape>(shp);
auto no_shape_ptr = dyn_cast<abstract::NoShape>(shp);
std::string format = GetOpIOFormat(node); //通过调用GetOpIOFormat函数来获取节点的数据格式IO格式
//函数检查形状信息的类型
if ((normal_shape_ptr != nullptr) || (no_shape_ptr != nullptr)) { //如果形状类型为Shape或NoShape单个输出
if (UpdateSingleOutputDesc(op, shp, type, format) != SUCCESS) { //则调用UpdateSingleOutputDesc函数来更新输出描述。
return;
}
} else if (dyn_cast<abstract::TupleShape>(shp) != nullptr) { // 如果形状类型为TupleShape多个输出
if (UpdateMultiOutputDesc(op, shp, type, format) != SUCCESS) { //调用UpdateMultiOutputDesc函数来更新输出描述
return;
}
} else { //如果形状类型未知,则记录警告并返回。
MS_LOG(WARNING) << "Update output desc failed, unknown output shape type";
return;
}
MS_EXCEPTION_IF_NULL(node);
if (!node->isa<CNode>()) { //更新输出描述后函数检查节点是否为CNode即计算节点
return; //如果节点不是CNode则函数返回因为非计算节点不需要更新输入描述。
}
// Need to update input_desc while the output_desc is updated
// 如果节点是CNode则函数调用updateInputDesc函数来同时更新输入描述。
updateInputDesc(op, node);
}
// 该函数用于为运算符设置属性。
// 参数:
// - op: 指向OperatorPtr的指针表示要设置属性的运算符。
// - attr_key: 属性的键,表示要设置的属性名称。
// - attr_value: 指向ValuePtr的指针表示要设置的属性值。
int OpAdapterImpl::setAttr(const OperatorPtr &op, const std::string &attr_key, const ValuePtr &attr_value) {
auto it = attr_map_.find(attr_key); //通过在attr_map_中查找给定的attr_key来检查是否有对应的属性信息
if (it != attr_map_.end()) { // 如果找到了匹配的属性信息则会调用相应的set_attr函数来设置属性。
// switch case for each avalilable attribute type
// 在设置属性之前函数会打印属性名称和属性值并将属性信息添加到adpt_对象以绘制图形。
MS_LOG(INFO) << "Set attr: " << attr_key << "(" << it->second.name << "), value: " << attr_value->ToString();
adpt_->AddAttrToDrawGraph(attr_key + std::string("=") + attr_value->ToString());
it->second.set_attr(op, attr_value);
return 0; // 成功则设置属性返回0。
}
return static_cast<int>(NOT_FOUND); // 如果未找到匹配的属性信息则函数返回NOT_FOUND。
}
//该函数用于设置自定义操作的属性。
int OpAdapterImpl::SetCustomOpAttr(const CusOperatorPtr &op, const PrimitivePtr &prim) {
enum ValueType { //定义一个枚举类型ValueType包括三个枚举值SINGLE_VALUE、SEQUEUE_VALUE和UNKNOWN_VALUE。
SINGLE_VALUE = 0,
SEQUEUE_VALUE,
UNKNOWN_VALUE,
};
MS_EXCEPTION_IF_NULL(prim); //使用断言MS_EXCEPTION_IF_NULL确保prim和op指针不为空
MS_EXCEPTION_IF_NULL(op);
ValueType value_type = SINGLE_VALUE; //初始化一个变量value_type为SINGLE_VALUE
for (auto item : prim->attrs()) { //通过遍历prim对象的属性来设置操作的属性
//对于每个属性,它首先检查其类型,然后根据类型调用适当的函数将属性值设置到操作中。
//支持的属性类型包括Int32Imm、StringImm、BoolImm和FP32Imm。
/* 如果属性的类型是ValueSequence则将value_type设置为SEQUEUE_VALUE并根据序列中第一个元素的类型设置属性值。
*/
if (item.second->isa<Int32Imm>()) {
(void)op->SetAttr(item.first, GetValue<int64_t>(item.second));
} else if (item.second->isa<StringImm>()) {
(void)op->SetAttr(item.first, GetValue<std::string>(item.second));
} else if (item.second->isa<BoolImm>()) {
(void)op->SetAttr(item.first, GetValue<bool>(item.second));
} else if (item.second->isa<FP32Imm>()) {
(void)op->SetAttr(item.first, GetValue<float>(item.second));
} else if (item.second->isa<ValueSequence>()) {
value_type = SEQUEUE_VALUE;
auto val_seq = item.second->cast<ValueSequencePtr>();
if ((*val_seq)[0]->isa<StringImm>()) {
(void)op->SetAttr(item.first, GetValue<const std::vector<std::string>>(item.second));
} else if ((*val_seq)[0]->isa<FP32Imm>()) {
(void)op->SetAttr(item.first, GetValue<const std::vector<float>>(item.second));
} else if ((*val_seq)[0]->isa<Int64Imm>()) {
(void)op->SetAttr(item.first, GetValue<const std::vector<int64_t>>(item.second));
} else if ((*val_seq)[0]->isa<BoolImm>()) {
(void)op->SetAttr(item.first, GetValue<const std::vector<bool>>(item.second));
} else {
MS_LOG(EXCEPTION) << "Unsupported custom attribute type in adaptor, prim name: " << prim->name()
<< ", attr name: " << item.first << ", value: " << item.second->ToString();
}
} else {
MS_LOG(WARNING) << "Unsupported custom attribute type in adaptor, prim name: " << prim->name()
<< ", attr name: " << item.first << ", value: " << item.second->ToString();
return static_cast<int>(NOT_FOUND);
}
/*在设置属性值之后根据value_type的值函数使用适当的字符串表示将属性添加到绘制图中。
value_type为SINGLE_VALUE
value_type为SEQUEUE_VALUE*/
if (value_type == SINGLE_VALUE) {
adpt_->AddAttrToDrawGraph(item.first + std::string("=") + item.second->ToString());
} else if (value_type == SEQUEUE_VALUE) {
adpt_->AddAttrToDrawGraph(item.first + std::string("=") + "[...]");
}
}
return 0; //函数返回0表示成功设置属性。
}
// 该函数用于为普通运算符设置属性。
// 参数:
// - op: 指向OperatorPtr的指针表示要设置属性的运算符。
// - prim: 指向PrimitivePtr的指针表示运算符的原语Primitive信息。
int OpAdapterImpl::SetNormalOpAttr(const OperatorPtr &op, const PrimitivePtr &prim) {
MS_EXCEPTION_IF_NULL(prim); //检查prim和op是否为空如果为空则会抛出异常
MS_EXCEPTION_IF_NULL(op);
for (auto &it : attr_map_) { //函数遍历attr_map_
auto value = prim->GetAttr(it.first); //对于每个属性attr_map_中的每个键值对它会先从prim中获取对应的属性值。
if (value != nullptr) { //如果在prim中找到了匹配的属性值则会对属性值进行一系列转换如将部分属性转换为字符串形式或将IR属性转换为Op属性
// convert parts of attr to str eg. data_format or change ir attr to op attr eg. axis[0]
(void)CheckAndConvertUtils::ConvertAttrValueToString(prim->name(), it.first, &value);
(void)CheckAndConvertUtils::CheckIrAttrtoOpAttr(prim->name(), it.first, &value);
// set attr from primitive
int ret = setAttr(op, it.first, value); //然后调用setAttr函数设置运算符的属性
if (ret) {
return ret;
}
} else { //// 如果在prim中未找到匹配的属性值则会检查是否存在extra_attr_额外的属性信息
// set attr from extra_attr
auto it_extra = extra_attr_->find(it.first);
if (it_extra != extra_attr_->end()) { // 如果在extra_attr_中找到了匹配的属性值则同样调用setAttr函数设置运算符的属性
int ret = setAttr(op, it.first, it_extra->second);
if (ret) { // 如果遍历过程中发现设置属性时返回了非零值(即设置属性失败),则函数会立即返回该错误码。
return ret;
}
}
}
}
return 0; //成功设置属性返回0。
}
// 该函数用于为运算符设置属性。
// 参数:
// - op: 指向OperatorPtr的指针表示要设置属性的运算符。
// - prim: 指向PrimitivePtr的指针表示运算符的原语Primitive信息。
int OpAdapterImpl::setAttr(const OperatorPtr &op, const PrimitivePtr &prim) {
int ret = 0;
if (IsCustomPrim(prim)) { //判断prim是否为自定义原语CustomPrimitive
auto cus_op = std::dynamic_pointer_cast<CustomOperator>(op);
ret = SetCustomOpAttr(cus_op, prim); //如果是自定义原语则调用SetCustomOpAttr函数为运算符设置属性。
} else { // 否则调用SetNormalOpAttr函数为运算符设置属性
ret = SetNormalOpAttr(op, prim);
}
return ret; //返回值为非零表示设置属性失败,返回对应的错误码。
}
// 该函数用于为运算符设置属性。
// 参数:
// - op: 指向OperatorPtr的指针表示要设置属性的运算符。
// - node: 指向AnfNodePtr的指针表示运算符对应的图节点AnfNode
int OpAdapterImpl::setAttr(const OperatorPtr &op, const AnfNodePtr &node) {
// no attribute for lonely node
MS_EXCEPTION_IF_NULL(node);
if (!node->isa<CNode>()) { //判断node是否为CNode计算节点
return 0; //如果不是CNode则表示该节点没有属性直接返回0。
}
// 将节点转换为CNodePtr计算节点的表示
auto cnode = node->cast<CNodePtr>();
if (cnode == nullptr) {
return 0;
}
// 获取计算节点的输入。
auto &inputs = cnode->inputs();
if (inputs.empty()) {
return 0;
}
// get Attr T from abstract of anfnode first,
// if attr "T" appears in primitive, the primitive T will cover this one
// 首先从AnfNode的抽象信息中获取属性"T"。
// 如果原语primitive中有属性"T",则原语中的"T"将覆盖此处的"T"属性。
if (attr_map_.find("T") != attr_map_.end()) {
// get dtype from inputs[1], if the node has no inputs, set the attr T with output dtype
// 从inputs[1]中获取数据类型dtype。如果节点没有输入则使用输出的数据类型来设置属性"T"。
TypePtr type;
if (inputs.size() > 1) {
type = inputs[1]->Type();
} else {
type = node->Type();
}
if (type != nullptr) { // 使用上面获得的数据类型来设置属性"T"
(void)setAttr(op, "T", MakeValue(type));
}
}
// set attr from primitive and ExtraAttr
// 从原语和ExtraAttr中设置属性。
if (IsValueNode<Primitive>(inputs[0])) {
// set attr from primitive
// 从原语中设置属性。
PrimitivePtr prim = GetValueNode<PrimitivePtr>(inputs[0]);
int ret = setAttr(op, prim);
if (ret != 0) {
return ret;
}
}
// set attr from const input
// 从常量输入中设置属性。
for (auto &it : input_attr_map_) {
// 检查输入索引是否在范围内并且输入是否为ValueNode常量节点
if (inputs.size() <= it.first || !inputs[it.first]->isa<ValueNode>()) {
continue;
}
// 从输入中获取常量值。
auto const_value = GetValueNode(inputs[it.first]);
MS_LOG(INFO) << "Set attr: input_" << it.first << "(" << it.second.name << "), value: " << const_value->ToString();
if (const_value->isa<None>()) { // 如果常量值为None则跳过设置属性。
continue;
}
// 将属性信息添加到绘图图形中。
adpt_->AddAttrToDrawGraph(it.second.name + std::string("=") + const_value->ToString());
// 使用提供的设置器函数it.second.set_attr和常量值来设置属性。
it.second.set_attr(op, const_value);
}
return 0;
}
} // namespace transform
} // namespace mindspore

View File

@ -0,0 +1,478 @@
/**
* Copyright 2019-2021 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_TRANSFORM_GRAPH_IR_OP_ADAPTER_H_
#define MINDSPORE_CCSRC_TRANSFORM_GRAPH_IR_OP_ADAPTER_H_
#include <memory>
#include <vector>
#include <string>
#include "utils/hash_map.h"
#include "transform/graph_ir/op_adapter_util.h"
#include "transform/graph_ir/op_adapter_base.h"
#include "include/common/utils/utils.h"
namespace mindspore {
namespace transform {
class OpAdapterImpl {
public:
// 构造函数用于初始化OpAdapterImpl对象。接受一系列输入参数并将它们保存到对应的成员变量中。
OpAdapterImpl(const mindspore::HashMap<int, InputDesc> &input_map,
const mindspore::HashMap<int, DynInputDesc> &dyn_input_map,
const mindspore::HashMap<int, OutputDesc> &output_map,
const mindspore::HashMap<int, DynOutputDesc> &dyn_output_map,
const mindspore::HashMap<int, DynSubGraphDesc> &dyn_subgraph_map,
const mindspore::HashMap<std::string, AttrDesc> &attr_map,
const mindspore::HashMap<std::string, int> &enum_map,
const mindspore::HashMap<unsigned int, AttrDesc> &input_attr_map,
mindspore::HashMap<std::string, mindspore::HashMap<int, std::string>> *cus_input_map,
mindspore::HashMap<std::string, mindspore::HashMap<int, std::string>> *cus_output_map,
mindspore::HashMap<std::string, ValuePtr> *extra_attr,
mindspore::HashMap<std::string, int> *name_counts, BaseOpAdapter *adpt)
: input_map_(input_map),
dyn_input_map_(dyn_input_map),
output_map_(output_map),
dyn_output_map_(dyn_output_map),
dyn_subgraph_map_(dyn_subgraph_map),
attr_map_(attr_map),
enum_map_(enum_map),
input_attr_map_(input_attr_map),
cus_input_map_(cus_input_map),
cus_output_map_(cus_output_map),
extra_attr_(extra_attr),
name_counts_(name_counts),
adpt_(adpt) {
MS_EXCEPTION_IF_NULL(cus_input_map_);
MS_EXCEPTION_IF_NULL(cus_output_map_);
MS_EXCEPTION_IF_NULL(extra_attr_);
MS_EXCEPTION_IF_NULL(name_counts_);
MS_EXCEPTION_IF_NULL(adpt_);
}
~OpAdapterImpl() {} // 析构函数,用于释放资源。
bool IsCustomOp(const OperatorPtr &op); // 判断一个运算符是否为自定义运算符。
Status GenerateCustomOpInputMap(const CusOperatorPtr &op, const PrimitivePtr &prim); // 生成自定义运算符的输入映射。
Status GenerateCustomOpOutputMap(const CusOperatorPtr &op, const PrimitivePtr &prim); // 生成自定义运算符的输出映射。
OperatorPtr GenerateCustomOp(const AnfNodePtr anf); // 生成自定义运算符。
Status SetOpSubgraphFunc(const OperatorPtr &op, int index, const std::shared_ptr<std::vector<DfGraph>> &branches); // 设置运算符的子图函数。
Status SetCustomOpInput(const CusOperatorPtr &op, int index, const OperatorPtr &input); // 设置自定义运算符的输入。
Status SetNormalOpInput(const OperatorPtr &op, int index, const OperatorPtr &input); // 设置普通运算符的输入。
int setInput(const OperatorPtr &op, int index, const OperatorPtr &input); // 设置运算符的输入。
Status SetCustomOpInput(const CusOperatorPtr &op, int index, const OutHandler &handle); // 设置自定义运算符的输入。
Status SetNormalOpInput(const OperatorPtr &op, int index, const OutHandler &handle); // 设置普通运算符的输入。
int setInput(const OperatorPtr &op, int index, const OutHandler &handle); // 设置运算符的输入。
int setInput(const OperatorPtr &op, int index, const std::shared_ptr<std::vector<OutHandler>> &handler_vec); // 设置运算符的输入。
OutHandler getOutput(const OperatorPtr &op, int index); // 获取运算符的输出处理器。
OutHandler getCustomOutput(const OperatorPtr &op, int index); // 获取自定义运算符的输出处理器。
OutHandler getNormalOutput(const OperatorPtr &op, int index); // 获取普通运算符的输出处理器
Status UpdateSingleOutputDesc(const OperatorPtr &op, const abstract::BaseShapePtr &shp, const TypePtr &type,
const std::string &format); // 更新单个输出的描述信息。
size_t GetCustomOpOutputSize(const CusOperatorPtr &cus_op); // 获取自定义运算符的输出数量。
std::shared_ptr<GeTensorDesc> CreateOutputDesc(const abstract::ShapePtr &shape_ptr, const TypePtr &type,
const std::string &format); // 创建输出描述。
Status UpdateMultiOutputDesc(const OperatorPtr &op, const abstract::BaseShapePtr &shp, const TypePtr &type,
const std::string &format); // 更新多个输出的描述信息。
std::shared_ptr<GeTensorDesc> CreateNodeDesc(const AnfNodePtr &node, const std::string &format); // 创建节点描述。
void UpdateNormalOpInputDesc(const OperatorPtr &op, const AnfNodePtr &node, const std::string format); // 更新普通运算符的输入描述。
void UpdateCustomOpInputDesc(const CusOperatorPtr &op, const AnfNodePtr &node, const std::string format);// 更新自定义运算符的输入描述。
void updateInputDesc(const OperatorPtr &op, const AnfNodePtr &node);// 更新运算符的输入描述。
void updateOutputDesc(const OperatorPtr &op, const abstract::BaseShapePtr &shp, const TypePtr &type,
const AnfNodePtr &node); // 更新运算符的输出描述。
int setAttr(const OperatorPtr &op, const std::string &attr_key, const ValuePtr &attr_value); // 设置运算符的属性。
int SetCustomOpAttr(const CusOperatorPtr &op, const PrimitivePtr &prim); // 设置自定义运算符的属性。
int SetNormalOpAttr(const OperatorPtr &op, const PrimitivePtr &prim); // 设置普通运算符的属性。
int setAttr(const OperatorPtr &op, const PrimitivePtr &prim); // 设置运算符的属性。
int setAttr(const OperatorPtr &op, const AnfNodePtr &node); // 设置运算符的属性。
private: // 一系列输入映射和输出映射。
const mindspore::HashMap<int, InputDesc> &input_map_;
const mindspore::HashMap<int, DynInputDesc> &dyn_input_map_;
const mindspore::HashMap<int, OutputDesc> &output_map_;
const mindspore::HashMap<int, DynOutputDesc> &dyn_output_map_;
const mindspore::HashMap<int, DynSubGraphDesc> &dyn_subgraph_map_;
const mindspore::HashMap<std::string, AttrDesc> &attr_map_;
const mindspore::HashMap<std::string, int> &enum_map_;
const mindspore::HashMap<unsigned int, AttrDesc> &input_attr_map_;
// 自定义输入映射和输出映射。
mindspore::HashMap<std::string, mindspore::HashMap<int, std::string>> *const cus_input_map_;
mindspore::HashMap<std::string, mindspore::HashMap<int, std::string>> *const cus_output_map_;
mindspore::HashMap<std::string, ValuePtr> *const extra_attr_;
mindspore::HashMap<std::string, int> *const name_counts_;
BaseOpAdapter *const adpt_;
};
template <typename T>
class OpAdapter : public BaseOpAdapter {
public:
// 使用OpType作为模板参数的构造函数。初始化OpAdapterImpl对象。
using OpType = T;
OpAdapter()
: impl_(std::make_shared<OpAdapterImpl>(input_map_, dyn_input_map_, output_map_, dyn_output_map_,
dyn_subgraph_map_, attr_map_, enum_map_, input_attr_map_, &cus_input_map_,
&cus_output_map_, &extra_attr_, &name_counts_, this)) {
MS_EXCEPTION_IF_NULL(impl_);
}
// 使用ExtraAttr作为输入参数的构造函数。初始化OpAdapterImpl对象。
explicit OpAdapter(const ExtraAttr &extra_attr)
: extra_attr_(extra_attr),
impl_(std::make_shared<OpAdapterImpl>(input_map_, dyn_input_map_, output_map_, dyn_output_map_,
dyn_subgraph_map_, attr_map_, enum_map_, input_attr_map_, &cus_input_map_,
&cus_output_map_, &extra_attr_, &name_counts_, this)) {
MS_EXCEPTION_IF_NULL(impl_);
}
// 析构函数,用于释放资源。
~OpAdapter() override {}
// 判断一个运算符是否为自定义运算符。
bool IsCustomOp(const OperatorPtr &op) { return impl_->IsCustomOp(op); }
// 生成自定义运算符的输入映射。
Status GenerateCustomOpInputMap(const CusOperatorPtr &op, const PrimitivePtr &prim) {
return impl_->GenerateCustomOpInputMap(op, prim);
}
// 生成自定义运算符的输出映射。
Status GenerateCustomOpOutputMap(const CusOperatorPtr &op, const PrimitivePtr &prim) {
return impl_->GenerateCustomOpOutputMap(op, prim);
}
// Convert ME UserCustom AnfNode to GE CustomOp. And set it's attrs.
// 将ME UserCustom AnfNode转换为GE CustomOp并设置其属性。
OperatorPtr GenerateCustomOp(const AnfNodePtr anf) { return impl_->GenerateCustomOp(anf); }
// 生成普通运算符。
OperatorPtr GenerateNormalOp(const AnfNodePtr &anf) {
OperatorPtr op = nullptr;
// There are duplicate names in ANF graph, do not assign ANF node name to GE
// GE will generate unique name automatically
if (anf != nullptr && anf->fullname_with_scope() != "") {
MS_LOG(DEBUG) << anf->fullname_with_scope();
op = std::make_shared<OpType>(anf->fullname_with_scope());
} else {
MS_LOG(DEBUG) << "no fullname_with_scope";
op = std::make_shared<OpType>();
}
// set dynamic output num if op use DYNAMIC_OUTPUT
if ((op != nullptr) && (!dyn_output_map_.empty()) && (anf != nullptr)) {
TypePtr type = anf->Type();
if (type == nullptr) {
MS_LOG(EXCEPTION) << "Dynamic output node:" << op->GetName() << "'s Type is a nullptr!";
}
size_t num = type->isa<Tuple>() ? (type->cast<std::shared_ptr<Tuple>>()->size()) : 1;
MS_LOG(INFO) << "create_dyn_output for node:" << anf->ToString() << ", type:" << type->ToString()
<< ", num:" << num;
dyn_output_map_.begin()->second.create_dyn_output(op, static_cast<unsigned int>(num));
}
return op;
}
// 实现generate函数根据传入的AnfNode生成对应的OperatorPtr。
OperatorPtr generate(const AnfNodePtr &anf) override {
OperatorPtr op = nullptr;
if (IsCustomCNode(anf)) {
op = GenerateCustomOp(anf);
} else {
op = GenerateNormalOp(anf);
}
if (op == nullptr) {
MS_LOG(EXCEPTION) << "Can not generate op for " << anf->fullname_with_scope();
}
return op;
}
// 实现generate函数根据传入的op_name生成对应的OperatorPtr。
OperatorPtr generate(const std::string &op_name) override { return std::make_shared<OpType>(op_name); }
// 获取输入映射。
const mindspore::HashMap<int, InputDesc> &getInputMap() override { return input_map_; }
// 获取输入属性映射。
const mindspore::HashMap<unsigned int, AttrDesc> &getInputAttrMap() override { return input_attr_map_; }
// 获取动态输入映射。
const mindspore::HashMap<int, DynInputDesc> &getDynInputMap() override { return dyn_input_map_; }
// 获取输出映射。
const mindspore::HashMap<int, OutputDesc> &getOutputMap() override { return output_map_; }
// 获取动态子图映射。
const mindspore::HashMap<int, DynSubGraphDesc> &getDynSubgraphMap() override { return dyn_subgraph_map_; }
// 设置运算符的子图函数。
Status SetOpSubgraphFunc(const OperatorPtr &op, int index, const std::shared_ptr<std::vector<DfGraph>> &branches) {
return impl_->SetOpSubgraphFunc(op, index, branches);
}
// 设置运算符的子图。
int setSubgraph(const OperatorPtr &op, int index, const std::shared_ptr<std::vector<DfGraph>> &branches) override {
return static_cast<int>(SetOpSubgraphFunc(op, index, branches));
}
// 设置自定义运算符的输入。
Status SetCustomOpInput(const CusOperatorPtr &op, int index, const OperatorPtr &input) {
return impl_->SetCustomOpInput(op, index, input);
}
// 设置普通运算符的输入。
Status SetNormalOpInput(const OperatorPtr &op, int index, const OperatorPtr &input) {
return impl_->SetNormalOpInput(op, index, input);
}
// 设置运算符的输入。
int setInput(const OperatorPtr &op, int index, const OperatorPtr &input) override {
return impl_->setInput(op, index, input);
}
// 设置自定义运算符的输入。
Status SetCustomOpInput(const CusOperatorPtr &op, int index, const OutHandler &handle) {
return impl_->SetCustomOpInput(op, index, handle);
}
// 设置普通运算符的输入。
Status SetNormalOpInput(const OperatorPtr &op, int index, const OutHandler &handle) {
return impl_->SetNormalOpInput(op, index, handle);
}
// 设置运算符的输入
int setInput(const OperatorPtr &op, int index, const OutHandler &handle) override {
return impl_->setInput(op, index, handle);
}
// 设置运算符的输入。
int setInput(const OperatorPtr &op, int index, const std::shared_ptr<std::vector<OutHandler>> &handler_vec) override {
return impl_->setInput(op, index, handler_vec);
}
// 获取运算符的输出处理器。
OutHandler getOutput(const OperatorPtr &op, int index) override { return impl_->getOutput(op, index); }
// 获取自定义运算符的输出处理器。
OutHandler getCustomOutput(const OperatorPtr &op, int index) { return impl_->getCustomOutput(op, index); }
// 获取普通运算符的输出处理器。
OutHandler getNormalOutput(const OperatorPtr &op, int index) { return impl_->getNormalOutput(op, index); }
// 更新单个输出的描述信息。
Status UpdateSingleOutputDesc(const OperatorPtr &op, const abstract::BaseShapePtr &shp, const TypePtr &type,
const std::string &format) {
return impl_->UpdateSingleOutputDesc(op, shp, type, format);
}
// 获取自定义运算符的输出数量。
size_t GetCustomOpOutputSize(const CusOperatorPtr &cus_op) { return impl_->GetCustomOpOutputSize(cus_op); }
// 创建输出描述。
std::shared_ptr<GeTensorDesc> CreateOutputDesc(const abstract::ShapePtr &shape_ptr, const TypePtr &type,
const std::string &format) {
return impl_->CreateOutputDesc(shape_ptr, type, format);
}
// 更新多个输出的描述信息。
Status UpdateMultiOutputDesc(const OperatorPtr &op, const abstract::BaseShapePtr &shp, const TypePtr &type,
const std::string &format) {
return impl_->UpdateMultiOutputDesc(op, shp, type, format);
}
// 创建节点描述。
std::shared_ptr<GeTensorDesc> CreateNodeDesc(const AnfNodePtr &node, const std::string &format) {
return impl_->CreateNodeDesc(node, format);
}
// 更新普通运算符的输入描述。
void UpdateNormalOpInputDesc(const OperatorPtr &op, const AnfNodePtr node, const std::string format) {
return impl_->UpdateNormalOpInputDesc(op, node, format);
}
// 更新自定义运算符的输入描述。
void UpdateCustomOpInputDesc(const CusOperatorPtr &op, const AnfNodePtr &node, const std::string format) {
return impl_->UpdateCustomOpInputDesc(op, node, format);
}
// 更新运算符的输入描述。
void updateInputDesc(const OperatorPtr &op, const AnfNodePtr &node) { impl_->updateInputDesc(op, node); }
// 更新运算符的输出描述。
void updateOutputDesc(const OperatorPtr &op, const abstract::BaseShapePtr &shp, const TypePtr &type,
const AnfNodePtr &node) override {
impl_->updateOutputDesc(op, shp, type, node);
}
// 设置运算符的属性。
int setAttr(const OperatorPtr &op, const std::string &attrKey, const ValuePtr &attrValue) override {
return impl_->setAttr(op, attrKey, attrValue);
}
// 设置自定义运算符的属性。
int SetCustomOpAttr(const CusOperatorPtr &op, const PrimitivePtr &prim) { return impl_->SetCustomOpAttr(op, prim); }
// 设置普通运算符的属性。
int SetNormalOpAttr(const OperatorPtr &op, const PrimitivePtr &prim) { return impl_->SetNormalOpAttr(op, prim); }
// 设置运算符的属性。
int setAttr(const OperatorPtr &op, const PrimitivePtr &prim) override { return impl_->setAttr(op, prim); }
// 设置运算符的属性。
int setAttr(const OperatorPtr &op, const AnfNodePtr &node) override { return impl_->setAttr(op, node); }
// 获取额外属性。
mindspore::HashMap<std::string, ValuePtr> GetExtraAttr() override { return extra_attr_; }
private:
template <typename S>
static S ConvertAny(const ValuePtr &value, const AnyTraits<S> &) {
return GetValue<S>(value);
}
// specialization for reverse bool
static bool ConvertAny(const ValuePtr &value, const AnyTraits<bool> &, bool reverse) {
return reverse != GetValue<bool>(value);
}
template <typename P, typename Q>
static Q ConvertAny(const ValuePtr &value, const AnyTraits<P> &traits_from, const AnyTraits<Q> &traits_to) {
return ConvertAnyUtil(value, traits_from, traits_to);
}
// specialization for tensor
static GeTensor ConvertAny(const ValuePtr &value, const AnyTraits<mindspore::tensor::Tensor> &traits) {
// To-DO the format may read from ME tensor
return ConvertAnyUtil(value, traits);
}
// specialization for int
static int64_t ConvertAny(const ValuePtr &value, const AnyTraits<int64_t>) {
return static_cast<int64_t>(GetValue<int64_t>(value));
}
// specialization for int or tuple broadcast to Vector
static std::vector<int64_t> ConvertAny(const ValuePtr &value, const std::string &name,
const AnyTraits<std::vector<int64_t>> anyTraitsInt) {
return ConvertAnyUtil(value, name, anyTraitsInt);
}
static std::vector<std::vector<int64_t>> ConvertAny(const ValuePtr &value,
const AnyTraits<std::vector<std::vector<int64_t>>>) {
MS_EXCEPTION_IF_NULL(value);
MS_LOG(INFO) << "Value: " << value->type_name();
std::vector<std::vector<int64_t>> list;
if (!value->isa<ValueTuple>()) {
MS_LOG(EXCEPTION) << "Value should be ValueTuple, but got " << value->type_name();
}
auto vec = value->cast<ValueTuplePtr>();
MS_EXCEPTION_IF_NULL(vec);
for (auto &it : vec->value()) {
MS_EXCEPTION_IF_NULL(it);
if (!it->isa<ValueTuple>()) {
MS_LOG(EXCEPTION) << "It should be ValueTuple, but got " << it->type_name();
}
auto sub_vector = it->cast<ValueTuplePtr>();
std::vector<int64_t> sublist;
for (auto &item : sub_vector->value()) {
sublist.push_back(static_cast<int64_t>(GetValue<int64_t>(item)));
}
list.push_back(sublist);
}
return list;
}
static std::vector<int64_t> ConvertAny(const ValuePtr &value, const AnyTraits<std::vector<std::vector<int64_t>>>,
const AnyTraits<std::vector<int64_t>>) {
MS_EXCEPTION_IF_NULL(value);
MS_LOG(DEBUG) << "Value: " << value->type_name();
if (!value->isa<ValueList>()) {
MS_LOG(EXCEPTION) << "Value should be ValueList, but got " << value->type_name();
}
auto vec = value->cast<ValueListPtr>();
std::vector<int64_t> list;
for (auto &it : vec->value()) {
MS_EXCEPTION_IF_NULL(it);
if (!it->isa<ValueList>()) {
MS_LOG(EXCEPTION) << "It should be ValueList, but got " << it->type_name();
}
auto sub_vector = it->cast<ValueListPtr>();
for (auto &item : sub_vector->value()) {
list.push_back(static_cast<int64_t>(GetValue<int64_t>(item)));
}
}
return list;
}
static std::vector<int64_t> ConvertAny(const ValuePtr &value, const AnyTraits<std::vector<int64_t>>,
const AnyTraits<std::vector<int64_t>>) {
MS_EXCEPTION_IF_NULL(value);
MS_LOG(INFO) << "Value: " << value->type_name();
std::vector<int64_t> list;
if (value->isa<ValueSequence>()) {
auto vec = value->cast<ValueSequencePtr>();
MS_EXCEPTION_IF_NULL(vec);
for (auto &it : vec->value()) {
list.push_back(static_cast<int64_t>(GetValue<int64_t>(it)));
}
return list;
}
if (value->isa<Scalar>()) {
list.push_back(static_cast<int64_t>(GetValue<int64_t>(value)));
return list;
}
MS_LOG(EXCEPTION) << "Value should be ValueTuple or Scalar, but got " << value->type_name();
}
static std::string ConvertAny(const ValuePtr &value, const AnyTraits<std::vector<int64_t>> anyTraitsVec,
const AnyTraits<std::string> anyTraitsStr) {
return ConvertAnyUtil(value, anyTraitsVec, anyTraitsStr);
}
static std::vector<float> ConvertAny(const ValuePtr &value, const AnyTraits<std::vector<float>> anyTraitsVec,
const AnyTraits<float> anyTraitsFlo) {
return ConvertAnyUtil(value, anyTraitsVec, anyTraitsFlo);
}
static std::vector<int64_t> ConvertAny(const ValuePtr &value, const std::string &format,
const AnyTraits<std::vector<int64_t>> anyTraitsVec,
const AnyTraits<int64_t> anyTraitsInt) {
return ConvertAnyUtil(value, format, anyTraitsVec, anyTraitsInt);
}
// convert value list for value tuple to vector
template <typename P, typename Q>
static std::vector<Q> ConvertAny(const ValuePtr &value, const AnyTraits<P> &anyTraitsP,
const AnyTraits<std::vector<Q>> anyTraitsQ) {
return ConvertAnyUtil(value, anyTraitsP, anyTraitsQ);
}
static int64_t ConvertAny(const ValuePtr &value, const AnyTraits<GeEnum>) {
auto name = GetValue<std::string>(value);
auto it = enum_map_.find(name);
int v = 0;
if (it != enum_map_.end()) {
v = it->second;
}
return v;
}
static GeDataType ConvertAny(const ValuePtr &value, const AnyTraits<GEType> anyTraitsGE) {
return ConvertAnyUtil(value, anyTraitsGE);
}
// convert any value to tensor
static GeTensor ConvertAny(const ValuePtr &value, const AnyTraits<AnyValue> anyTraitsValue) {
return ConvertAnyUtil(value, anyTraitsValue);
}
static const mindspore::HashMap<int, InputDesc> input_map_;
static const mindspore::HashMap<int, DynInputDesc> dyn_input_map_;
static const mindspore::HashMap<int, OutputDesc> output_map_;
static const mindspore::HashMap<int, DynOutputDesc> dyn_output_map_;
static const mindspore::HashMap<int, DynSubGraphDesc> dyn_subgraph_map_;
static const mindspore::HashMap<std::string, AttrDesc> attr_map_;
static const mindspore::HashMap<std::string, int> enum_map_;
// convert input from anf graph to Attr in Operators
static const mindspore::HashMap<unsigned int, AttrDesc> input_attr_map_;
static mindspore::HashMap<std::string, mindspore::HashMap<int, std::string>> cus_input_map_;
static mindspore::HashMap<std::string, mindspore::HashMap<int, std::string>> cus_output_map_;
mindspore::HashMap<std::string, ValuePtr> extra_attr_;
mindspore::HashMap<std::string, int> name_counts_;
const std::shared_ptr<OpAdapterImpl> impl_;
};
template <typename T>
const mindspore::HashMap<int, InputDesc> OpAdapter<T>::input_map_;
template <typename T>
const mindspore::HashMap<int, DynInputDesc> OpAdapter<T>::dyn_input_map_;
template <typename T>
const mindspore::HashMap<int, OutputDesc> OpAdapter<T>::output_map_;
template <typename T>
const mindspore::HashMap<int, DynOutputDesc> OpAdapter<T>::dyn_output_map_;
template <typename T>
const mindspore::HashMap<int, DynSubGraphDesc> OpAdapter<T>::dyn_subgraph_map_;
template <typename T>
const mindspore::HashMap<std::string, AttrDesc> OpAdapter<T>::attr_map_;
template <typename T>
const mindspore::HashMap<std::string, int> OpAdapter<T>::enum_map_;
template <typename T>
const mindspore::HashMap<unsigned int, AttrDesc> OpAdapter<T>::input_attr_map_;
template <typename T>
mindspore::HashMap<std::string, mindspore::HashMap<int, std::string>> OpAdapter<T>::cus_input_map_;
template <typename T>
mindspore::HashMap<std::string, mindspore::HashMap<int, std::string>> OpAdapter<T>::cus_output_map_;
// specialization for method
} // namespace transform
} // namespace mindspore
#endif // MINDSPORE_CCSRC_TRANSFORM_GRAPH_IR_OP_ADAPTER_H_

View File

@ -0,0 +1,175 @@
/**
* Copyright 2019-2021 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_TRANSFORM_GRAPH_IR_OP_ADAPTER_BASE_H_
#define MINDSPORE_CCSRC_TRANSFORM_GRAPH_IR_OP_ADAPTER_BASE_H_
#include <string>
#include <memory>
#include <utility>
#include <vector>
#include <sstream>
#include "utils/hash_map.h"
#include "include/transform/graph_ir/util.h"
#include "ir/anf.h"
#include "ir/primitive.h"
#include "ir/value.h"
#include "include/transform/graph_ir/types.h"
#include "graph/operator_reg.h"
#include "external/ge/ge_api.h"
#include "graph/tensor.h"
namespace ge {
class CustomOperator : public Operator { //定义类 CustomOperator
public: //函数
CustomOperator(const string &name, const string &type) : Operator(name, type) {}
~CustomOperator() override{};
void CustomInputRegister(const string &name) { Operator::InputRegister(name); }
void CustomOutputRegister(const string &name) { Operator::OutputRegister(name); }
void CustomInferFuncRegister(const std::function<graphStatus(Operator &)> &func) {
Operator::InferFuncRegister(func);
}
};
} // namespace ge
namespace mindspore {
namespace transform {
using CusOperatorPtr = std::shared_ptr<ge::CustomOperator>;
using CustomOperator = ge::CustomOperator;
using AttrFunc = std::function<void(OperatorPtr, ValuePtr)>;
using OutputFunc = std::function<OutHandler(OperatorPtr)>;
using InputOpFunc = std::function<void(OperatorPtr, OperatorPtr)>;
using InputHandleFunc = std::function<void(OperatorPtr, OutHandler)>;
using CreateDynInputOpFunc = std::function<void(OperatorPtr, unsigned int)>;
using DynInputOpFunc = std::function<void(OperatorPtr, unsigned int, OperatorPtr)>;
using DynInputHandleFunc = std::function<void(OperatorPtr, unsigned int, OutHandler)>;
using UpdateOutputDescFunc = std::function<void(OperatorPtr, GeTensorDesc)>;
using CreateDynOutputOpFunc = std::function<void(OperatorPtr, unsigned int)>;
using CreateDynSubGraphFunc = std::function<void(OperatorPtr, unsigned int)>;
using DynSubGraphFunc = std::function<void(OperatorPtr, unsigned int, DfGraphPtr)>;
//定义结构体
struct AttrDesc {
std::string name;
AttrFunc set_attr;
};
struct InputDesc {
std::string name;
InputOpFunc set_op;
InputHandleFunc set_handle;
UpdateOutputDescFunc update_input_desc;
};
struct DynInputDesc {
std::string name;
CreateDynInputOpFunc create_dyn_input;
DynInputOpFunc set_op;
DynInputHandleFunc set_handle;
};
struct DynSubGraphDesc {
std::string name;
CreateDynSubGraphFunc create_dyn_subgraph;
DynSubGraphFunc set_subgraph;
};
struct OutputDesc {
std::string name;
UpdateOutputDescFunc update_out_desc;
};
struct DynOutputDesc {
std::string name;
CreateDynOutputOpFunc create_dyn_output;
};
class BaseOpAdapter { //定义类BaseOpAdapter
public: //函数
virtual ~BaseOpAdapter() {}
virtual OperatorPtr generate(const AnfNodePtr &anf) = 0;
virtual OperatorPtr generate(const std::string &type) { return std::make_shared<ge::Operator>(type); }
virtual int setSubgraph(const OperatorPtr &op, int index, const std::shared_ptr<std::vector<DfGraph>> &branches) = 0;
virtual int setInput(const OperatorPtr &op, int index, const OperatorPtr &input) = 0;
virtual int setInput(const OperatorPtr &op, int index, const OutHandler &handle) = 0;
virtual int setInput(const OperatorPtr &op, int index,
const std::shared_ptr<std::vector<OutHandler>> &handler_vec) = 0;
virtual int setAttr(const OperatorPtr &op, const std::string &attrKey, const ValuePtr &attrValue) = 0;
virtual int setAttr(const OperatorPtr &op, const PrimitivePtr &prim) = 0;
virtual int setAttr(const OperatorPtr &op, const AnfNodePtr &node) = 0;
virtual mindspore::HashMap<std::string, ValuePtr> GetExtraAttr() = 0;
template <typename T, typename _ = typename std::enable_if<!std::is_base_of<Value, T>::value>::type>
int setAttr(const OperatorPtr &op, const std::string &attrKey, const std::shared_ptr<T> &attrValue) {
return setAttr(op, attrKey, MakeValue(attrValue));
}
template <typename T, typename _ = typename std::enable_if<!is_shared_ptr<T>::value>::type>
int setAttr(const OperatorPtr &op, const std::string &attrKey, const T &attrValue) {
return setAttr(op, attrKey, MakeValue(attrValue));
}
virtual OutHandler getOutput(const OperatorPtr &op, int index) = 0;
virtual void updateOutputDesc(const OperatorPtr &op, const abstract::BaseShapePtr &shp, const TypePtr &type,
const AnfNodePtr &node) = 0;
virtual const mindspore::HashMap<int, InputDesc> &getInputMap() = 0;
virtual const mindspore::HashMap<unsigned int, AttrDesc> &getInputAttrMap() = 0;
virtual const mindspore::HashMap<int, DynInputDesc> &getDynInputMap() = 0;
virtual const mindspore::HashMap<int, OutputDesc> &getOutputMap() = 0;
virtual const mindspore::HashMap<int, DynSubGraphDesc> &getDynSubgraphMap() = 0;
void AddAttrToDrawGraph(const std::string &attr_str) { attrs_vec_.push_back(attr_str); }
const std::vector<std::string> &GetAttrsFromDrawGraph() const { return attrs_vec_; }
void clearAttrVect() { attrs_vec_.clear(); }
private: //成员变量
std::vector<std::string> attrs_vec_;
};
using OpAdapterPtr = std::shared_ptr<BaseOpAdapter>;
enum AttrType { //enum关键字
ATTR_INT = 0,
ATTR_FLOAT,
ATTR_DOUBLE,
ATTR_STRING,
ATTR_TENSOR,
ATTR_BOOL,
ATTR_LIST_INT,
ATTR_LIST_ANY_INT,
ATTR_ENUM
};
struct GeEnum {};
struct TFType {};
struct GEType {};
// declare Any type
template <typename T>
struct AnyTraits {
using type = T;
};
template <>
struct AnyTraits<int> {
using type = int64_t;
};
using ExtraAttr = mindspore::HashMap<std::string, ValuePtr>;
} // namespace transform
} // namespace mindspore
#endif // MINDSPORE_CCSRC_TRANSFORM_GRAPH_IR_OP_ADAPTER_BASE_H_

View File

@ -0,0 +1,75 @@
/**
* 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.
*/
#ifndef MINDSPORE_CCSRC_TRANSFORM_GRAPH_IR_OP_ADAPTER_DESC_H_
#define MINDSPORE_CCSRC_TRANSFORM_GRAPH_IR_OP_ADAPTER_DESC_H_
#include <memory>
#include "transform/graph_ir/op_adapter.h"
namespace mindspore {
namespace transform {
class OpAdapterDesc { //定义了一个类OpAdapterDesc
public: //函数
OpAdapterDesc() : train_(nullptr), infer_(nullptr) {}
OpAdapterDesc(const OpAdapterPtr &train, const OpAdapterPtr &infer) : train_(train), infer_(infer) {}
explicit OpAdapterDesc(const OpAdapterPtr &common) : train_(common), infer_(common) {}
OpAdapterDesc(const OpAdapterDesc &desc) {
this->train_ = desc.train_;
this->infer_ = desc.infer_;
}
OpAdapterDesc(OpAdapterDesc &&desc) {
this->train_ = desc.train_;
this->infer_ = desc.infer_;
desc.train_ = nullptr;
desc.infer_ = nullptr;
}
~OpAdapterDesc() = default;
OpAdapterPtr Get(bool train) const { return train ? train_ : infer_; }
OpAdapterDesc &operator=(const OpAdapterDesc &desc) {
if (this != &desc) {
this->train_ = desc.train_;
this->infer_ = desc.infer_;
}
return *this;
}
OpAdapterDesc &operator=(OpAdapterDesc &&desc) {
if (this != &desc) {
this->train_ = desc.train_;
this->infer_ = desc.infer_;
desc.train_ = nullptr;
desc.infer_ = nullptr;
}
return *this;
}
private: //成员变量
OpAdapterPtr train_;
OpAdapterPtr infer_;
};
using OpAdapterDescPtr = std::shared_ptr<OpAdapterDesc>;
} // namespace transform
} // namespace mindspore
#endif // MINDSPORE_CCSRC_TRANSFORM_GRAPH_IR_OP_ADAPTER_DESC_H_

View File

@ -0,0 +1,43 @@
/**
* Copyright 2019-2021 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 "include/transform/graph_ir/op_adapter_map.h"
#include <memory>
#include "graph/operator.h"
#include "transform/graph_ir/op_adapter_desc.h"
namespace mindspore {
namespace transform {
namespace {
// 定义一个 HashMap 来存储字符串到 OpAdapterDescPtr 的映射关系。
// 键是 std::string 类型,值是 OpAdapterDesc 的 shared_ptr。
mindspore::HashMap<std::string, OpAdapterDescPtr> adpt_map_ = {
{kNameCustomOp, std::make_shared<OpAdapterDesc>(std::make_shared<OpAdapter<Operator>>())}};
// 使用初始化列表将一个元素插入到 HashMap 中。
// 键是 "kNameCustomOp",值是一个使用 OpAdapter<Operator> 作为模板参数构造的 OpAdapterDesc 的 shared_ptr。
} // namespace
// 特例化模板,为 ge::Operator 类型的 OpAdapter 创建一个定制的输入映射。
// 使用 mindspore::HashMap<int, std::string> 作为值的 HashMap然后使用 std::string 作为键的 HashMap。
template <>
mindspore::HashMap<std::string, mindspore::HashMap<int, std::string>> OpAdapter<ge::Operator>::cus_input_map_{};
// 特例化模板,为 ge::Operator 类型的 OpAdapter 创建一个定制的输出映射。
// 使用 mindspore::HashMap<int, std::string> 作为值的 HashMap然后使用 std::string 作为键的 HashMap。
template <>
mindspore::HashMap<std::string, mindspore::HashMap<int, std::string>> OpAdapter<ge::Operator>::cus_output_map_{};
// OpAdapterMap 类的成员函数,用于返回 OpAdapterMap 的 adpt_map_ 成员引用。
mindspore::HashMap<std::string, OpAdapterDescPtr> &OpAdapterMap::get() { return adpt_map_; }
} // namespace transform
} // namespace mindspore

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

View File

@ -0,0 +1,72 @@
/**
* 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.
*/
#ifndef MINDSPORE_CCSRC_TRANSFORM_GRAPH_IR_OP_ADAPTER_UTIL_H_
#define MINDSPORE_CCSRC_TRANSFORM_GRAPH_IR_OP_ADAPTER_UTIL_H_
#include <string>
#include <vector>
#include "transform/graph_ir/op_adapter_base.h"
namespace mindspore {
namespace transform {
template <typename P, typename Q>
static Q ConvertAnyUtil(const ValuePtr &value, const AnyTraits<P> &, const AnyTraits<Q> &) {
return static_cast<Q>(GetValue<P>(value));
}
GeTensor ConvertAnyUtil(const ValuePtr &value, const AnyTraits<mindspore::tensor::Tensor> &traits);
std::vector<int64_t> ConvertAnyUtil(const ValuePtr &value, const std::string &name,
const AnyTraits<std::vector<int64_t>>);
std::string ConvertAnyUtil(const ValuePtr &value, const AnyTraits<std::vector<int64_t>>, const AnyTraits<std::string>);
std::vector<float> ConvertAnyUtil(const ValuePtr &value, const AnyTraits<std::vector<float>>, const AnyTraits<float>);
std::vector<int64_t> ConvertAnyUtil(const ValuePtr &value, const std::string &format,
const AnyTraits<std::vector<int64_t>>, const AnyTraits<int64_t>);
GeDataType ConvertAnyUtil(const ValuePtr &value, const AnyTraits<GEType>);
template <typename P, typename Q>
// ConvertAnyUtil 函数用于将给定的 ValuePtr 转换为具有类型 P 的元素的 std::vector<Q>。
// 这里 P 和 Q 可以是不同的类型。
std::vector<Q> ConvertAnyUtil(const ValuePtr &value, AnyTraits<P>, const AnyTraits<std::vector<Q>>) {
MS_EXCEPTION_IF_NULL(value); // 检查给定的 ValuePtr 是否为空指针,如果是,抛出异常。
// 检查给定的 ValuePtr 是否为 ValueTuple 或 ValueList如果不是抛出异常。
if (!value->isa<ValueTuple>() && !value->isa<ValueList>()) {
MS_LOG(EXCEPTION) << "error convert Value to vector for value: " << value->ToString()
<< ", type: " << value->type_name() << ", value should be a tuple or list";
}
// 获取 ValuePtr 中的数据集合,可以是 ValueTuple 或 ValueList。
auto vec = value->isa<ValueTuple>() ? value->cast<ValueTuplePtr>()->value() : value->cast<ValueListPtr>()->value();
std::vector<Q> data; // 创建 std::vector<Q>,用于存储转换后的结果。
for (auto &it : vec) { // 遍历集合中的每个元素,对每个元素调用 ConvertAnyUtil 进行转换,并将结果添加到 data 中。
data.push_back(ConvertAnyUtil(it, AnyTraits<P>(), AnyTraits<Q>()));
}
return data; // 返回转换后的 std::vector<Q>。
}
GeTensor ConvertAnyUtil(const ValuePtr &value, const AnyTraits<AnyValue>);
bool IsCustomPrim(const PrimitivePtr &prim);
bool IsCustomCNode(const AnfNodePtr &node);
std::string GetOpIOFormat(const AnfNodePtr &node);
} // namespace transform
} // namespace mindspore
#endif // MINDSPORE_CCSRC_TRANSFORM_GRAPH_IR_OP_ADAPTER_UTIL_H_

View File

@ -0,0 +1,213 @@
/**
* Copyright 2019-2021 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_TRANSFORM_GRAPH_IR_OP_DECLARE_MACRO_H_
#define MINDSPORE_CCSRC_TRANSFORM_GRAPH_IR_OP_DECLARE_MACRO_H_
#include <string>
#include <memory>
#include "utils/hash_map.h"
#include "transform/graph_ir/op_adapter.h"
#include "transform/graph_ir/op_adapter_desc.h"
#include "include/transform/graph_ir/op_adapter_map.h"
#include "mindspore/core/base/core_ops.h"
namespace mindspore::transform {
//定义了一个宏 DECLARE_OP_ADAPTER(T)用于声明对应的Op Adapter
#define DECLARE_OP_ADAPTER(T) \
using T = ge::op::T; \//定义一个别名 T表示对应GE框架中的操作ge::op::T
template <> \
const mindspore::HashMap<int, InputDesc> OpAdapter<T>::input_map_; \//一个模板特化,它声明了一个静态成员变量 input_map_用于存储 T 类型的操作的输入映射信息。
// InputDesc 是一个自定义的结构体,用于描述输入的信息,例如输入的名称和相应的处理函数。
template <> \
const mindspore::HashMap<std::string, AttrDesc> OpAdapter<T>::attr_map_; //一个模板特化,它声明了一个静态成员变量 attr_map_用于存储 T 类型的操作的属性映射信息。
//AttrDesc 是一个自定义的结构体,用于描述属性的信息,例如属性的名称和相应的处理函数。
#define DECLARE_OP_USE_OUTPUT(T) \
template <> \
const mindspore::HashMap<int, OutputDesc> OpAdapter<T>::output_map_;// 声明了 OpAdapter 类的一个模板特化,使用模板参数 T来定义 output_map_。
// 这个宏用于为 OpAdapter 类声明一个 output_map_ 的模板特化。它将整数键与 OutputDesc 值关联起来。 output_map_ 模板用于将整数标识符映射到 OutputDesc
#define DECLARE_OP_USE_ENUM(T) \
template <> \
const mindspore::HashMap<std::string, int> OpAdapter<T>::enum_map_{};// 声明了 OpAdapter 类的一个模板特化,使用模板参数 T来定义了一个空的 enum_map_。
// 这个宏用于为 OpAdapter 类声明一个 enum_map_ 的模板特化。它将字符串键与整数值关联起来。模板参数 T 表示数据类型。
#define DECLARE_OP_USE_INPUT_ATTR(T) \
template <> \
const mindspore::HashMap<unsigned int, AttrDesc> OpAdapter<T>::input_attr_map_;// 声明了 OpAdapter 类的一个模板特化,使用模板参数 T来定义 input_attr_map_。
// 这个宏用于为 OpAdapter 类声明一个 input_attr_map_ 的模板特化。它将无符号整数键与 AttrDesc 值关联起来。
#define DECLARE_OP_USE_DYN_INPUT(T) \
template <> \
const mindspore::HashMap<int, DynInputDesc> OpAdapter<T>::dyn_input_map_;//声明了 OpAdapter 类的一个模板特化,使用模板参数 T来定义 dyn_input_map_。
// 这个宏用于为 OpAdapter 类声明一个 dyn_input_map_ 的模板特化。它将整数键与 DynInputDesc 值关联起来。
#define DECLARE_OP_USE_DYN_SUBGRAPH(T) \
template <> \
const mindspore::HashMap<int, DynSubGraphDesc> OpAdapter<T>::dyn_subgraph_map_;//声明了 OpAdapter 类的一个模板特化,使用模板参数 T来定义dyn_subgraph_map_。
// 这个宏用于为 OpAdapter 类声明一个 dyn_input_map_ 的模板特化。它将整数键与 DynInputDesc值关联起来。
#define DECLARE_OP_USE_DYN_OUTPUT(T) \
template <> \
const mindspore::HashMap<int, DynOutputDesc> OpAdapter<T>::dyn_output_map_;//声明了 OpAdapter 类的一个模板特化,使用模板参数 T来定义dyn_output_map_。
// 这个宏用于为 OpAdapter 类声明一个 dyn_input_map_ 的模板特化。它将整数键与 DynInputDesc值关联起来。
#define INPUT_MAP(T) \
template <> \
const mindspore::HashMap<int, InputDesc> OpAdapter<T>::input_map_
// 定义宏 EMPTY_INPUT_MAP表示一个空的输入映射使用 mindspore::HashMap<int, InputDesc>() 初始化。
// 定义宏 INPUT_DESC(name),用于为输入描述创建一个匿名函数对象。
#define EMPTY_INPUT_MAP mindspore::HashMap<int, InputDesc>()
#define INPUT_DESC(name) \
{ \
#name, \
[](const OperatorPtr op, const OperatorPtr input) { \//设置输入
auto p = std::static_pointer_cast<OpType>(op); \
(void)p->set_input_##name(*input); \
}, \
[](const OperatorPtr op, const OutHandler& handle) { \//处理输出
auto p = std::static_pointer_cast<OpType>(op); \
(void)p->set_input_##name(*(handle.op), handle.out); \
}, \
[](const OperatorPtr op, const GeTensorDesc desc) { \//更新描述
auto p = std::static_pointer_cast<OpType>(op); \
(void)p->update_input_desc_##name(desc); \
} \
}//为输入描述提供注释和操作
// 定义宏 DYN_INPUT_MAP(T),用于为 OpAdapter 类声明动态输入映射特化。
#define DYN_INPUT_MAP(T) \
template <> \
const mindspore::HashMap<int, DynInputDesc> OpAdapter<T>::dyn_input_map_
// 定义宏 DYN_INPUT_DESC(name),用于为动态输入描述创建一个匿名函数对象。
#define DYN_INPUT_DESC(name) \
{ \
#name, \
[](const OperatorPtr op, unsigned int num) { \//创建
auto p = std::static_pointer_cast<OpType>(op); \
(void)p->create_dynamic_input_##name(num); \
}, \
[](const OperatorPtr op, unsigned int index, const OperatorPtr input) { \//设置输入
auto p = std::static_pointer_cast<OpType>(op); \
(void)p->set_dynamic_input_##name(index, *input); \
}, \
[](const OperatorPtr op, unsigned int index, const OutHandler& handle) { \//处理输出
auto p = std::static_pointer_cast<OpType>(op); \
(void)p->set_dynamic_input_##name(index, *(handle.op), handle.out); \
} \
}//为输入描述提供注释和操作
// 定义宏 DYN_SUBGRAPH_MAP(T),用于为 OpAdapter 类声明动态子图映射特化。
#define DYN_SUBGRAPH_MAP(T) \
template <> \
const mindspore::HashMap<int, DynSubGraphDesc> OpAdapter<T>::dyn_subgraph_map_
// 定义宏 DYN_SUBGRAPH_DESC(name),用于为动态子图描述创建一个匿名函数对象。
#define DYN_SUBGRAPH_DESC(name) \
{ \
#name, \
[](const OperatorPtr op, unsigned int num) { \//创建动态子图
auto p = std::static_pointer_cast<OpType>(op); \
(void)p->create_dynamic_subgraph_##name(num); \
}, \
[](const OperatorPtr op, unsigned int index, const DfGraphPtr graph) { \//设置子图构建器
auto p = std::static_pointer_cast<OpType>(op); \
(void)p->set_dynamic_subgraph_builder_##name(index, [graph](){return *graph;}); \
} \
}// 为动态子图描述提供注释和操作
// 定义宏 ATTR_MAP(T),用于为 OpAdapter 类声明属性映射特化。
#define ATTR_MAP(T) \
template <> \
const mindspore::HashMap<std::string, AttrDesc> OpAdapter<T>::attr_map_
#define EMPTY_ATTR_MAP mindspore::HashMap<std::string, AttrDesc>()
// 定义宏 EMPTY_ATTR_MAP表示一个空的属性映射使用 mindspore::HashMap<std::string, AttrDesc>() 初始化。
#define ATTR_DESC(name, ...) \
// 定义宏 ATTR_DESC(name, ...),用于为属性描述创建一个匿名函数对象。
{ \
#name, \
[](const OperatorPtr op, const ValuePtr& value) { \ //设置属性值
auto p = std::static_pointer_cast<OpType>(op); \
(void)p->set_attr_##name(ConvertAny(value, __VA_ARGS__)); \
} \
}// 为属性描述提供注释和操作
// 定义宏 INPUT_ATTR_MAP(T),用于为 OpAdapter 类声明输入属性映射特化。
//INPUT_ATTR_MAP 宏定义了一个针对类型 T 的模板特化。在这个特化中,有一个名为 input_attr_map_ 的常量哈希映射,它将无符号整数映射到 AttrDesc 对象
#define INPUT_ATTR_MAP(T) \
template <> \
const mindspore::HashMap<unsigned int, AttrDesc> OpAdapter<T>::input_attr_map_ //输入属性映射表
//OUTPUT_MAP 宏定义了一个针对类型 T 的模板特化。在这个特化中,有一个名为 output_map_ 的常量哈希映射,它将整数映射到 OutputDesc 对象
#define OUTPUT_MAP(T) \
template <> \
const mindspore::HashMap<int, OutputDesc> OpAdapter<T>::output_map_ //输出属性映射表
#define OUTPUT_DESC(name) \
{ \
#name, \
[](const OperatorPtr op, const GeTensorDesc desc) { \ //定义一个 Lambda 表达式,接收 OperatorPtr 和 GeTensorDesc 参数
auto p = std::static_pointer_cast<OpType>(op); \ //将 OperatorPtr 转换为 OpType 的智能指针
(void)p->update_output_desc_##name(desc); \ //调用 OpType 类的成员函数 update_output_desc_name其中 name 是宏展开的参数
} \
}
//DYN_OUTPUT_MAP 宏定义了一个针对类型 T 的模板特化。在这个特化中,有一个名为 dyn_output_map_ 的常量哈希映射,它将整数映射到 DynOutputDesc 对象
#define DYN_OUTPUT_MAP(T) \
template <> \
const mindspore::HashMap<int, DynOutputDesc> OpAdapter<T>::dyn_output_map_ //动态输出映射表
#define DYN_OUTPUT_DESC(name) \
{ \
#name, \
[](const OperatorPtr op, unsigned int num) { \ //定义一个 Lambda 表达式,接收 OperatorPtr 和 unsigned int 参数
auto p = std::static_pointer_cast<OpType>(op); \ //将 OperatorPtr 转换为 OpType 的智能指针
(void)p->create_dynamic_output_##name(num); \//调用 OpType 类的成员函数 create_dynamic_output_name其中 name 是宏展开的参数num 是传递给函数的 unsigned int 参数
} \
}
#define ADPT_DESC_ONE(T) std::make_shared<OpAdapterDesc>(std::make_shared<OpAdapter<T>>())
//使用 std::make_shared<OpAdapter<T>>() 创建了一个 OpAdapter<T> 类型的智能指针,并将其作为参数传递给 std::make_shared<OpAdapterDesc>() 来创建 OpAdapterDesc 类型的智能指针。
#define ADPT_DESC_TWO(T, I) \
std::make_shared<OpAdapterDesc>(std::make_shared<OpAdapter<T>>(), std::make_shared<OpAdapter<I>>())
//这个宏定义返回一个 std::shared_ptr<OpAdapterDesc> 对象。
//它使用 std::make_shared<OpAdapter<T>>()`` 和 std::make_shared<OpAdapter<I>>()创建了两个不同类型的智能指针然后将它们作为参数传递给std::make_shared<OpAdapterDesc>()来创建OpAdapterDesc类型的智能指针。
//这个宏表示有两个模板参数T和I` 的情况。
#define GET_MACRO(_1, _2, DESC, ...) DESC
//这个宏定义是一个辅助宏,用于根据参数的数量来选择不同的宏定义。在这里,它根据传入的参数数量选择 ADPT_DESC_TWO 或 ADPT_DESC_ONE。
#define ADPT_DESC(...) GET_MACRO(__VA_ARGS__, ADPT_DESC_TWO, ADPT_DESC_ONE, ...)(__VA_ARGS__)
//这个宏定义是根据传入的参数数量选择调用 ADPT_DESC_TWO 或 ADPT_DESC_ONE 宏。它将传入的参数原样传递给 GET_MACRO 宏,然后根据参数的数量选择正确的宏。
#define REG_ADPT_DESC(name, name_str, adpt_desc) \
static struct RegAdptDesc##name { \
public: \
RegAdptDesc##name() { OpAdapterMap::get()[name_str] = adpt_desc; } \
\
private: \
int ph_{0}; \// ph_{0} 是一个无用的成员,用于确保结构体有独一无二的实例化。
} g_reg_adpt_desc_##name;
//这个宏定义用于注册适配器描述。它在静态存储区定义了一个结构体 RegAdptDesc##name其中 name 是传入的参数。
//然后,在结构体的构造函数中,将适配器描述 adpt_desc 添加到 OpAdapterMap 的映射中,映射的键是 name_str。
//这个宏允许在程序运行时自动注册适配器描述。
} // namespace mindspore::transform
#endif // MINDSPORE_CCSRC_TRANSFORM_GRAPH_IR_OP_DECLARE_MACRO_H_

View File

@ -0,0 +1,103 @@
/**
* Copyright 2019-2021 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_declare/pad_ops_declare.h"
#include <vector>
namespace mindspore::transform {
// PadD
INPUT_MAP(PadD) = {{1, INPUT_DESC(x)}};
// 输入映射x索引为1
ATTR_MAP(PadD) = {{"paddings", ATTR_DESC(paddings, AnyTraits<std::vector<std::vector<int64_t>>>())}};
// 属性映射,"paddings"类型为float,"sqrt_mode"类型为std::vector<std::vector<int64_t>>
OUTPUT_MAP(PadD) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(PadD, kNamePadD, ADPT_DESC(PadD))
// 注册PadD操作的适配器描述kNamePadD
// Pad
INPUT_MAP(Pad) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(paddings)}};
// 输入映射x索引为1paddings索引为2
ATTR_MAP(Pad) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(Pad) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(Pad, kNamePadV1, ADPT_DESC(Pad))
// 注册Pad操作的适配器描述kNamePadV1
// BroadcastToD
INPUT_MAP(BroadcastToD) = {{1, INPUT_DESC(x)}};
// 输入映射x索引为1
ATTR_MAP(BroadcastToD) = {{"shape", ATTR_DESC(shape, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())}};
// 属性映射,"shape"类型为int64_t和std::vector<std::vector<int64_t>>
OUTPUT_MAP(BroadcastToD) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(BroadcastToD, kNameBroadcastTo, ADPT_DESC(BroadcastToD))
// 注册BroadcastToD操作的适配器描述kNameBroadcastTo
// Diag
INPUT_MAP(Diag) = {{1, INPUT_DESC(x)}};
// 输入映射x索引为1
ATTR_MAP(Diag) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(Diag) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Diag, kNameDiag, ADPT_DESC(Diag))
// 注册Diag操作的适配器描述kNameDiag
// FillD
INPUT_MAP(FillD) = {{1, INPUT_DESC(value)}};
// 输入映射value索引为1
ATTR_MAP(FillD) = {{"dims", ATTR_DESC(dims, AnyTraits<std::vector<int64_t>>())}};
// 属性映射,属性"dims"的类型是std::vector<int64_t>
OUTPUT_MAP(FillD) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(FillD, kNameFillD, ADPT_DESC(FillD))
// 注册FillD操作的适配器描述kNameFillD
// Fill
INPUT_MAP(Fill) = {{1, INPUT_DESC(dims)}, {2, INPUT_DESC(value)}};
// 输入映射dims索引为1value索引为2
ATTR_MAP(Fill) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(Fill) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(Fill, kNameFillV1, ADPT_DESC(Fill))
// 注册Fill操作的适配器描述kNameFillV1
// PadV3
INPUT_MAP(PadV3) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(paddings)}, {3, INPUT_DESC(constant_values)}};
// 输入映射x索引为1paddings索引为2constant_values索引为3
ATTR_MAP(PadV3) = {{"mode", ATTR_DESC(mode, AnyTraits<std::string>())},
{"pad_contiguous", ATTR_DESC(paddings_contiguous, AnyTraits<bool>())}};
// 属性映射,属性"dims""pad_contiguous"的类型分别是std::string和bool
OUTPUT_MAP(PadV3) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(PadV3, kNamePadV3, ADPT_DESC(PadV3))
// 注册PadV3操作的适配器描述kNamePadV3
// PadV2
INPUT_MAP(PadV2) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(paddings)}, {3, INPUT_DESC(constant_values)}};
// 输入映射x索引为1paddings索引为2constant_values索引为3
ATTR_MAP(PadV2) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(PadV2) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(PadV2, kNamePadV2, ADPT_DESC(PadV2))
// 注册PadV2操作的适配器描述kNamePadV2
} // namespace mindspore::transform

View File

@ -0,0 +1,74 @@
# 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.
# ==============================================================================
"""Process imagenet validate dataset.
处理imagenet验证数据集
"""
import os
import stat
from mindspore import log as logger
def preprocess_imagenet_validation_dataset(train_dataset_path, validation_dataset_path, image_label_mapping_file):
"""
在读取imagenet验证数据集之前调用此函数用于预处理数据集
Args:
train_dataset_path (str): 训练数据集路径
validation_dataset_path (str): 验证数据集路径
image_label_mapping_file (str): imagenet_validate_dataset_2012_image_dir_map.txt 文件路径
"""
# 获取训练数据集的绝对路径
train_dataset_path = os.path.realpath(train_dataset_path)
# 获取训练数据集中的子目录列表
sub_dir = [dir_.name for dir_ in os.scandir(train_dataset_path) if dir_.is_dir()]
# 遍历子目录并在验证数据集路径下创建对应的子目录
for sub_dir_name in sub_dir:
validate_sub_dir = os.path.join(validation_dataset_path, sub_dir_name)
validate_sub_dir = os.path.realpath(validate_sub_dir)
# 如果验证数据集子目录不存在,则创建之
if not os.path.exists(validate_sub_dir):
os.makedirs(validate_sub_dir, mode=stat.S_IRWXU)
# 获取映射文件的绝对路径
real_file_path = os.path.realpath(image_label_mapping_file)
# 读取映射文件中的映射关系
mappings = [mapping.strip() for mapping in open(real_file_path).readlines()]
# 遍历映射关系,将图像从训练目录移动到验证目录中的对应子目录
for mapping in mappings:
image_dir = mapping.split(':')
old_image_path = os.path.join(validation_dataset_path, image_dir[0])
old_image_path = os.path.realpath(old_image_path)
# 如果原始图像路径不存在,则发出警告
if not os.path.exists(old_image_path):
logger.warning('Image is not existed %s', old_image_path)
new_image_sub_dir = os.path.join(validation_dataset_path, image_dir[1])
new_image_sub_dir = os.path.realpath(new_image_sub_dir)
new_image_path = os.path.join(new_image_sub_dir, image_dir[0])
new_image_path = os.path.realpath(new_image_path)
# 如果新图像的子目录不存在,则发出警告
if not os.path.exists(new_image_sub_dir):
logger.warning('Image sub dir is not existed %s', new_image_sub_dir)
# 将图像从旧路径移到新路径
os.rename(old_image_path, new_image_path)

View File

@ -0,0 +1,265 @@
# Copyright 2020 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.
# ============================================================================
"""Python pass register"""
from inspect import isfunction # 检查对象是否为函数
from mindspore.graph_utils.graph_pattern import Pattern, NewParameter # 用于图模式匹配的类
from mindspore._c_expression import PyPassManager_ # 用于管理优化传递的类
# __all__ 列表用于指定在使用 "from <module> import *" 时导出的符号
# 它包含本脚本中定义的函数和类的名称,以便从外部访问
__all__ = [
"register_pass", # 注册新的优化传递到传递管理器中的函数
"unregister_pass", # 从传递管理器中注销优化传递的函数
"gen_new_parameter", # 生成用于图转换的新参数的函数
"cancel_new_parameter", # 取消生成新参数的函数
"set_renorm", # 设置图转换的重新归一化标志的函数
"set_reopt" # 设置图转换的重新优化标志的函数
]
# PyPassManager类继承自PyPassManager_用于注册和注销Python优化传递以便在编译期间对图进行修改。
class PyPassManager(PyPassManager_):
r"""
Used to register and unregister python passes which can be used to alter graphs.
Args:
requires_grad(bool): Do automatic-differentiation after modified graph if true. Default: True
run_only_once (bool): Specify whether or not to run pass only once. Default: False.
Raises:
TypeError: If argument has invalid type.
"""
#创建一个PyPassManager对象并用指定的参数requires_grad和run_only_once对其进行初始化。
#PyPassManager是用于管理优化传递的类它允许注册和注销Python优化传递函数以便在编译期间对计算图进行修改。
#通过创建PyPassManager对象可以将Python优化传递函数注册到特定的编译阶段并指定是否进行自动微分和是否只运行一次。
def __init__(self, requires_grad=True, run_only_once=False):
# 检查输入的参数run_only_once是否为bool类型否则抛出TypeError异常
if not isinstance(requires_grad, bool):
raise TypeError(f"Expect bool, got : ({type(requires_grad)}){requires_grad}")
# 检查输入的参数requires_grad是否为bool类型否则抛出TypeError异常
if not isinstance(run_only_once, bool):
raise TypeError(f"Expect bool, got : ({type(run_only_once)}){run_only_once}")
# 检查输入的参数run_only_once是否为bool类型否则抛出TypeError异常
self.requires_grad = requires_grad
self.run_only_once_ = run_only_once
# 将输入的参数requires_grad和run_only_once保存到实例变量中
PyPassManager_.__init__(self)
# 调用父类PyPassManager_的构造函数初始化PyPassManager_
# register函数的作用是将Python优化传递函数注册到优化传递管理器中以便在编译期间对计算图进行修改和优化。
# 创建一个PyPassManager对象后可以使用该对象调用register函数将编写的Python优化传递函数注册到传递管理器中。
# 注册后,该优化传递函数会在编译期间的特定阶段被自动调用,对计算图进行修改。
def register(self, py_pass):
if not isfunction(py_pass):
raise TypeError(f"Expect function pass, got : ({type(py_pass)}){py_pass}")
# 检查输入的py_pass是否为函数类型如果不是则抛出TypeError异常
pattern, target = py_pass()
# 调用py_pass函数获取其返回的图模式匹配的模式和目标
pass_name = py_pass.__name__
# 获取py_pass函数的名称作为优化传递的名称
if not isinstance(pattern, Pattern):
raise TypeError(f"Expect pattern of Pattern type, got : ({type(pattern)}){pattern}")
# 检查pattern是否为Pattern类型如果不是则抛出TypeError异常
if not isinstance(target, Pattern):
raise TypeError(f"Expect target of Pattern type, got : ({type(target)}){target}")
# 检查target是否为Pattern类型如果不是则抛出TypeError异常
super().register(pass_name, pattern, target, self.requires_grad, self.run_only_once_)
# 调用父类PyPassManager_的register方法将优化传递函数注册到传递管理器中
# 参数包括优化传递名称、图模式匹配的模式、目标、是否进行自动微分和是否只运行一次的标志
#该unregister方法用于从传递管理器中注销已注册的优化传递函数。优化传递函数的注册是通过register方法完成的。
def unregister(self, py_pass):
#如果输入的py_pass参数是字符串类型说明要注销一个已注册的优化传递函数
if isinstance(py_pass, str):
super().unregister(py_pass)
return
# 调用父类PyPassManager_的unregister方法传递优化传递名称从传递管理器中注销优化传递函数
# 如果输入的py_pass参数是函数类型说明要注销一个已注册的优化传递函数
if isfunction(py_pass):
super().unregister(py_pass.__name__)
return
# 调用父类PyPassManager_的unregister方法传递优化传递函数的名称从传递管理器中注销优化传递函数
raise TypeError(f"Expect py_pass to be string or function, got ({type(py_pass)}){py_pass}")
# 如果输入的py_pass参数既不是字符串也不是函数则抛出TypeError异常
#__call__方法在Python类中被称为"调用"方法,它使得该类的实例可以像函数一样被调用。
#在PyPassManager类中__call__方法用于将输入的Python优化传递函数py_pass注册到传递管理器中并在成功注册后返回该优化传递函数本身。
def __call__(self, py_pass):
self.register(py_pass)
# 调用register方法将输入的py_pass函数注册到传递管理器中
return py_pass
# 返回输入的py_pass函数本身
#这个方法用于生成用于图转换的新参数。
#首先,它检查传入的 pattern 参数是否是 NewParameter 类型的实例,如果不是,就会抛出异常。
#然后,它调用父类的 gen_new_parameter 方法,完成新参数的生成过程。
def gen_new_parameter(self, pattern):
if not isinstance(pattern, NewParameter):
raise TypeError(f"Expect pattern to be a NewParameter Pattern, got {pattern}")
# 检查输入的pattern参数是否为NewParameter类型如果不是则抛出TypeError异常
super().gen_new_parameter(pattern)
# 调用父类PyPassManager_的gen_new_parameter方法生成用于图转换的新参数
#这个方法用于设置一个参数 should_renorm用于指示是否进行重新规范化。
#首先,它检查传入的 should_renorm 参数是否是布尔类型,如果不是,就会抛出异常。
#然后,它调用父类的 set_renorm 方法,将 should_renorm 参数传递给它,完成重新规范化设置的操作。
def set_renorm(self, should_renorm):
if not isinstance(should_renorm, bool):
raise TypeError(f"Expect should_renorm to be a bool, got {should_renorm}")
# 检查输入的should_renorm参数是否为bool类型如果不是则抛出TypeError异常
super().set_renorm(should_renorm)
# 调用父类的set_renorm方法并将should_renorm参数传递给它
#这个方法用于设置一个参数 do_reopt用于指示是否进行重新优化。
#首先,它检查传入的 do_reopt 参数是否是布尔类型,如果不是,就会抛出异常。
#然后,它调用父类的 set_reopt 方法,将 do_reopt 参数传递给它,完成重新优化设置的操作。
def set_reopt(self, do_reopt):
if not isinstance(do_reopt, bool):
raise TypeError(f"Expect do_reopt to be a bool, got {do_reopt}")
# 检查输入的do_reopt参数是否为bool类型如果不是则抛出TypeError异常
super().set_reopt(do_reopt)
# 调用父类的set_reopt方法并将do_reopt参数传递给它
def register_pass(requires_grad=True, run_only_once=False):
"""
Register python pass to specified pipeline phase which would be used in compilation.
将python传递注册到指定的管道阶段该阶段将在编译中使用
Args: 参数:
requires_grad(bool): Do automatic-differentiation after modified graph if true. Default: True.
如果修改后的图为true则执行自动微分默认值:True
run_only_once(bool): Run this pass only once if set true. Otherwise run the pass until converge. Default:
False.
如果设置为true则只运行一次否则运行通道直到收敛默认值:False
Returns:
This function should be used as a decorator, return the decoratorated pass function.
这个函数应该被用作装饰器返回经过装饰的传递函数
Examples:
>>> from mindspore.graph_utils.graph_pattern import Call, Any
>>> from mindspore.ops import operations as P
>>> @register_pass()
>>> def toy_pass():
>>> x = Any()
>>> pattern = Call(P.Softmax(), [x])
>>> target = Call(P.ReLU(), [x])
>>> return pattern, target
"""
return PyPassManager(requires_grad, run_only_once)
def unregister_pass(py_pass):
"""
Unregister python pass.
注销python路径
Args:
py_pass(Union(str, function)): target python pass to unregister.
注销指定的python路径
"""
ppm = PyPassManager()
ppm.unregister(py_pass)
def gen_new_parameter(pattern):
"""
Generate specified parameter every time a network gets compiled.
每次编译网络时生成指定的参数
NOTE:
In this way, every pass uses this pattern would be using the same Parameter. If use NewParameter without
gen_new_parameter, every pass match would build a new Parameter.
This would register a pass to add new parameter in the compilation pipeline, so later compilation would
ALSO add this parameter unless the pass is unregistered. To unregister this pass, call
cancel_new_parameter(pattern)
这样每次使用此模式的pass都将使用相同的Parameter如使用gen_new_parameter之外的NewParameter
每次通过匹配都会构建一个新的Parameter
这将注册一个在编译管道中添加新参数的pass因此以后的编译将除非pass未注册否则也添加此参数
要注销此pass请调用cancel_new_parameter(模式)
Args:
pattern (NewParameter): NewParameter type, could be used to build nested patterns across multiple passes
after gen_new_parameter.
NewParameter类型可用于在gen_new_parameter之后跨多个pass构建嵌套模式
Raises:
TypeError: If argument has invalid type.
参数的类型无效
Examples:
>>> from mindspore.graph_utils.graph_pattern import NewParameter
>>> abc = NewParameter("abc")
>>> gen_new_parameter(abc)
"""
ppm = PyPassManager()
ppm.gen_new_parameter(pattern)
def cancel_new_parameter(pattern):
"""
Use with gen_new_parameter to unregister gen_new_parameter pass.
Args:
pattern (NewParameter): NewParameter type, cancel the pass which would add new parameter as this pattern
describes.
NewParameter类型取消将添加新参数的传递如该模式所描述的
Examples:
>>> from mindspore.graph_utils.graph_pattern import NewParameter
>>> abc = NewParameter("abc")
>>> gen_new_parameter(abs)
>>> # some compilations
>>> cancel_new_parameter(abc)
"""
if not isinstance(pattern, NewParameter):
raise TypeError(f"Expect pattern to be a NewParameter Pattern, got {pattern}")
ppm = PyPassManager()
ppm.unregister(pattern.para_name)
def set_renorm(should_renorm):
"""
Set whether or not to do renormalization after modified graph in python pass(es).
Args:
should_renorm(bool): whether or not to do renormalization after modified graph in python pass(es).
NOTE:
This interface is mainly intended for testing modifying graph without worrying about its validity. Turn off
renormalization may BREAK the network.
"""
ppm = PyPassManager()
ppm.set_renorm(should_renorm)
def set_reopt(do_reopt):
"""
Set whether or not to do optimization after modified graph in python pass(es).
Args:
do_reopt(bool): whether or not to do optimization after modified graph in python pass(es).
在python的pass中修改图形后是否进行重新规范化
NOTE:
This interface is mainly intended for testing modifying graph without worrying about its validity. Turn off
renormalization may BREAK the network.
该接口主要用于测试修改图而不用担心修改图的有效性关闭重整化可能会破坏网络
"""
ppm = PyPassManager()
ppm.set_reopt(do_reopt)

View File

@ -0,0 +1,44 @@
/**
* 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_declare/quantize_ops_declare.h"
namespace mindspore::transform {
// AscendQuant
INPUT_MAP(AscendQuant) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(AscendQuant) = {{"scale", ATTR_DESC(scale, AnyTraits<float>())},
{"offset", ATTR_DESC(offset, AnyTraits<float>())},
{"sqrt_mode", ATTR_DESC(sqrt_mode, AnyTraits<bool>())},
{"round_mode", ATTR_DESC(round_mode, AnyTraits<std::string>())}};
// 属性映射,列出了四个属性,"scale""offset"类型为float,"sqrt_mode"类型为bool,"round_mode"类型为std::string
OUTPUT_MAP(AscendQuant) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(AscendQuant, kNameAscendQuant, ADPT_DESC(AscendQuant))
// 注册AscendQuant操作的适配器描述kNameAscendQuant
// AscendDequant
INPUT_MAP(AscendDequant) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(deq_scale)}};
// 输入映射x索引为1deq_scale索引为2
ATTR_MAP(AscendDequant) = {{"sqrt_mode", ATTR_DESC(sqrt_mode, AnyTraits<bool>())},
{"relu_flag", ATTR_DESC(relu_flag, AnyTraits<bool>())},
{"dtype", ATTR_DESC(dtype, AnyTraits<GEType>())}};
// 属性映射,列出了四个属性,"sqrt_mode""relu_flag"类型为bool,"dtype"类型为GEType
OUTPUT_MAP(AscendDequant) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(AscendDequant, kNameAscendDequant, ADPT_DESC(AscendDequant))
//注册AscendDequant操作的适配器描述kNameAscendDequant
} // namespace mindspore::transform

View File

@ -0,0 +1,63 @@
/**
* Copyright 2019-2021 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_declare/random_ops_declare.h"
namespace mindspore::transform {
// DropOutGenMask
INPUT_MAP(DropOutGenMask) = {{1, INPUT_DESC(shape)}, {2, INPUT_DESC(prob)}};
// 输入映射shape索引为1prob索引为2
ATTR_MAP(DropOutGenMask) = {{"Seed0", ATTR_DESC(seed, AnyTraits<int64_t>())},
{"Seed1", ATTR_DESC(seed2, AnyTraits<int64_t>())}};
//属性映射,列出了两个属性,"Seed0""Seed1"类型为int64_t
OUTPUT_MAP(DropOutGenMask) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(DropOutGenMask, prim::kPrimDropoutGenMask->name(), ADPT_DESC(DropOutGenMask))
// 注册DropOutGenMask操作的适配器描述prim::kPrimDropoutGenMask->name()
//
// LinSpace
INPUT_MAP(LinSpace) = {{1, INPUT_DESC(start)}, {2, INPUT_DESC(stop)}, {3, INPUT_DESC(num)}};
// 输入映射start索引为1stop索引为2num索引为3
ATTR_MAP(LinSpace) = EMPTY_ATTR_MAP;
//属性映射,空
OUTPUT_MAP(LinSpace) = {{0, OUTPUT_DESC(output)}};
//输出映射output索引为空
REG_ADPT_DESC(LinSpace, kNameLinSpace, ADPT_DESC(LinSpace))
// 注册LinSpace操作的适配器描述kNameLinSpace
// RandomChoiceWithMask
INPUT_MAP(RandomChoiceWithMask) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(RandomChoiceWithMask) = {{"count", ATTR_DESC(count, AnyTraits<int64_t>())},
{"seed", ATTR_DESC(seed, AnyTraits<int64_t>())},
{"seed2", ATTR_DESC(seed2, AnyTraits<int64_t>())}};
// 属性映射,列出了三个属性,"count""seed""seed2"类型为int64_t
OUTPUT_MAP(RandomChoiceWithMask) = {{0, OUTPUT_DESC(y)}, {1, OUTPUT_DESC(mask)}};
// 输出映射y索引为0mask索引为1
REG_ADPT_DESC(RandomChoiceWithMask, kNameRandomChoiceWithMask, ADPT_DESC(RandomChoiceWithMask))
// 注册RandomChoiceWithMask操作的适配器描述kNameRandomChoiceWithMask
// TruncatedNormal
INPUT_MAP(TruncatedNormal) = {{1, INPUT_DESC(shape)}};
// 输入映射shape索引为1
ATTR_MAP(TruncatedNormal) = {{"seed", ATTR_DESC(seed, AnyTraits<int64_t>())},
{"seed2", ATTR_DESC(seed2, AnyTraits<int64_t>())}};
// 属性映射,列出了两个属性,"seed""seed2"类型为int64_t
OUTPUT_MAP(TruncatedNormal) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(TruncatedNormal, kNameTruncatedNormal, ADPT_DESC(TruncatedNormal))
// 注册TruncatedNormal操作的适配器描述kNameTruncatedNormal
} // namespace mindspore::transform

View File

@ -0,0 +1,161 @@
/**
* Copyright 2019-2021 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_declare/reduce_ops_declare.h"
#include <vector>
namespace mindspore::transform {
// BNTrainingReduce
INPUT_MAP(BNTrainingReduce) = {{1, INPUT_DESC(x)}};
// 输入映射x索引为1
ATTR_MAP(BNTrainingReduce) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(BNTrainingReduce) = {{0, OUTPUT_DESC(sum)}, {1, OUTPUT_DESC(square_sum)}};
// 输出映射sum索引为0square_sum索引为1
REG_ADPT_DESC(BNTrainingReduce, kNameBNTrainingReduce, ADPT_DESC(BNTrainingReduce))
//注册BNTrainingReduce操作的适配器描述kNameBNTrainingReduce
// BNTrainingReduceGrad
INPUT_MAP(BNTrainingReduceGrad) = {{1, INPUT_DESC(grads)}, {2, INPUT_DESC(x)}, {3, INPUT_DESC(diff_scale)},
{4, INPUT_DESC(diff_offset)}, {5, INPUT_DESC(scale)}, {6, INPUT_DESC(batch_mean)},
{7, INPUT_DESC(batch_variance)}};
//输入映射共七个grad索引为1x索引为2diff_scale索引为3diff_offset索引为4scale索引为5batch_mean索引为6batch_variance索引为7
ATTR_MAP(BNTrainingReduceGrad) = {{"epsilon", ATTR_DESC(epsilon, AnyTraits<float>())}};
// 属性映射,列出了"epsilon"类型为float
OUTPUT_MAP(BNTrainingReduceGrad) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(BNTrainingReduceGrad, kNameBNTrainingReduceGrad, ADPT_DESC(BNTrainingReduceGrad))
// 注册BNTrainingReduceGrad操作的适配器描述kNameBNTrainingReduceGrad
// BNTrainingUpdate
INPUT_MAP(BNTrainingUpdate) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(sum)}, {3, INPUT_DESC(square_sum)},
{4, INPUT_DESC(scale)}, {5, INPUT_DESC(offset)}, {6, INPUT_DESC(mean)},
{7, INPUT_DESC(variance)}};
// 输入映射共七个grad索引为1x索引为2diff_scale索引为3diff_offset索引为4scale索引为5batch_mean索引为6batch_variance索引为7
ATTR_MAP(BNTrainingUpdate) = {{"factor", ATTR_DESC(factor, AnyTraits<float>())},
{"epsilon", ATTR_DESC(epsilon, AnyTraits<float>())}};
// 属性映射,列出了"factor""epsilon"类型为float
OUTPUT_MAP(BNTrainingUpdate) = {{0, OUTPUT_DESC(y)},
{1, OUTPUT_DESC(mean)},
{2, OUTPUT_DESC(variance)},
{3, OUTPUT_DESC(batch_mean)},
{4, OUTPUT_DESC(batch_variance)}};
// 输出映射共五个y索引为0mean索引为1variance索引为2batch_mean索引为3batch_variance索引为4
REG_ADPT_DESC(BNTrainingUpdate, kNameBNTrainingUpdate, ADPT_DESC(BNTrainingUpdate))
// 注册BNTrainingUpdate操作的适配器描述kNameBNTrainingUpdate
// BNTrainingUpdateGrad
INPUT_MAP(BNTrainingUpdateGrad) = {
{1, INPUT_DESC(grads)}, {2, INPUT_DESC(x)}, {3, INPUT_DESC(batch_mean)}, {4, INPUT_DESC(batch_variance)}};
// 输入映射共五个grads索引为1x索引为2batch_mean索引为3batch_variance索引为4
ATTR_MAP(BNTrainingUpdateGrad) = {{"epsilon", ATTR_DESC(epsilon, AnyTraits<float>())}};
// 属性映射,"epsilon"类型为float
OUTPUT_MAP(BNTrainingUpdateGrad) = {{0, OUTPUT_DESC(diff_scale)}, {1, OUTPUT_DESC(diff_offset)}};
// 输出映射共两个diff_scale索引为0diff_offset索引为1
REG_ADPT_DESC(BNTrainingUpdateGrad, kNameBNTrainingUpdateGrad, ADPT_DESC(BNTrainingUpdateGrad))
// 注册BNTrainingUpdateGrad操作的适配器描述kNameBNTrainingUpdateGrad
// ReduceAnyD
INPUT_MAP(ReduceAnyD) = {{1, INPUT_DESC(x)}};
// 输入映射x索引为1
INPUT_ATTR_MAP(ReduceAnyD) = {
{2, ATTR_DESC(axes, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
// 输入属性映射axes索引为2类型为int64_t
ATTR_MAP(ReduceAnyD) = {{"keep_dims", ATTR_DESC(keep_dims, AnyTraits<bool>())}};
// 属性映射,"keep_dims"类型为bool
OUTPUT_MAP(ReduceAnyD) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(ReduceAnyD, kNameReduceAnyD, ADPT_DESC(ReduceAnyD))
// 注册ReduceAnyD操作的适配器描述 kNameReduceAnyD
// ReduceSumD
INPUT_MAP(ReduceSumD) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
INPUT_ATTR_MAP(ReduceSumD) = {
{2, ATTR_DESC(axes, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
// 输入属性映射axes索引为2类型为int64_t
ATTR_MAP(ReduceSumD) = {{"keep_dims", ATTR_DESC(keep_dims, AnyTraits<bool>())}};
// 属性映射,"keep_dims"类型为bool
OUTPUT_MAP(ReduceSumD) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(ReduceSumD, prim::kPrimReduceSum->name(), ADPT_DESC(ReduceSumD))
// 注册ReduceSumD操作的适配器描述 prim::kPrimReduceSum->name()
// ReduceProdD
INPUT_MAP(ReduceProdD) = {{1, INPUT_DESC(x)}};
// 输入映射x索引为1
INPUT_ATTR_MAP(ReduceProdD) = {
{2, ATTR_DESC(axes, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
// 输入属性映射axes索引为2类型为int64_t
ATTR_MAP(ReduceProdD) = {{"keep_dims", ATTR_DESC(keep_dims, AnyTraits<bool>())}};
// 属性映射,"keep_dims"类型为bool
OUTPUT_MAP(ReduceProdD) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(ReduceProdD, kNameReduceProd, ADPT_DESC(ReduceProdD))
// 注册ReduceProdD操作的适配器描述kNameReduceProd
// ReduceAllD
INPUT_MAP(ReduceAllD) = {{1, INPUT_DESC(x)}};
// 输入映射x索引为1
INPUT_ATTR_MAP(ReduceAllD) = {
{2, ATTR_DESC(axes, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
// 属性映射axes索引为2类型为int64_t
ATTR_MAP(ReduceAllD) = {{"keep_dims", ATTR_DESC(keep_dims, AnyTraits<bool>())}};
// 属性映射,"keep_dims"类型为bool
OUTPUT_MAP(ReduceAllD) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(ReduceAllD, prim::kPrimReduceAll->name(), ADPT_DESC(ReduceAllD))
// 注册ReduceAllD操作的适配器描述prim::kPrimReduceAll->name()
// ReduceMeanD
INPUT_MAP(ReduceMeanD) = {{1, INPUT_DESC(x)}};
// 输入映射x索引为1
INPUT_ATTR_MAP(ReduceMeanD) = {
{2, ATTR_DESC(axes, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
// 输入属性映射axes索引为2类型为int64_t
ATTR_MAP(ReduceMeanD) = {{"keep_dims", ATTR_DESC(keep_dims, AnyTraits<bool>())}};
// 属性映射,"keep_dims"类型为bool
OUTPUT_MAP(ReduceMeanD) = {{0, OUTPUT_DESC(y)}};
REG_ADPT_DESC(ReduceMeanD, prim::kPrimReduceMean->name(), ADPT_DESC(ReduceMeanD))
// 注册ReduceMeanD操作的适配器描述prim::kPrimReduceAll->name()
//
// ReduceMinD
INPUT_MAP(ReduceMinD) = {{1, INPUT_DESC(x)}};
// 输入映射x索引为1
INPUT_ATTR_MAP(ReduceMinD) = {
{2, ATTR_DESC(axes, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
// 输入属性映射axes索引为2类型为int64_t
ATTR_MAP(ReduceMinD) = {{"keep_dims", ATTR_DESC(keep_dims, AnyTraits<bool>())}};
// 属性映射,"keep_dims"类型为bool
OUTPUT_MAP(ReduceMinD) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(ReduceMinD, prim::kPrimReduceMin->name(), ADPT_DESC(ReduceMinD))
// 注册ReduceMinD操作的适配器描述prim::kPrimReduceAll->name()
// ReduceMaxD
INPUT_MAP(ReduceMaxD) = {{1, INPUT_DESC(x)}};
// 输入映射x索引为1
INPUT_ATTR_MAP(ReduceMaxD) = {
{2, ATTR_DESC(axes, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
// 输入属性映射axes索引为2类型为int64_t
ATTR_MAP(ReduceMaxD) = {{"keep_dims", ATTR_DESC(keep_dims, AnyTraits<bool>())}};
// 属性映射,"keep_dims"类型为bool
OUTPUT_MAP(ReduceMaxD) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(ReduceMaxD, prim::kPrimReduceMax->name(), ADPT_DESC(ReduceMaxD))
// 注册ReduceMaxD操作的适配器描述prim::kPrimReduceAll->name()
} // namespace mindspore::transform

View File

@ -0,0 +1,192 @@
/**
* Copyright 2019-2021 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_declare/rnn_declare.h"
namespace mindspore::transform {
// BasicLSTMCell
INPUT_MAP(BasicLSTMCell) = {
{1, INPUT_DESC(x)}, {2, INPUT_DESC(h)}, {3, INPUT_DESC(c)}, {4, INPUT_DESC(w)}, {5, INPUT_DESC(b)}};
// 输入映射共五个x索引为1h索引为2c索引为3w索引为4b索引为5
ATTR_MAP(BasicLSTMCell) = {{"keep_prob", ATTR_DESC(keep_prob, AnyTraits<float>())},
{"forget_bias", ATTR_DESC(forget_bias, AnyTraits<float>())},
{"state_is_tuple", ATTR_DESC(state_is_tuple, AnyTraits<bool>())},
{"activation", ATTR_DESC(activation, AnyTraits<std::string>())}};
// 属性映射,列出了"keep_prob"、"forget_bias"、"state_is_tuple"、"activation"四个属性类型分别为bool和std::string
OUTPUT_MAP(BasicLSTMCell) = {{0, OUTPUT_DESC(ct)}, {1, OUTPUT_DESC(ht)}, {2, OUTPUT_DESC(it)}, {3, OUTPUT_DESC(jt)},
{4, OUTPUT_DESC(ft)}, {5, OUTPUT_DESC(ot)}, {6, OUTPUT_DESC(tanhct)}}
// 输出映射共七个cty索引为0ht索引为1it索引为2jt索引为3ft索引为4ot索引为5tanhct索引为6
REG_ADPT_DESC(BasicLSTMCell, kNameBasicLSTMCell, ADPT_DESC(BasicLSTMCell))
// 注册BasicLSTMCell操作的适配器描述kNameBasicLSTMCell
// BasicLSTMCellInputGrad
INPUT_MAP(BasicLSTMCellInputGrad) = {{1, INPUT_DESC(dgate)}, {2, INPUT_DESC(w)}};
// 输入映射共两个dgate索引为1w索引为2
ATTR_MAP(BasicLSTMCellInputGrad) = {{"keep_prob", ATTR_DESC(keep_prob, AnyTraits<float>())}};
// 属性映射,列出了"keep_prob"属性类型为float
OUTPUT_MAP(BasicLSTMCellInputGrad) = {{0, OUTPUT_DESC(dxt)}, {1, OUTPUT_DESC(dht)}};
// 输出映射共两个dxt索引为0dht索引为1
REG_ADPT_DESC(BasicLSTMCellInputGrad, kNameBasicLSTMCellInputGrad, ADPT_DESC(BasicLSTMCellInputGrad))
// 注册BasicLSTMCellInputGrad操作的适配器描述kNameBasicLSTMCellInputGrad
// BasicLSTMCellWeightGrad
INPUT_MAP(BasicLSTMCellWeightGrad) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(h)}, {3, INPUT_DESC(dgate)}};
// 输入映射共三个dgate索引为1w索引为2dgate索引为3
ATTR_MAP(BasicLSTMCellWeightGrad) = EMPTY_ATTR_MAP;
//属性映射,空
OUTPUT_MAP(BasicLSTMCellWeightGrad) = {{0, OUTPUT_DESC(dw)}, {1, OUTPUT_DESC(db)}};
// 输出映射共两个dw索引为0db索引为1
REG_ADPT_DESC(BasicLSTMCellWeightGrad, kNameBasicLSTMCellWeightGrad, ADPT_DESC(BasicLSTMCellWeightGrad))
// 注册BasicLSTMCellWeightGrad操作的适配器描述kNameBasicLSTMCellWeightGrad
// BasicLSTMCellCStateGrad
INPUT_MAP(BasicLSTMCellCStateGrad) = {{1, INPUT_DESC(c)}, {2, INPUT_DESC(dht)}, {3, INPUT_DESC(dct)},
{4, INPUT_DESC(it)}, {5, INPUT_DESC(jt)}, {6, INPUT_DESC(ft)},
{7, INPUT_DESC(ot)}, {8, INPUT_DESC(tanhct)}};
// 输入映射共八个c索引为1dht索引为2dct索引为3it索引为4jt索引为5ft索引为6ot索引为7tanhct索引为8
ATTR_MAP(BasicLSTMCellCStateGrad) = {{"forget_bias", ATTR_DESC(forget_bias, AnyTraits<float>())},
{"activation", ATTR_DESC(activation, AnyTraits<std::string>())}};
// 属性映射,列出了"forget_bias"和"activation"属性类型分别为float和std::string
OUTPUT_MAP(BasicLSTMCellCStateGrad) = {{0, OUTPUT_DESC(dgate)}, {1, OUTPUT_DESC(dct_1)}};
// 输出映射共两个dgate索引为0dct_1索引为1
REG_ADPT_DESC(BasicLSTMCellCStateGrad, kNameBasicLSTMCellCStateGrad, ADPT_DESC(BasicLSTMCellCStateGrad))
// 注册BasicLSTMCellCStateGrad操作的适配器描述kNameBasicLSTMCellCStateGrad
// LSTMInputGrad
INPUT_MAP(LSTMInputGrad) = {{1, INPUT_DESC(w)}, {2, INPUT_DESC(init_c)}, {3, INPUT_DESC(c)}, {4, INPUT_DESC(dy)},
{5, INPUT_DESC(dh)}, {6, INPUT_DESC(dc)}, {7, INPUT_DESC(i)}, {8, INPUT_DESC(j)},
{9, INPUT_DESC(f)}, {10, INPUT_DESC(o)}, {11, INPUT_DESC(tanhct)}};
//输入映射共十一个w索引为1init_c索引为2di索引为3dy索引为4dh索引为5dc索引为6i索引为7j索引为8f索引为9o索引为10tanhct索引为11
ATTR_MAP(LSTMInputGrad) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(LSTMInputGrad) = {
{0, OUTPUT_DESC(dx)}, {1, OUTPUT_DESC(dh_prev)}, {2, OUTPUT_DESC(dc_prev)}, {4, OUTPUT_DESC(dgate)}};
// 输出映射共四个dh_prev索引为1dc_prev索引为2dgate索引为4
REG_ADPT_DESC(LSTMInputGrad, kNameLSTMInputGrad, ADPT_DESC(LSTMInputGrad))
// 注册LSTMInputGrad操作的适配器描述kNameLSTMInputGrad
// DynamicRNN
INPUT_MAP(DynamicRNN) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(w)}, {3, INPUT_DESC(b)},
{4, INPUT_DESC(seq_length)}, {5, INPUT_DESC(init_h)}, {6, INPUT_DESC(init_c)},
{7, INPUT_DESC(wci)}, {8, INPUT_DESC(wcf)}, {9, INPUT_DESC(wco)},
{10, INPUT_DESC(mask)}};
// 输入映射共十个x索引为1w索引为2b索引为3seq_length索引为4init_h索引为5init_c索引为6wci索引为7wcf索引为8wco索引为9mask索引为10
ATTR_MAP(DynamicRNN) = {{"cell_type", ATTR_DESC(cell_type, AnyTraits<std::string>())},
{"direction", ATTR_DESC(direction, AnyTraits<std::string>())},
{"cell_depth", ATTR_DESC(cell_depth, AnyTraits<int64_t>())},
{"use_peephole", ATTR_DESC(use_peephole, AnyTraits<bool>())},
{"keep_prob", ATTR_DESC(keep_prob, AnyTraits<float>())},
{"cell_clip", ATTR_DESC(cell_clip, AnyTraits<float>())},
{"num_proj", ATTR_DESC(num_proj, AnyTraits<int64_t>())},
{"time_major", ATTR_DESC(time_major, AnyTraits<bool>())},
{"ivation", ATTR_DESC(activation, AnyTraits<std::string>())},
{"forget_bias", ATTR_DESC(forget_bias, AnyTraits<float>())},
{"is_training", ATTR_DESC(is_training, AnyTraits<bool>())}};
// 属性映射,列出了"cell_type""ivation"和"direction"属性类型为std::string
//"cell_depth"和"num_proj",类型为int64_t
//"use_peephole""is_training"和"time_major"类型为bool
//"keep_prob""cell_clip""forget_bias"类型为float
OUTPUT_MAP(DynamicRNN) = {{0, OUTPUT_DESC(y)}, {1, OUTPUT_DESC(output_h)}, {2, OUTPUT_DESC(output_c)},
{3, OUTPUT_DESC(i)}, {4, OUTPUT_DESC(j)}, {5, OUTPUT_DESC(f)},
{6, OUTPUT_DESC(o)}, {7, OUTPUT_DESC(tanhc)}};
// 输出映射共十个x索引为1w索引为2b索引为3seq_length索引为4init_h索引为5init_c索引为6wci索引为7wcf索引为8wco索引为9mask索引为10
REG_ADPT_DESC(DynamicRNN, kNameDynamicRNN, ADPT_DESC(DynamicRNN))
// 注册DynamicRNN操作的适配器描述kNameDynamicRNN
// DynamicRNNGrad
INPUT_MAP(DynamicRNNGrad) = {
{1, INPUT_DESC(x)}, {2, INPUT_DESC(w)}, {3, INPUT_DESC(b)}, {4, INPUT_DESC(y)},
{5, INPUT_DESC(init_h)}, {6, INPUT_DESC(init_c)}, {7, INPUT_DESC(h)}, {8, INPUT_DESC(c)},
{9, INPUT_DESC(dy)}, {10, INPUT_DESC(dh)}, {11, INPUT_DESC(dc)}, {12, INPUT_DESC(i)},
{13, INPUT_DESC(j)}, {14, INPUT_DESC(f)}, {15, INPUT_DESC(o)}, {16, INPUT_DESC(tanhct)}};
// 输入映射共十个x索引为1w索引为2b索引为3y索引为4init_h索引为5init_c索引为6h索引为7c索引为8dy索引为9dh索引为10,dc索引为11i索引为12
//j索引为13f索引为14o索引为15tanhct索引为16
ATTR_MAP(DynamicRNNGrad) = {{"cell_type", ATTR_DESC(cell_type, AnyTraits<std::string>())},
{"direction", ATTR_DESC(direction, AnyTraits<std::string>())},
{"cell_depth", ATTR_DESC(cell_depth, AnyTraits<int64_t>())},
{"use_peephole", ATTR_DESC(use_peephole, AnyTraits<bool>())},
{"keep_prob", ATTR_DESC(keep_prob, AnyTraits<float>())},
{"cell_clip", ATTR_DESC(cell_clip, AnyTraits<float>())},
{"num_proj", ATTR_DESC(num_proj, AnyTraits<int64_t>())},
{"time_major", ATTR_DESC(time_major, AnyTraits<bool>())},
{"forget_bias", ATTR_DESC(forget_bias, AnyTraits<float>())}};
// 属性映射,列出了"cell_type"和"direction"属性类型为std::string
//"cell_depth"和"num_proj",类型为int64_t
//"use_peephole""is_training"和"time_major"类型为bool
//"keep_prob""cell_clip""forget_bias"类型为float
OUTPUT_MAP(DynamicRNNGrad) = {{0, OUTPUT_DESC(dw)},
{1, OUTPUT_DESC(db)},
{2, OUTPUT_DESC(dx)},
{3, OUTPUT_DESC(dh_prev)},
{4, OUTPUT_DESC(dc_prev)}};
// 输出映射共五个dw索引为0db索引为1dh_prev索引为2dh_prev索引为3dc_prev索引为4
REG_ADPT_DESC(DynamicRNNGrad, kNameDynamicRNNGrad, ADPT_DESC(DynamicRNNGrad))
// 注册DynamicRNNGrad操作的适配器描述kNameDynamicRNNGrad
// DynamicGRUV2
INPUT_MAP(DynamicGRUV2) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(weight_input)}, {3, INPUT_DESC(weight_hidden)},
{4, INPUT_DESC(bias_input)}, {5, INPUT_DESC(bias_hidden)}, {6, INPUT_DESC(seq_length)},
{7, INPUT_DESC(init_h)}};
// 输入映射共七个x索引为1weight_input索引为2weight_hidden索引为3bias_input索引为4bias_hidden索引为5seq_length索引为6init_h索引为7
ATTR_MAP(DynamicGRUV2) = {{"direction", ATTR_DESC(direction, AnyTraits<std::string>())},
{"cell_depth", ATTR_DESC(cell_depth, AnyTraits<int64_t>())},
{"keep_prob", ATTR_DESC(keep_prob, AnyTraits<float>())},
{"cell_clip", ATTR_DESC(cell_clip, AnyTraits<float>())},
{"num_proj", ATTR_DESC(num_proj, AnyTraits<int64_t>())},
{"time_major", ATTR_DESC(time_major, AnyTraits<bool>())},
{"activation", ATTR_DESC(activation, AnyTraits<std::string>())},
{"gate_order", ATTR_DESC(gate_order, AnyTraits<std::string>())},
{"reset_after", ATTR_DESC(reset_after, AnyTraits<bool>())},
{"is_training", ATTR_DESC(is_training, AnyTraits<bool>())}};
// 属性映射,列出了"direction"和"activation""gate_order"属性类型为std::string
//"cell_depth"和"num_proj",类型为int64_t
//"reset_after""is_training"和"time_major"类型为bool
//"keep_prob""cell_clip""forget_bias"类型为float
OUTPUT_MAP(DynamicGRUV2) = {{0, OUTPUT_DESC(y)}, {1, OUTPUT_DESC(output_h)}, {2, OUTPUT_DESC(update)},
{3, OUTPUT_DESC(reset)}, {4, OUTPUT_DESC(new)}, {5, OUTPUT_DESC(hidden_new)}};
// 输入映射共六个y索引为0output_h索引为1update索引为2reset索引为3new索引为4hidden_new索引为5
REG_ADPT_DESC(DynamicGRUV2, kNameDynamicGRUV2, ADPT_DESC(DynamicGRUV2))
// 注册DynamicGRUV2操作的适配器描述kNameDynamicGRUV2
//
// DynamicGRUV2Grad
INPUT_MAP(DynamicGRUV2Grad) = {
{1, INPUT_DESC(x)}, {2, INPUT_DESC(weight_input)}, {3, INPUT_DESC(weight_hidden)},
{4, INPUT_DESC(y)}, {5, INPUT_DESC(init_h)}, {6, INPUT_DESC(h)},
{7, INPUT_DESC(dy)}, {8, INPUT_DESC(dh)}, {9, INPUT_DESC(update)},
{10, INPUT_DESC(reset)}, {11, INPUT_DESC(new)}, {12, INPUT_DESC(hidden_new)},
{13, INPUT_DESC(seq_length)}, {14, INPUT_DESC(mask)}};
// 输入映射共十四个x索引为1weight_input索引为2weight_hidden索引为3y索引为4init_h索引为5h索引为6dy索引为7dh索引为8
//update索引为9reset索引为10new索引为11hidden_new索引为12seq_length索引为13mask索引为14
ATTR_MAP(DynamicGRUV2Grad) = {{"direction", ATTR_DESC(direction, AnyTraits<std::string>())},
{"cell_depth", ATTR_DESC(cell_depth, AnyTraits<int64_t>())},
{"keep_prob", ATTR_DESC(keep_prob, AnyTraits<float>())},
{"cell_clip", ATTR_DESC(cell_clip, AnyTraits<float>())},
{"num_proj", ATTR_DESC(num_proj, AnyTraits<int64_t>())},
{"time_major", ATTR_DESC(time_major, AnyTraits<bool>())},
{"gate_order", ATTR_DESC(gate_order, AnyTraits<std::string>())},
{"reset_after", ATTR_DESC(reset_after, AnyTraits<bool>())}};
// 属性映射,列出了"direction"和"activation""gate_order"属性类型为std::string
//"cell_depth"和"num_proj",类型为int64_t
//"reset_after""is_training"和"time_major"类型为bool
//"keep_prob""cell_clip"类型为float
OUTPUT_MAP(DynamicGRUV2Grad) = {{0, OUTPUT_DESC(dw_input)}, {1, OUTPUT_DESC(dw_hidden)}, {2, OUTPUT_DESC(db_input)},
{3, OUTPUT_DESC(db_hidden)}, {4, OUTPUT_DESC(dx)}, {5, OUTPUT_DESC(dh_prev)}};
// 输入映射共六个dw_input索引为0dw_hidden索引为1db_input索引为2db_hidden索引为3dx索引为4dh_prev索引为5
REG_ADPT_DESC(DynamicGRUV2Grad, kNameDynamicGRUV2Grad, ADPT_DESC(DynamicGRUV2Grad))
// 注册DynamicGRUV2Grad操作的适配器描述kNameDynamicGRUV2Grad
} // namespace mindspore::transform

View File

@ -0,0 +1,35 @@
/**
* 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_declare/rpn_ops_declare.h"
namespace mindspore::transform {
// NMSWithMask
INPUT_MAP(NMSWithMask) = {{1, INPUT_DESC(box_scores)}};
//输入映射输入的形参是box_scores
ATTR_MAP(NMSWithMask) = {{"iou_threshold", ATTR_DESC(iou_threshold, AnyTraits<float>())}};
//属性映射,其中包含一个属性 "iou_threshold"。该属性使用名为 "iou_threshold" 的属性描述(ATTR_DESC)
//并指定其值的类型为 float。"iou_threshold" 属性可能用于指定非极大值抑制 (NMS) 过程中的 IoU 阈值。
OUTPUT_MAP(NMSWithMask) = {
{0, OUTPUT_DESC(selected_boxes)}, {1, OUTPUT_DESC(selected_idx)}, {2, OUTPUT_DESC(selected_mask)}};
//定义 "NMSWithMask" 运算符的输出映射(OUTPUT_MAP)将输出索引0映射为名为 "selected_boxes" 的输出描述(OUTPUT_DESC)
//将输出索引1映射为名为 "selected_idx" 的输出描述将输出索引2映射为名为 "selected_mask" 的输出描述。
//这表示 "NMSWithMask" 运算符在计算过程中会产生三个输出结果。
REG_ADPT_DESC(NMSWithMask, kNameNMSWithMask, ADPT_DESC(NMSWithMask))
//注册 "NMSWithMask" 运算符的适配器描述(REG_ADPT_DESC)。
//适配器描述中包含运算符名称 "kNameNMSWithMask" 和适配器描述(ADPT_DESC)。
//这将把 "NMSWithMask" 运算符与其在框架中的实现关联起来。
} // namespace mindspore::transform

View File

@ -0,0 +1,320 @@
/**
* Copyright 2019-2021 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 <vector>
#include "transform/graph_ir/op_declare/selection_ops_declare.h"
namespace mindspore::transform {
// CumsumD
INPUT_MAP(CumsumD) = {{1, INPUT_DESC(x)}};
//一个输入映射x
INPUT_ATTR_MAP(CumsumD) = {{2, ATTR_DESC(axis, AnyTraits<int64_t>())}};
//CumsumD操作的输入属性映射有一个名为"axis"的属性类型为int64_t
ATTR_MAP(CumsumD) = {{"exclusive", ATTR_DESC(exclusive, AnyTraits<bool>())},
{"reverse", ATTR_DESC(reverse, AnyTraits<bool>())}};
// CumsumD操作的属性映射列出了"exclusive"和"reverse"两个属性类型分别为bool
OUTPUT_MAP(CumsumD) = {{0, OUTPUT_DESC(y)}};
// CumsumD操作的输出映射有一个输出"y"索引为0
REG_ADPT_DESC(CumsumD, kNameCumSum, ADPT_DESC(CumsumD))
// 注册CumsumD操作的适配器描述kNameCumSum
//
// GatherV2
INPUT_MAP(GatherV2) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(axis)}};
// GatherV2操作的输入映射有三个输入"x"、"indices"、"axis"索引分别为1、2、3
ATTR_MAP(GatherV2) = EMPTY_ATTR_MAP;
// GatherV2操作没有属性为空的属性映射
OUTPUT_MAP(GatherV2) = {{0, OUTPUT_DESC(y)}};
// GatherV2操作的输出映射有一个输出"y"索引为0
//
// CumprodD
INPUT_MAP(CumprodD) = {{1, INPUT_DESC(x)}};
// CumprodD操作的输入映射有一个输入"x"索引为1
INPUT_ATTR_MAP(CumprodD) = {{2, ATTR_DESC(axis, AnyTraits<int64_t>())}};
// CumprodD操作的输入属性映射有一个名为"axis"的属性类型为int64_tz
ATTR_MAP(CumprodD) = {{"exclusive", ATTR_DESC(exclusive, AnyTraits<bool>())},
{"reverse", ATTR_DESC(reverse, AnyTraits<bool>())}};
// CumprodD操作的属性映射列出了"exclusive"和"reverse"两个属性类型分别为bool
OUTPUT_MAP(CumprodD) = {{0, OUTPUT_DESC(y)}};
// CumprodD操作的输出映射有一个输出"y"索引为0
REG_ADPT_DESC(CumprodD, kNameCumProd, ADPT_DESC(CumprodD))
// 注册CumprodD操作的适配器描述kNameCumProd
INPUT_MAP(SliceD) = {{1, INPUT_DESC(x)}};
// SliceD操作的输入映射有一个输入"x"索引为1
INPUT_ATTR_MAP(SliceD) = {{2, ATTR_DESC(offsets, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
{3, ATTR_DESC(size, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())}};
// 有两个输入属性,分别是"offsets"和"size"对应的类型分别是int64_t和std::vector<int64_t>。
ATTR_MAP(SliceD) = EMPTY_ATTR_MAP;
//SliceD操作没有属性为空的属性映射
OUTPUT_MAP(SliceD) = {{0, OUTPUT_DESC(y)}};
// SliceD操作的输出映射
REG_ADPT_DESC(SliceD, kNameSlice, ADPT_DESC(SliceD))
//注册SliceD操作的适配器描述kNameSlice
// TopK
INPUT_MAP(TopK) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(k)}};
// TopK操作的输入映射有两个输入"x"、"k"索引分别为1、2
ATTR_MAP(TopK) = {{"sorted", ATTR_DESC(sorted, AnyTraits<bool>())}};
//属性映射有一个属性sort类型是bool
OUTPUT_MAP(TopK) = {{0, OUTPUT_DESC(values)}, {1, OUTPUT_DESC(indices)}};
//输入映射,有两个输出:"values"、"indices"索引分别为0、1
REG_ADPT_DESC(TopK, kNameTopK, ADPT_DESC(TopK))
// 注册TopK操作的适配器描述kNameTopK
// InTopK
INPUT_MAP(InTopKD) = {{1, INPUT_DESC(x1)}, {2, INPUT_DESC(x2)}};
// InTopKD操作的输入映射有两个输入"x1"、"x2"索引分别为1、2
ATTR_MAP(InTopKD) = {{"k", ATTR_DESC(k, AnyTraits<int64_t>())}};
//属性映射有一个属性k类型是int64_t
OUTPUT_MAP(InTopKD) = {{0, OUTPUT_DESC(y)}};
//输出映射有一个输出y索引是0
REG_ADPT_DESC(InTopKD, kNameInTopKD, ADPT_DESC(InTopKD))
//注册InTopKD操作的适配器kNameInTopK
// TileD
INPUT_MAP(TileD) = {{1, INPUT_DESC(x)}};
//输入映射有一个输入x索引是1
INPUT_ATTR_MAP(TileD) = {{2, ATTR_DESC(multiples, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())}};
// 输入属性multiples对应的类型是int64_t和std::vector<int64_t>索引是2
ATTR_MAP(TileD) = EMPTY_ATTR_MAP;
//属性映射,空
OUTPUT_MAP(TileD) = {{0, OUTPUT_DESC(y)}};
//输出映射有一个输出y索引时0
REG_ADPT_DESC(TileD, kNameTile, ADPT_DESC(TileD))
// 注册TileD操作的适配器kNameTile
// OneHot
INPUT_MAP(OneHot) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(depth)}, {3, INPUT_DESC(on_value)}, {4, INPUT_DESC(off_value)}};
// 输入映射有四个输入x、depth、on_value、off_value索引分别是1、2、3、4
ATTR_MAP(OneHot) = {{"axis", ATTR_DESC(axis, AnyTraits<int64_t>())}};
//属性映射一个属性axis类型为int64_t
OUTPUT_MAP(OneHot) = {{0, OUTPUT_DESC(y)}};
//输出映射一个输出y索引为0
REG_ADPT_DESC(OneHot, prim::kPrimOneHot->name(), ADPT_DESC(OneHot))
//将名为 "OneHot" 的操作与适配器描述进行注册。
//将"OneHot" 的名称prim::kPrimOneHot->name()和适配器描述ADPT_DESC(OneHot))关联起来
// GatherV2D
INPUT_MAP(GatherV2D) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(indices)}};
//输入映射有两个输入x、indices,索引分别为1、2
INPUT_ATTR_MAP(GatherV2D) = {{3, ATTR_DESC(axis, AnyTraits<int64_t>())}};
//输入属性映射int64_t型的axis索引为3
ATTR_MAP(GatherV2D) = EMPTY_ATTR_MAP;
//属性映射,空
OUTPUT_MAP(GatherV2D) = {{0, OUTPUT_DESC(y)}};
//有一个输出映射y索引为0
REG_ADPT_DESC(GatherV2D, prim::kPrimGather->name(), ADPT_DESC(GatherV2D))
//这行代码是将名为 "GatherV2D" 的操作与适配器描述进行注册。
//它将 "GatherV2D" 的名称prim::kPrimGather->name()和适配器描述ADPT_DESC(GatherV2D))关联起来,以便在特定计算框架或引擎中能够正确地执行和优化 "GatherV2D" 操作。
REG_ADPT_DESC(Gather, kNameGather, ADPT_DESC(GatherV2D))
//将名为 "Gather" 的操作与适配器描述进行注册。
//将 "Gather" 的名称kNameGather和适配器描述ADPT_DESC(GatherV2D))关联起来,以便在特定计算框架或引擎中能够正确地执行和优化 "Gather" 操作。
// ScatterNdD
INPUT_MAP(ScatterNdD) = {{1, INPUT_DESC(indices)}, {2, INPUT_DESC(x)}};
//输入映射有两个indices和x索引为1、2
INPUT_ATTR_MAP(ScatterNdD) = {
{3, ATTR_DESC(shape, AnyTraits<std::vector<int64_t>>(), AnyTraits<std::vector<int64_t>>())}};
//输入属性映射int64_t型的shape索引为3
ATTR_MAP(ScatterNdD) = EMPTY_ATTR_MAP;
//属性映射为空
OUTPUT_MAP(ScatterNdD) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(ScatterNdD, kNameScatterNdD, ADPT_DESC(ScatterNdD))
// 将名为 "ScatterNdD" 的操作与适配器描述进行注册。
// 将 "ScatterNdD" 的名称kNameScatterNdD和适配器描述ADPT_DESC(ScatterNdD))关联起来,以便在特定计算框架或引擎中能够正确地执行和优化 "ScatterNdD" 操作。
//
// ScatterNonAliasingAdd
INPUT_MAP(ScatterNonAliasingAdd) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(indices)}, {3, INPUT_DESC(updates)}};
//输入映射共三个x索引为1indices索引为2updates索引为3
ATTR_MAP(ScatterNonAliasingAdd) = EMPTY_ATTR_MAP;
//属性映射,空
OUTPUT_MAP(ScatterNonAliasingAdd) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(ScatterNonAliasingAdd, kNameScatterNonAliasingAdd, ADPT_DESC(ScatterNonAliasingAdd))
// 注册ScatterNonAliasingAdd操作的适配器描述kNameScatterNonAliasingAdd
//
// GatherNd
INPUT_MAP(GatherNd) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(indices)}};
//输入映射共两个x索引为1indices索引为2
ATTR_MAP(GatherNd) = EMPTY_ATTR_MAP;
//属性映射,空
OUTPUT_MAP(GatherNd) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(GatherNd, kNameGatherNd, ADPT_DESC(GatherNd))
// 注册GatherNd操作的适配器描述 kNameGatherNd
// GatherD
INPUT_MAP(GatherD) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(dim)}, {3, INPUT_DESC(index)}};
//输入映射共三个x索引为1dim索引为2,index索引为3
ATTR_MAP(GatherD) = EMPTY_ATTR_MAP;
//属性映射,空
OUTPUT_MAP(GatherD) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(GatherD, kNameGatherD, ADPT_DESC(GatherD))
// 注册kNameGatherD操作的适配器描述 GatherD
// Range
INPUT_MAP(RangeD) = {{1, INPUT_DESC(x)}};
//输入映射x索引为1
ATTR_MAP(RangeD) = {{"start", ATTR_DESC(start, AnyTraits<float>())},
{"limit", ATTR_DESC(limit, AnyTraits<float>())},
{"delta", ATTR_DESC(delta, AnyTraits<float>())}};
//属性映射,列出了"start"、"limit"、"delta"三个属性类型分别为float
REG_ADPT_DESC(RangeD, kNameRange, ADPT_DESC(RangeD))
//注册RangeD操作的适配器描述 kNameRange
// InplaceAddD
INPUT_MAP(InplaceAddD) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(v)}};
// 输入映射x索引为1y索引为2
ATTR_MAP(InplaceAddD) = {{"indices", ATTR_DESC(indices, AnyTraits<std::vector<int64_t>>())}};
//属性映射,属性indices类型为int64_t
OUTPUT_MAP(InplaceAddD) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(InplaceAddD, kNameInplaceAddD, ADPT_DESC(InplaceAddD))
// 注册RangeD操作的适配器描述 kNameRange
// InplaceSubD
INPUT_MAP(InplaceSubD) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(v)}};
//输入映射共两个x索引为1y索引为2
ATTR_MAP(InplaceSubD) = {{"indices", ATTR_DESC(indices, AnyTraits<std::vector<int64_t>>())}};
// 属性映射,属性indices类型为int64_t
OUTPUT_MAP(InplaceSubD) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(InplaceSubD, kNameInplaceSubD, ADPT_DESC(InplaceSubD))
// 注册InplaceSubD操作的适配器描述kNameInplaceSubD
// InplaceUpdateD
INPUT_MAP(InplaceUpdateD) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(v)}};
// 输入映射共两个x索引为1y索引为2
ATTR_MAP(InplaceUpdateD) = {{"indices", ATTR_DESC(indices, AnyTraits<std::vector<int64_t>>())}};
// 属性映射,属性indices类型为int64_t
OUTPUT_MAP(InplaceUpdateD) = {{0, OUTPUT_DESC(y)}};
// 输出映射,y索引为0
REG_ADPT_DESC(InplaceUpdateD, kNameInplaceUpdateD, ADPT_DESC(InplaceUpdateD))
// 注册InplaceUpdateD操作的适配器描述kNameInplaceUpdateD
// Select
INPUT_MAP(Select) = {{1, INPUT_DESC(condition)}, {2, INPUT_DESC(x1)}, {3, INPUT_DESC(x2)}};
// 输入映射共三个condition索引为1x1索引为2x2索引为3
ATTR_MAP(Select) = EMPTY_ATTR_MAP;
//属性映射,空
OUTPUT_MAP(Select) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(Select, prim::kPrimSelect->name(), ADPT_DESC(Select))
// 注册InplaceUpdateD操作的适配器描述prim::kPrimSelect->name()
// StridedSliceGrad
INPUT_MAP(StridedSliceGrad) = {
{1, INPUT_DESC(dy)}, {2, INPUT_DESC(shape)}, {3, INPUT_DESC(begin)}, {4, INPUT_DESC(end)}, {5, INPUT_DESC(strides)}};
// 输入映射共五个dy索引为1shape索引为2begin索引为3end索引为4strides索引为5
ATTR_MAP(StridedSliceGrad) = {{"begin_mask", ATTR_DESC(begin_mask, AnyTraits<int64_t>())},
{"end_mask", ATTR_DESC(end_mask, AnyTraits<int64_t>())},
{"ellipsis_mask", ATTR_DESC(ellipsis_mask, AnyTraits<int64_t>())},
{"new_axis_mask", ATTR_DESC(new_axis_mask, AnyTraits<int64_t>())},
{"shrink_axis_mask", ATTR_DESC(shrink_axis_mask, AnyTraits<int64_t>())}};
// 属性映射,列出了"begin_mask"、"end_mask"、"ellipsis_mask"、"new_axis_mask"、"shrink_axis_mask"五个属性类型分别为int64_t
OUTPUT_MAP(StridedSliceGrad) = {{0, OUTPUT_DESC(output)}};
// 输出映射output索引为0
REG_ADPT_DESC(StridedSliceGrad, kNameStridedSliceGrad, ADPT_DESC(StridedSliceGrad))
//注册StridedSliceGradD操作的适配器描述kNameStridedSliceGrad
// StridedSlice
INPUT_MAP(StridedSlice) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(begin)}, {3, INPUT_DESC(end)}, {4, INPUT_DESC(strides)}};
// 输入映射共四个x索引为1begin索引为2end索引为3strides索引为4
ATTR_MAP(StridedSlice) = {{"begin_mask", ATTR_DESC(begin_mask, AnyTraits<int64_t>())},
{"end_mask", ATTR_DESC(end_mask, AnyTraits<int64_t>())},
{"ellipsis_mask", ATTR_DESC(ellipsis_mask, AnyTraits<int64_t>())},
{"new_axis_mask", ATTR_DESC(new_axis_mask, AnyTraits<int64_t>())},
{"shrink_axis_mask", ATTR_DESC(shrink_axis_mask, AnyTraits<int64_t>())}};
// 属性映射,列出了"begin_mask"、"end_mask"、"ellipsis_mask"、"new_axis_mask"、"shrink_axis_mask"五个属性类型分别为int64_t
OUTPUT_MAP(StridedSlice) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(StridedSlice, kNameStridedSlice, ADPT_DESC(StridedSlice))
// 注册StridedSlice操作的适配器描述kNameStridedSlice
// StridedSliceV2
INPUT_MAP(StridedSliceV2) = {
{1, INPUT_DESC(x)}, {2, INPUT_DESC(begin)}, {3, INPUT_DESC(end)}, {4, INPUT_DESC(axes)}, {5, INPUT_DESC(strides)}};
// 输入映射共五个x索引为1begin索引为2end索引为3axes索引为4strides索引为5
ATTR_MAP(StridedSliceV2) = {{"begin_mask", ATTR_DESC(begin_mask, AnyTraits<int64_t>())},
{"end_mask", ATTR_DESC(end_mask, AnyTraits<int64_t>())},
{"ellipsis_mask", ATTR_DESC(ellipsis_mask, AnyTraits<int64_t>())},
{"new_axis_mask", ATTR_DESC(new_axis_mask, AnyTraits<int64_t>())},
{"shrink_axis_mask", ATTR_DESC(shrink_axis_mask, AnyTraits<int64_t>())}};
// 属性映射,列出了"begin_mask"、"end_mask"、"ellipsis_mask"、"new_axis_mask"、"shrink_axis_mask"五个属性类型分别为int64_t
OUTPUT_MAP(StridedSliceV2) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(StridedSliceV2, kNameStridedSliceV2, ADPT_DESC(StridedSliceV2))
// 注册StridedSliceV2操作的适配器描述StridedSliceV2
// UnsortedSegmentSum
INPUT_MAP(UnsortedSegmentSumD) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(segment_ids)}};
// 输入映射共两个x索引为1segment_ids索引为2
INPUT_ATTR_MAP(UnsortedSegmentSumD) = {{3, ATTR_DESC(num_segments, AnyTraits<int64_t>())}};
// 输入属性映射num_segments类型是int64_t,索引是3
ATTR_MAP(UnsortedSegmentSumD) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(UnsortedSegmentSumD) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(UnsortedSegmentSumD, prim::kPrimUnsortedSegmentSum->name(), ADPT_DESC(UnsortedSegmentSumD))
//注册UnsortedSegmentSumD操作的适配器描述prim::kPrimUnsortedSegmentSum->name()
// UnsortedSegmentProdD
INPUT_MAP(UnsortedSegmentProdD) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(segment_ids)}};
// 输入映射共两个x索引为1segment_ids索引为2
INPUT_ATTR_MAP(UnsortedSegmentProdD) = {{3, ATTR_DESC(num_segments, AnyTraits<int64_t>())}};
// 输入属性映射num_segments类型是int64_t,索引是3
ATTR_MAP(UnsortedSegmentProdD) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(UnsortedSegmentProdD) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(UnsortedSegmentProdD, kNameUnsortedSegmentProdD, ADPT_DESC(UnsortedSegmentProdD))
// 注册UnsortedSegmentSumD操作的适配器描述kNameUnsortedSegmentProdD
// UnsortedSegmentMaxD
INPUT_MAP(UnsortedSegmentMaxD) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(segment_ids)}};
// 输入映射共两个x索引为1segment_ids索引为2
INPUT_ATTR_MAP(UnsortedSegmentMaxD) = {{3, ATTR_DESC(num_segments, AnyTraits<int64_t>())}};
// 输入属性映射num_segments类型是int64_t,索引是3
ATTR_MAP(UnsortedSegmentMaxD) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(UnsortedSegmentMaxD) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(UnsortedSegmentMaxD, kNameUnsortedSegmentMaxD, ADPT_DESC(UnsortedSegmentMaxD))
// 注册UnsortedSegmentMaxD操作的适配器描述kNameUnsortedSegmentMaxD
// UnsortedSegmentMin
INPUT_MAP(UnsortedSegmentMin) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(segment_ids)}, {3, INPUT_DESC(num_segments)}};
// 输入映射共三个x索引为1segment_ids索引为2num_segments索引为3
ATTR_MAP(UnsortedSegmentMin) = EMPTY_ATTR_MAP;
// 属性映射,空
OUTPUT_MAP(UnsortedSegmentMin) = {{0, OUTPUT_DESC(y)}};
// 输出映射y索引为0
REG_ADPT_DESC(UnsortedSegmentMin, prim::kPrimUnsortedSegmentMin->name(), ADPT_DESC(UnsortedSegmentMin))
// 注册UnsortedSegmentMin操作的适配器描述prim::kPrimUnsortedSegmentMin->name()
// ReverseV2
INPUT_MAP(ReverseV2D) = {{1, INPUT_DESC(x)}};
// 输入映射x索引为1
ATTR_MAP(ReverseV2D) = {{"axis", ATTR_DESC(axis, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())}};
//属性映射axis类型为int64_t和std::vector<int64_t>
OUTPUT_MAP(ReverseV2D) = {{0, OUTPUT_DESC(y)}};
//输出映射y索引为0
REG_ADPT_DESC(ReverseV2D, kNameReverseV2, ADPT_DESC(ReverseV2D))
// 注册ReverseV2D操作的适配器描述kNameReverseV2
} // namespace mindspore::transform

View File

@ -0,0 +1,94 @@
/**
* Copyright 2019-2021 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_declare/split_combination_ops_declare.h"
#include <vector>
namespace mindspore::transform {
// SplitD
INPUT_MAP(SplitD) = {{1, INPUT_DESC(x)}};
//输入映射将输入索引1映射为名为x的输入描述(INPUT_DESC)
ATTR_MAP(SplitD) = {{"axis", ATTR_DESC(split_dim, AnyTraits<int64_t>())},//指定维度
{"output_num", ATTR_DESC(num_split, AnyTraits<int64_t>())}};//指定输出数量
// 属性映射
DYN_OUTPUT_MAP(SplitD) = {{0, DYN_OUTPUT_DESC(y)}};
//动态输出映射 //将输出索引0映射为名为 "y" 的动态输出描述(DYN_OUTPUT_DESC)
REG_ADPT_DESC(SplitD, kNameSplitD, ADPT_DESC(SplitD))
//注册 "SplitD" 运算符的适配器描述(REG_ADPT_DESC),适配器描述中包含运算符名称 "kNameSplitD" 和适配器描述(ADPT_DESC)。
// 这将把 "SplitD" 运算符与其在框架中的实现关联起来。
//
// Pack
INPUT_MAP(Pack) = EMPTY_INPUT_MAP;
//定义 "Pack" 运算符的输入映射(INPUT_MAP)为空。这表示 "Pack" 运算符没有显式的输入,因此没有任何输入描述。
DYN_INPUT_MAP(Pack) = {{1, DYN_INPUT_DESC(x)}};
//定义 "Pack" 运算符的动态输入映射(DYN_INPUT_MAP)将输入索引1映射为名为 "x" 的动态输入描述(DYN_INPUT_DESC)
ATTR_MAP(Pack) = {{"num", ATTR_DESC(N, AnyTraits<int64_t>())}, {"axis", ATTR_DESC(axis, AnyTraits<int64_t>())}};
//定义 "Pack" 运算符的属性映射(ATTR_MAP) 两个属性:数量/维度
OUTPUT_MAP(Pack) = {{0, OUTPUT_DESC(y)}};//输出映射(OUTPUT_MAP)将输出索引0映射为名为 "y" 的输出描述(OUTPUT_DESC)
REG_ADPT_DESC(Pack, prim::kStack, ADPT_DESC(Pack))//注册 "Pack" 运算符的适配器描述(REG_ADPT_DESC)
// ParallelConcat
INPUT_MAP(ParallelConcat) = EMPTY_INPUT_MAP;
//定义 "ParallelConcat" 运算符的输入映射(INPUT_MAP)为空。
//这表示 "ParallelConcat" 运算符没有显式的输入,因此没有任何输入描述
DYN_INPUT_MAP(ParallelConcat) = {{1, DYN_INPUT_DESC(values)}};
//定义 "ParallelConcat" 运算符的动态输入映射(DYN_INPUT_MAP)将输入索引1映射为名为 "values" 的动态输入描述(DYN_INPUT_DESC)。
//这表示 "ParallelConcat" 运算符会接收一个动态数量的输入,而每个输入都可以使用 "values" 来标识
ATTR_MAP(ParallelConcat) = {//属性映射(ATTR_MAP),包含两个属性
{"shape", ATTR_DESC(shape, AnyTraits<std::vector<int64_t>>())},//连接操作时的形状
{"N", ATTR_DESC(N, AnyTraits<int64_t>())},//连接的数量
};
OUTPUT_MAP(ParallelConcat) = {{0, OUTPUT_DESC(output_data)}};
//输出映射(OUTPUT_MAP)
REG_ADPT_DESC(ParallelConcat, kNameParallelConcat, ADPT_DESC(ParallelConcat))
//注册 "ParallelConcat" 运算符的适配器描述(REG_ADPT_DESC)。
//适配器描述中包含运算符名称 "kNameParallelConcat" 和适配器描述(ADPT_DESC)。
//这将把 "ParallelConcat" 运算符与其在框架中的实现关联起来,并使用 "kNameParallelConcat" 作为标识来调用适配器。
// ConcatD
INPUT_MAP(ConcatD) = EMPTY_INPUT_MAP;
//定义 "ConcatD" 运算符的输入映射(INPUT_MAP)为空。
//这表示 "ConcatD" 运算符没有显式的输入,因此没有任何输入描述
DYN_INPUT_MAP(ConcatD) = {{1, DYN_INPUT_DESC(x)}};
//定义 "ConcatD" 运算符的动态输入映射(DYN_INPUT_MAP)将输入索引1映射为名为 "x" 的动态输入描述(DYN_INPUT_DESC)。
//这表示 "ConcatD" 运算符会接收一个动态数量的输入,而每个输入都可以使用 "x" 来标识。
ATTR_MAP(ConcatD) = {//属性映射
{"axis", ATTR_DESC(concat_dim, AnyTraits<int64_t>())},//连接操作时的维度
{"inputNums", ATTR_DESC(N, AnyTraits<int64_t>())},//输入数量
};
OUTPUT_MAP(ConcatD) = {{0, OUTPUT_DESC(y)}};
//定义 "ConcatD" 运算符的输出映射(OUTPUT_MAP)将输出索引0映射为名为 "y" 的输出描述(OUTPUT_DESC)。
//这表示 "ConcatD" 运算符会产生一个输出结果,并使用 "y" 来标识该输出。
REG_ADPT_DESC(ConcatD, prim::kPrimConcat->name(), ADPT_DESC(ConcatD))
//注册 "ConcatD" 运算符的适配器描述(REG_ADPT_DESC)。适配器描述中包含运算符名称 "prim::kPrimConcat->name()" 和适配器描述(ADPT_DESC)。
// 这将把 "ConcatD" 运算符与其在框架中的实现关联起来,并使用 "prim::kPrimConcat->name()" 作为标识来调用适配器。
//
// ConcatV2D Inference for tf
INPUT_MAP(ConcatV2D) = EMPTY_INPUT_MAP;//输入映射为空
DYN_INPUT_MAP(ConcatV2D) = {{1, DYN_INPUT_DESC(x)}};//动态输入映射,可以有多个数量的映射
ATTR_MAP(ConcatV2D) = {
{"axis", ATTR_DESC(concat_dim, AnyTraits<int64_t>())},//连接操作时的维度
{"N", ATTR_DESC(N, AnyTraits<int64_t>())},//连接的数量
};
OUTPUT_MAP(ConcatV2D) = {{0, OUTPUT_DESC(y)}};
//定义 "ConcatV2D" 运算符的输出映射(OUTPUT_MAP)将输出索引0映射为名为 "y" 的输出描述(OUTPUT_DESC)。
//这表示 "ConcatV2D" 运算符会产生一个输出结果,并使用 "y" 来标识该输出。
REG_ADPT_DESC(ConcatV2D, kNameConcatV2D, ADPT_DESC(ConcatV2D))
//注册 "ConcatV2D" 运算符的适配器描述(REG_ADPT_DESC)。适配器描述中包含运算符名称 "kNameConcatV2D" 和适配器描述(ADPT_DESC)。
//这将把 "ConcatV2D" 运算符与其在框架中的实现关联起来,并使用 "kNameConcatV2D" 作为标识来调用适配器。
} // namespace mindspore::transform

View File

@ -0,0 +1,25 @@
/**
* 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_declare/state_ops_declare.h"
//"Variable" 运算符通常用于表示模型中的变量(例如权重和偏置项)
namespace mindspore::transform {
// Variable
INPUT_MAP(Variable) = {{1, INPUT_DESC(x)}};
// 定义 "Variable" 运算符的输入映射(INPUT_MAP)将输入1映射为名为 "x" 的输入描述(INPUT_DESC)
ATTR_MAP(Variable) = EMPTY_ATTR_MAP;
// 定义 "Variable" 运算符的属性映射(ATTR_MAP),此处为空(EMPTY_ATTR_MAP)
} // namespace mindspore::transform

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,133 @@
/**
* Copyright 2019-2021 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_declare/transformation_ops_declare.h"
#include <vector>
namespace mindspore::transform {
// Flatten
// 将输入张量展平为一个1D张量
INPUT_MAP(Flatten) = {{1, INPUT_DESC(x)}};//输入映射Flatten有一个输入参数它的索引为1且该输入参数形参x
ATTR_MAP(Flatten) = EMPTY_ATTR_MAP;//属性映射,空,该操作不需要任何额外的属性参数
OUTPUT_MAP(Flatten) = {{0, OUTPUT_DESC(y)}};//输出映射Flatten有一个输出参数它的索引为0且该输入参数形参y
REG_ADPT_DESC(Flatten, prim::kPrimFlatten->name(), ADPT_DESC(Flatten))
// 通过调用"prim::kPrimFlatten"的name()函数来获取"Flatten"操作的名称 另一个先前定义的适配器描述。该描述告诉MindSpore如何在运行时执行"Flatten"操作。
//将操作 "Flatten"注册到适配器描述(REG_ADPT_DESC)中以便在MindSpore深度学习框架中能够使用该操作进行图计算
//适配器描述将此操作注册到名为 prim::kPrimFlatten->name() 的图操作
// Unpack
INPUT_MAP(Unpack) = {{1, INPUT_DESC(x)}};
ATTR_MAP(Unpack) = {{"axis", ATTR_DESC(axis, AnyTraits<int64_t>())}, {"num", ATTR_DESC(num, AnyTraits<int64_t>())}};
//具有两个属性 //axis表示拆分的轴 //num表示拆分后生成的张量数量
DYN_OUTPUT_MAP(Unpack) = {{0, DYN_OUTPUT_DESC(y)}};///动态输出参数 y表示可以输出多个张量。
REG_ADPT_DESC(Unpack, prim::kUnstack, ADPT_DESC(Unpack))
//适配器描述将此操作注册到名为 prim::kUnstack 的图操作
// ExtractImagePatches
INPUT_MAP(ExtractImagePatches) = {{1, INPUT_DESC(x)}};
//一个输入参数x
ATTR_MAP(ExtractImagePatches) = {
//具有四个属性
{"ksizes", ATTR_DESC(ksizes, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
//ksizes表示在输入数据的每个维度上滑动的窗口大小。
{"strides", ATTR_DESC(strides, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
//strides表示在输入数据的每个维度上滑动的步长。
{"rates", ATTR_DESC(rates, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())},
//rates表示在输入数据的每个维度上的dilation扩张
{"padding", ATTR_DESC(padding, AnyTraits<std::string>())}};
//padding表示在输入数据的周围添加的填充类型。
OUTPUT_MAP(ExtractImagePatches) = {{0, OUTPUT_DESC(y)}};
//一个输出参数y
REG_ADPT_DESC(ExtractImagePatches, kNameExtractImagePatches, ADPT_DESC(ExtractImagePatches))
//适配器描述将此操作注册到名为 kNameExtractImagePatches 的图操作
// Transpose
INPUT_MAP(TransposeD) = {{1, INPUT_DESC(x)}};
// 一个输入参数x
INPUT_ATTR_MAP(TransposeD) = {{2, ATTR_DESC(perm, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>())}};
//2是属性索引表示这是操作"TransposeD"的第二个输入属性
// perm:属性的名称 该属性的数据类型为int64_t 该属性是一个std::vector<int64_t>类型的值,即一维整数数组
ATTR_MAP(TransposeD) = EMPTY_ATTR_MAP;
// Do not set Transpose operator output descriptor
REG_ADPT_DESC(TransposeD, prim::kPrimTranspose->name(), ADPT_DESC(TransposeD))
// SpaceToDepth
INPUT_MAP(SpaceToDepth) = {{1, INPUT_DESC(x)}};
ATTR_MAP(SpaceToDepth) = {{"block_size", ATTR_DESC(block_size, AnyTraits<int64_t>())}};
//属性 block_size表示空间到深度转换的块大小
OUTPUT_MAP(SpaceToDepth) = {{0, OUTPUT_DESC(y)}};
REG_ADPT_DESC(SpaceToDepth, kNameSpaceToDepth, ADPT_DESC(SpaceToDepth))
// DepthToSpace
INPUT_MAP(DepthToSpace) = {{1, INPUT_DESC(x)}};
ATTR_MAP(DepthToSpace) = {{"block_size", ATTR_DESC(block_size, AnyTraits<int64_t>())}};
//属性 block_size表示深度到空间转换的块大小
OUTPUT_MAP(DepthToSpace) = {{0, OUTPUT_DESC(y)}};
//有一个输出参数 y
REG_ADPT_DESC(DepthToSpace, kNameDepthToSpace, ADPT_DESC(DepthToSpace))
//适配器描述将此操作注册到名为 kNameDepthToSpace 的图操作
//
// SpaceToBatchD
INPUT_MAP(SpaceToBatchD) = {{1, INPUT_DESC(x)}};
ATTR_MAP(SpaceToBatchD) = {
{"block_size", ATTR_DESC(block_size, AnyTraits<int64_t>())},
//block_size表示空间到批处理转换的块大小
{"paddings", ATTR_DESC(paddings, AnyTraits<std::vector<std::vector<int64_t>>>(), AnyTraits<std::vector<int64_t>>())}};
//paddings表示空间到批处理转换的填充方式
OUTPUT_MAP(SpaceToBatchD) = {{0, OUTPUT_DESC(y)}};
REG_ADPT_DESC(SpaceToBatchD, kNameSpaceToBatch, ADPT_DESC(SpaceToBatchD))
// SpaceToBatchNDD
INPUT_MAP(SpaceToBatchNDD) = {{1, INPUT_DESC(x)}};
ATTR_MAP(SpaceToBatchNDD) = {
{"block_shape", ATTR_DESC(block_shape, AnyTraits<std::vector<int64_t>>())},
//block_shape表示空间到批处理转换的块形状
{"paddings", ATTR_DESC(paddings, AnyTraits<std::vector<std::vector<int64_t>>>(), AnyTraits<std::vector<int64_t>>())}};
//paddings表示空间到批处理转换的填充方式
OUTPUT_MAP(SpaceToBatchNDD) = {{0, OUTPUT_DESC(y)}};
//有一个输出参数 y
REG_ADPT_DESC(SpaceToBatchNDD, kNameSpaceToBatchNDD, ADPT_DESC(SpaceToBatchNDD))
//适配器描述将此操作注册到名为 kNameSpaceToBatchNDD 的图操作
//
// BatchToSpaceD
INPUT_MAP(BatchToSpaceD) = {{1, INPUT_DESC(x)}};
//该操作接受一个输入参数 x
ATTR_MAP(BatchToSpaceD) = {
{"block_size", ATTR_DESC(block_size, AnyTraits<int64_t>())},
//block_size表示批处理到空间转换的块大小
{"crops", ATTR_DESC(crops, AnyTraits<std::vector<std::vector<int64_t>>>(), AnyTraits<std::vector<int64_t>>())}};
//crops表示批处理到空间转换的裁剪方式
OUTPUT_MAP(BatchToSpaceD) = {{0, OUTPUT_DESC(y)}};
// 有一个输出参数 y
REG_ADPT_DESC(BatchToSpaceD, kNameBatchToSpace, ADPT_DESC(BatchToSpaceD))
//适配器描述将此操作注册到名为 kNameBatchToSpace 的图操作
// BatchToSpaceNDD
INPUT_MAP(BatchToSpaceNDD) = {{1, INPUT_DESC(x)}};
//接受一个输入参数 x
ATTR_MAP(BatchToSpaceNDD) = {
{"block_shape", ATTR_DESC(block_shape, AnyTraits<std::vector<int64_t>>())},
//block_shape表示批处理到空间转换的块形状
{"crops", ATTR_DESC(crops, AnyTraits<std::vector<std::vector<int64_t>>>(), AnyTraits<std::vector<int64_t>>())}};
//crops表示批处理到空间转换的裁剪方式
OUTPUT_MAP(BatchToSpaceNDD) = {{0, OUTPUT_DESC(y)}};
//有一个输出参数 y
REG_ADPT_DESC(BatchToSpaceNDD, kNameBatchToSpaceNd, ADPT_DESC(BatchToSpaceNDD))
//适配器描述将此操作注册到名为 kNameBatchToSpaceNd 的图操作
} // namespace mindspore::transform
// 定义了一系列图操作,每个操作有不同的输入、输出和属性,
//并且将这些操作注册到相应的适配器描述中以便后续在MindSpore深度学习框架中使用这些操作进行图计算。

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,524 @@
/**
* 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 "include/transform/graph_ir/util.h"
#include <utility>
#include <map>
#include "securec/include/securec.h"
#include "include/common/utils/convert_utils.h"
#include "include/common/utils/utils.h"
namespace mindspore {
namespace transform {
using std::make_shared;
using std::shared_ptr;
using std::string;
using std::vector;
const size_t kErrorSize = 0;
//该函数主要用于生成一个包含相同 数据的 int64_tvector方便在一些情况下使用。
vector<int64_t> TransformUtil::ConvertIntToList(int64_t data, int size) {
vector<int64_t> list{}; //创建一个空的 类型的 vector<int64_t> list。
if (size <= 0) { //检查 size 是否小于等于 0
MS_LOG(WARNING) << "size <= 0"; //如果是,输出警告日志并返回空的 list。
return list;
}
for (int i = 0; i < size; ++i) { // 使用 for 循环将 data 复制 size 次并将每次复制的结果添加到list中。
list.push_back(data);
}
return list;//循环结束后返回存储有复制结果的list
}
static std::map<MeDataType, GeDataType> datatype_trans_map = {
{MeDataType::kNumberTypeFloat16, GeDataType::DT_FLOAT16}, {MeDataType::kNumberTypeFloat32, GeDataType::DT_FLOAT},
{MeDataType::kNumberTypeFloat64, GeDataType::DT_DOUBLE}, {MeDataType::kNumberTypeInt8, GeDataType::DT_INT8},
{MeDataType::kNumberTypeInt16, GeDataType::DT_INT16}, {MeDataType::kNumberTypeInt32, GeDataType::DT_INT32},
{MeDataType::kNumberTypeInt64, GeDataType::DT_INT64}, {MeDataType::kNumberTypeUInt8, GeDataType::DT_UINT8},
{MeDataType::kNumberTypeUInt16, GeDataType::DT_UINT16}, {MeDataType::kNumberTypeUInt32, GeDataType::DT_UINT32},
{MeDataType::kNumberTypeUInt64, GeDataType::DT_UINT64}, {MeDataType::kNumberTypeBool, GeDataType::DT_BOOL}};
// ConvertDataType 函数用于将 MeDataType 类型的数据转换为 GeDataType 类型。
GeDataType TransformUtil::ConvertDataType(const MeDataType &type) {
MS_LOG(DEBUG) << "Convert me data type: " << TypeIdLabel(type) << " to ge data type";
// 在 datatype_trans_map 中查找 MeDataType 对应的 GeDataType。
if (datatype_trans_map.find(type) != datatype_trans_map.end()) {
return datatype_trans_map[type];
} else { // 如果找不到对应的映射关系,则返回 GeDataType::DT_UNDEFINED。
return GeDataType::DT_UNDEFINED;
}
}
static std::map<MeDataType, size_t> datatype_size_map = {
{MeDataType::kNumberTypeFloat16, sizeof(float) / 2}, {MeDataType::kNumberTypeFloat32, sizeof(float)}, // 1/2 of float
{MeDataType::kNumberTypeFloat64, sizeof(double)}, {MeDataType::kNumberTypeInt8, sizeof(int8_t)},
{MeDataType::kNumberTypeInt16, sizeof(int16_t)}, {MeDataType::kNumberTypeInt32, sizeof(int32_t)},
{MeDataType::kNumberTypeInt64, sizeof(int64_t)}, {MeDataType::kNumberTypeUInt8, sizeof(uint8_t)},
{MeDataType::kNumberTypeUInt16, sizeof(uint16_t)}, {MeDataType::kNumberTypeUInt32, sizeof(uint32_t)},
{MeDataType::kNumberTypeUInt64, sizeof(uint64_t)}, {MeDataType::kNumberTypeBool, sizeof(bool)}};
// GetDataTypeSize 函数用于获取给定 MeDataType 类型数据在内存中占据的字节大小。
size_t TransformUtil::GetDataTypeSize(const MeDataType &type) {
if (datatype_size_map.find(type) != datatype_size_map.end()) { // 在 datatype_size_map 中查找 MeDataType 对应的字节大小。
return datatype_size_map[type];
} else { // 如果找不到对应的大小输出错误日志并返回一个特定的错误大小kErrorSize
MS_LOG(ERROR) << "Illegal tensor data type!";
return kErrorSize;
}
}
// ConvertFormat 函数用于将给定的字符串格式 `format` 转换为对应的 GeFormat 枚举类型。
GeFormat TransformUtil::ConvertFormat(const string &format) {
// 通过比较字符串格式 `format`,判断对应的 GeFormat 枚举类型,并进行转换并返回。
if (format == kOpFormat_NCHW) {
return GeFormat::FORMAT_NCHW;
} else if (format == kOpFormat_NDHWC) {
return GeFormat::FORMAT_NDHWC;
} else if (format == kOpFormat_NCDHW) {
return GeFormat::FORMAT_NCDHW;
} else if (format == kOpFormat_DHWNC) {
return GeFormat::FORMAT_DHWNC;
} else if (format == kOpFormat_DHWCN) {
return GeFormat::FORMAT_DHWCN;
} else if (format == kOpFormat_NC1HWC0) {
return GeFormat::FORMAT_NC1HWC0;
} else if (format == kOpFormat_NHWC) {
return GeFormat::FORMAT_NHWC;
} else if (format == kOpFormat_HWCN) {
return GeFormat::FORMAT_HWCN;
} else if (format == kOpFormat_ND) {
return GeFormat::FORMAT_ND;
} else { // 如果 `format` 不是支持的数据格式,输出错误日志并返回默认的 GeFormat::FORMAT_ND 格式。
MS_LOG(ERROR) << "Illegal tensor data format: (" << format << "). Use ND format instead.";
return GeFormat::FORMAT_ND;
}
}
static int64_t IntegerCastFunc(size_t temp) { return static_cast<int64_t>(temp); }
// GetGeTensorDesc 函数用于根据给定的 MeTensor 的形状ShapeVector、数据类型MeDataType和格式format
// 创建对应的 GeTensorDesc 对象,并返回一个指向该对象的 shared_ptr。
// GeTensorDesc 是 Ascend AI Core 引擎中定义的张量描述类,用于描述张量的形状、数据类型和数据格式。
std::shared_ptr<GeTensorDesc> TransformUtil::GetGeTensorDesc(const ShapeVector &me_shape, const MeDataType &me_type,
const std::string &format) {
// convert me shape to ge shape
// 将 MeTensor 的形状ShapeVector转换为 GeShape 对象std::vector<int64_t>
std::vector<int64_t> ge_shape;
if (me_shape.size() == 1) {
ge_shape.push_back(static_cast<int64_t>(me_shape[0]));
} else {
ge_shape.resize(me_shape.size());
(void)std::transform(me_shape.begin(), me_shape.end(), ge_shape.begin(), IntegerCastFunc);
}
GeShape shape(ge_shape);
if (shape.GetDimNum() == 0) { // 如果 GeShape 对象的维度数为 0则输出提示信息日志。
MS_LOG(INFO) << "The dims size of Ge tensor is zero";
}
// convert me format to ge format
// 将 MeTensor 的格式format转换为 GeFormat 枚举类型。
GeFormat ge_format = ConvertFormat(format);
if (ge_format == GeFormat::FORMAT_ND) {
MS_LOG(INFO) << "Set ND data format";
}
// convert me datatype to ge datatype
// 将 MeTensor 的数据类型me_type转换为 GeDataType 枚举类型。
GeDataType data_type = ConvertDataType(me_type);
if (data_type == GeDataType::DT_UNDEFINED) { // 如果数据类型转换失败,则输出错误日志,并返回空指针。
MS_LOG(ERROR) << "undefined data type :" << me_type;
return nullptr;
}
// 创建 GeTensorDesc 对象,并设置相应的形状、数据类型和数据格式信息。
auto desc = std::make_shared<GeTensorDesc>(shape, ge_format, data_type);
if (desc == nullptr) {
MS_LOG(ERROR) << "Create GeTensorDesc failed!";
return nullptr;
}
// 设置实际维度数量,即 GeTensorDesc 对象的形状维度数。
MS_LOG(INFO) << "SetRealDimCnt is :" << me_shape.size();
desc->SetRealDimCnt(SizeToInt(me_shape.size()));
return desc; // 返回指向创建的 GeTensorDesc 对象的 shared_ptr。
}
// if failed, return empty vector.
// ConvertInputTensors 函数用于将给定的 MeTensor 列表me_tensors转换为对应的 GeTensor 列表,并返回转换后的结果。
// MeTensor 是 MindSpore 引擎中定义的张量类,用于存储张量的数据和相关信息。
// GeTensor 是 Ascend AI Core 引擎中定义的张量类,用于存储张量的数据和相关信息。
// 函数遍历输入的 MeTensor 列表,对每个 MeTensor 进行转换,并将转换后的 GeTensor 添加到结果列表 ge_tensors 中。
// 如果在转换过程中遇到错误,则输出相应的错误日志,并返回空列表。
std::vector<GeTensorPtr> TransformUtil::ConvertInputTensors(const std::vector<MeTensorPtr> &me_tensors,
const std::string &format) {
std::vector<GeTensorPtr> ge_tensors;
// 遍历输入的 MeTensor 列表,对每个 MeTensor 进行转换,并将转换后的 GeTensor 添加到结果列表 ge_tensors 中。
for (size_t index = 0; index < me_tensors.size(); index++) {
MS_EXCEPTION_IF_NULL(me_tensors[index]);
// 输出当前 MeTensor 的数据大小、形状和数据类型信息。
MS_LOG(INFO) << "me_tensor " << index << " 's data size is: " << me_tensors[index]->DataSize();
auto shape = me_tensors[index]->shape();
std::string shape_str;
for (size_t i = 0; i < shape.size(); i++) {
shape_str += std::to_string(shape[i]);
shape_str += " ";
}
MS_LOG(INFO) << "me_tensor " << index << " 's shape is: { " << shape_str << "}";
MS_LOG(INFO) << "me_tensor " << index << " 's type is: " << me_tensors[index]->data_type();
// 调用 ConvertTensor 函数将当前的 MeTensor 转换为对应的 GeTensor。
auto ge_tensor_ptr = TransformUtil::ConvertTensor(me_tensors[index], format);
if (ge_tensor_ptr != nullptr) { // 如果转换成功,则将转换后的 GeTensor 添加到结果列表 ge_tensors 中。
ge_tensors.emplace_back(ge_tensor_ptr);
} else { // 如果转换过程中遇到错误,则输出相应的错误日志,并清空结果列表 ge_tensors并返回空列表。
MS_LOG(ERROR) << "Convert me_tensor " << index << " to Ge Tensor failed!";
ge_tensors.clear();
return ge_tensors;
}
}
return ge_tensors; // 返回转换后的 GeTensor 列表。
}
// ConvertTensor 函数用于将给定的 MeTensor`tensor`)转换为对应的 GeTensor并返回转换后的结果。
// MeTensor 是 MindSpore 引擎中定义的张量类,用于存储张量的数据和相关信息。
// GeTensor 是 Ascend AI Core 引擎中定义的张量类,用于存储张量的数据和相关信息。
GeTensorPtr TransformUtil::ConvertTensor(const MeTensorPtr &tensor, const std::string &format) {
// get tensor data type size
// 获取 MeTensor 的数据类型大小type_size即数据类型占用的字节数。
MS_EXCEPTION_IF_NULL(tensor);
size_t type_size = GetDataTypeSize(tensor->data_type());
if (type_size == kErrorSize) { // 如果数据类型大小获取失败,则输出错误日志,并返回空指针。
MS_LOG(ERROR) << "The Me Tensor data type size is wrong, type size is: " << type_size;
return nullptr;
}
// 获取 MeTensor 的元素数量和数据缓冲区大小data_buff_size
size_t elements_num = IntToSize(tensor->ElementsNum());
// get tensor buff size
size_t data_buff_size = elements_num * type_size;
if (data_buff_size == 0) { // 如果数据缓冲区大小为 0则输出提示信息日志。
MS_LOG(INFO) << "The Me Tensor data buff size is 0.";
}
// create ge tensor
// 创建 GeTensorDesc 对象,并根据 MeTensor 的形状、数据类型和数据格式信息创建对应的 GeTensor 对象。
auto desc = GetGeTensorDesc(tensor->shape_c(), tensor->data_type(), format);
if (desc == nullptr) { // 如果创建 GeTensorDesc 对象失败,则输出错误日志,并返回空指针。
MS_LOG(ERROR) << "Failed to get Tensor Desc";
return nullptr;
}
// 创建 GeTensor 对象,并设置相应的数据缓冲区、形状、数据类型等信息。
GeTensorPtr tensor_ptr = make_shared<GeTensor>(*desc, static_cast<uint8_t *>(tensor->data_c()), data_buff_size);
if (tensor_ptr != nullptr) { // 如果创建 GeTensor 对象成功,则输出转换成功的提示信息,并返回指向创建的 GeTensor 对象的 shared_ptr。
MS_LOG(INFO) << "Convert Me Tensor to Ge Tensor success!";
}
return tensor_ptr;
}
// ConvertGeTensors 函数用于将给定的 GeTensor`ge_tensors`)向量转换为对应的 MeTensorMindSpore
// 引擎中的张量)向量,并返回转换后的结果。 `ge_tensors` 是 Ascend AI Core 引擎中的张量向量,用于存储计算结果的张量。
// `request_dims` 是一个与 `ge_tensors` 同样大小的向量,用于指定转换后的 MeTensor 的形状ShapeVector
std::vector<MeTensorPtr> TransformUtil::ConvertGeTensors(const std::vector<GeTensorPtr> &ge_tensors,
const std::vector<ShapeVector> &request_dims) {
std::vector<MeTensorPtr> outputs;
// 遍历 `ge_tensors` 向量中的每个 GeTensor将其转换为对应的 MeTensor 对象
for (size_t index = 0; index < ge_tensors.size(); index++) {
MeTensorPtr me_tensor_ptr = nullptr;
// 根据索引值 `index` 来获取对应的请求形状(`request_dims`)。
if (index < request_dims.size()) {
me_tensor_ptr = ConvertGeTensor(ge_tensors[index], request_dims[index]);
} else { // 如果请求形状的向量长度小于当前索引 `index`,则使用空的形状向量来进行转换。
ShapeVector empty_shape;
me_tensor_ptr = ConvertGeTensor(ge_tensors[index], empty_shape);
}
if (me_tensor_ptr != nullptr) { // 如果转换成功,则将转换后的 MeTensor 存储在输出向量 `outputs` 中。
outputs.emplace_back(me_tensor_ptr);
} else { // 如果转换失败,则输出相应的错误日志,并返回已经成功转换的 MeTensor 向量 `outputs`。
MS_LOG(ERROR) << "Convert Ge Tensor " << index << " to Me Tensor failed!";
return outputs;
}
}
return outputs; // 返回转换后的 MeTensor 向量 `outputs`。
}
// ConvertGeTensors 函数用于将给定的 GeTensor`ge_tensors`)向量转换为对应的 MeTensorMindSpore 引擎中的张量)向量,并返回转换后的结果。
//`ge_tensors` 是 Ascend AI Core 引擎中的张量向量,用于存储计算结果的张量。
std::vector<MeTensorPtr> TransformUtil::ConvertGeTensors(const std::vector<GeTensorPtr> &ge_tensors) {
std::vector<MeTensorPtr> outputs;
// 遍历 `ge_tensors` 向量中的每个 GeTensor将其转换为对应的 MeTensor 对象。
for (size_t index = 0; index < ge_tensors.size(); index++) {
MeTensorPtr me_tensor_ptr = ConvertGeTensor(ge_tensors[index]);
if (me_tensor_ptr != nullptr) { // 如果转换成功,则将转换后的 MeTensor 存储在输出向量 `outputs` 中。
outputs.emplace_back(me_tensor_ptr);
} else { // 如果转换失败,则输出相应的错误日志,并返回已经成功转换的 MeTensor 向量 `outputs`。
MS_LOG(ERROR) << "Convert Ge Tensor " << index << " to Me Tensor failed!";
return outputs;
}
}
return outputs; // 返回转换后的 MeTensor 向量 `outputs`。
}
// ConvertGeDataType 函数用于将给定的 GeDataTypeAscend AI Core 引擎中的数据类型)转换为对应的 MeDataTypeMindSpore引擎中的数据类型
//`type` 是 Ascend AI Core 引擎中的数据类型,需要被转换为对应的 MeDataType。
MeDataType TransformUtil::ConvertGeDataType(const GeDataType &type) {
switch (type) { // 对于不同的 GeDataType 值,根据其对应的数据类型进行转换。
case GeDataType::DT_FLOAT16:
return MeDataType::kNumberTypeFloat16;
case GeDataType::DT_FLOAT:
return MeDataType::kNumberTypeFloat32;
case GeDataType::DT_DOUBLE:
return MeDataType::kNumberTypeFloat64;
case GeDataType::DT_INT64:
return MeDataType::kNumberTypeInt64;
case GeDataType::DT_INT32:
return MeDataType::kNumberTypeInt32;
case GeDataType::DT_INT16:
return MeDataType::kNumberTypeInt16;
case GeDataType::DT_INT8:
return MeDataType::kNumberTypeInt8;
case GeDataType::DT_BOOL:
return MeDataType::kNumberTypeBool;
case GeDataType::DT_UINT8:
return MeDataType::kNumberTypeUInt8;
case GeDataType::DT_UINT16:
return MeDataType::kNumberTypeUInt16;
case GeDataType::DT_UINT32:
return MeDataType::kNumberTypeUInt32;
case GeDataType::DT_UINT64:
return MeDataType::kNumberTypeUInt64;
// 对于其他未列出的 GeDataType 值,或者无法转换的值,返回 MeDataType::kTypeUnknown表示未知数据类型。
case GeDataType::DT_UNDEFINED:
case GeDataType::DT_DUAL_SUB_UINT8:
case GeDataType::DT_DUAL_SUB_INT8:
case GeDataType::DT_DUAL:
return MeDataType::kTypeUnknown;
default:
return MeDataType::kTypeUnknown;
}
}
namespace {
// IsGeShapeCompatible 函数用于检查给定的 GeTensor 的形状 `ge_shape` 是否与请求的形状 `request_dims` 兼容。
// `ge_shape` 是 GeTensor 的形状,`request_dims` 是请求的形状。
bool IsGeShapeCompatible(const GeShape &ge_shape, const ShapeVector &request_dims) {
MS_LOG(INFO) << "GeTensor's shape is " << TransformUtil::PrintVector(ge_shape.GetDims());
MS_LOG(INFO) << "Me request shape is " << TransformUtil::PrintVector(request_dims);
const int GE_DIMS = 4;
std::vector<int64_t> ge_dims = ge_shape.GetDims();
if (request_dims.size() > ge_dims.size()) { // 如果请求的维度数量大于 GeTensor 的维度数量,说明形状不兼容,返回 false。
MS_LOG(ERROR) << "Request shape's dims count greater than ge shape's";
return false;
}
// convert NHWC to NCHW
// 如果请求的维度数量等于 1且 GeTensor 的维度数量等于 4且对应维度值满足 NHWC 到 NCHW 的转换条件,返回兼容。
if ((request_dims.size() == 1) && (ge_dims.size() == GE_DIMS) && (request_dims[0] == ge_dims[1]) &&
(ge_dims[0] == 1) && (ge_dims[2] == 1) && (ge_dims[3] == 1)) {
MS_LOG(INFO) << "Ge tensor shape and request shape is compatible";
return true;
}
std::string::size_type i = 0;
// 逐一比较 `request_dims` 和 `ge_shape` 的维度值,如果任何维度值不相等,说明形状不兼容,返回 false。
for (; i < request_dims.size(); i++) {
if (ge_dims[i] != request_dims[i]) {
MS_LOG(ERROR) << "Request shape's dims value not equal to ge shape's";
return false;
}
}
// 对于 `request_dims` 中已比较的维度后的未提供的维度,要求其在 `ge_shape` 中对应的维度值为1否则说明形状不兼容返回 false。
for (; i < ge_dims.size(); i++) {
if (ge_dims[i] != 1) {
MS_LOG(ERROR) << "GeShape's extend dims is not equal to 1";
return false;
}
}
// 形状兼容,返回 true。
MS_LOG(INFO) << "Ge tensor shape and request shape is compatible";
return true;
}
} // namespace
// ConvertMeShape 函数用于将 MeTensor 的形状表示转换为 GeTensor 的形状表示。
GeShape TransformUtil::ConvertMeShape(const ShapeVector &me_dims) {
std::vector<int64_t> ge_dims;
//将 `me_dims` 中的维度值拷贝到一个新的 vector `ge_dims` 中,并使用这个新的 vector 创建一个 GeShape 对象
(void)std::copy(me_dims.begin(), me_dims.end(), std::back_inserter(ge_dims));
return GeShape(ge_dims); //返回 GeShape 对象,表示 MeTensor 形状转换为 GeTensor 形状的结果。
}
// ConvertGeShape 函数用于将 GeTensor 的形状表示转换为 MeTensor 的形状表示。
ShapeVector TransformUtil::ConvertGeShape(const GeShape &ge_shape) {
//将 GeShape 对象中的维度值拷贝到一个新的 ShapeVector `me_dims` 中,并使用这个新的 ShapeVector 表示 MeTensor
ShapeVector me_dims;
std::vector<int64_t> ge_dims = ge_shape.GetDims();
(void)std::copy(ge_dims.begin(), ge_dims.end(), std::back_inserter(me_dims));
return me_dims; //返回 `me_dims`,表示 GeTensor 形状转换为 MeTensor 形状的结果
}
// ConvertGeShape 函数用于将 GeTensor 的形状表示转换为 MeTensor 的形状表示。
// 参数 `ge_shape` 是 GeTensor 的形状,以 GeShape 对象表示。
// 参数 `request_dims` 是 MeTensor 请求的形状,以 ShapeVector 表示。
ShapeVector TransformUtil::ConvertGeShape(const GeShape &ge_shape, const ShapeVector &request_dims) {
vector<int64_t> ret;
if (ge_shape.GetDimNum() == 0) {
MS_LOG(DEBUG) << "GeTensor's shape is scalar";
return ret;
}
if (IsGeShapeCompatible(ge_shape, request_dims) == true) { //比较 GeShape 和 MeTensor 请求形状是否兼容
ret = request_dims; //如果兼容则返回 MeTensor 请求形状 `request_dims`
} else { //否则返回 GeTensor 形状转换后的 MeTensor 形状 `ret`
MS_LOG(ERROR) << "GeShape and Me request shape are incompatible, return GeShape";
ret = ConvertGeShape(ge_shape);
}
return ret;
}
// GenerateMeTensor 函数用于根据给定的 GeTensor 对象 `ge_tensor`,生成相应的 MeTensor 对象并将其形状和数据复制到MeTensor 中。
// 参数 `ge_tensor` 是给定的 GeTensor 对象,表示待转换的 GeTensor。
// 参数 `me_dims` 是 MeTensor 的形状以ShapeVector 表示。
// 参数 `me_type` 是 MeTensor 的数据类型,以 TypeId 表示。
MeTensorPtr TransformUtil::GenerateMeTensor(const GeTensorPtr &ge_tensor, const ShapeVector &me_dims,
const TypeId &me_type) {
MeTensor me_tensor(me_type, me_dims);
// Get the writable data pointer of the tensor and cast it to its data type
// 获取 MeTensor 的可写数据指针,并将其转换为指定的数据类型
auto me_data_ptr = reinterpret_cast<uint8_t *>(me_tensor.data_c());
size_t me_data_size = static_cast<size_t>(me_tensor.data().nbytes());
MS_EXCEPTION_IF_NULL(me_data_ptr);
MS_EXCEPTION_IF_NULL(ge_tensor);
if (me_data_size < ge_tensor->GetSize()) {
MS_LOG(ERROR) << "ME tensor data size[" << me_data_size << " bytes] is less than GE tensor ["
<< ge_tensor->GetSize() << " bytes]";
return nullptr;
}
// Copy or use the writable data pointer of the ME tensor
// 复制或使用 MeTensor 的可写数据指针
MS_EXCEPTION_IF_NULL(ge_tensor->GetData());
if (ge_tensor->GetSize() == 0) {
MS_LOG(ERROR) << "GE tensor data size is zero!";
return nullptr;
}
// Use memcpy here, not memcpy_s, just because the size of ge_tensor may be bigger than 2GB
// which is the size limit of memcpy_s
// 使用 memcpy 进行数据拷贝,而不使用 memcpy_s这是因为 ge_tensor 的大小可能大于 2GB
// 而 memcpy_s 有 2GB 的大小限制。
(void)memcpy(me_data_ptr, ge_tensor->GetData(), ge_tensor->GetSize());
return make_shared<MeTensor>(me_tensor);
}
// ConvertGeTensor 函数用于将给定的 GeTensor 对象 `ge_tensor` 转换为相应的 MeTensor 对象。
// 参数 `ge_tensor` 是给定的 GeTensor 对象,表示待转换的 GeTensor。
MeTensorPtr TransformUtil::ConvertGeTensor(const GeTensorPtr &ge_tensor) {
MS_EXCEPTION_IF_NULL(ge_tensor);
// 获取 GeTensor 的形状,并将其转换为 MeTensor 的形状
GeShape ge_shape = ge_tensor->GetTensorDesc().GetShape();
vector<int64_t> me_dims = ConvertGeShape(ge_shape);
// 获取 GeTensor 的数据类型,并将其转换为 MeTensor 的数据类型
TypeId type_id = ConvertGeDataType(ge_tensor->GetTensorDesc().GetDataType());
if (type_id == MeDataType::kTypeUnknown) {
MS_LOG(ERROR) << "Could not convert Ge Tensor because of unsupported data type: "
<< static_cast<int>(ge_tensor->GetTensorDesc().GetDataType());
return nullptr;
}
// 调用 GenerateMeTensor 函数,根据转换后的 MeTensor 形状和数据类型,生成相应的 MeTensor 对象
return GenerateMeTensor(ge_tensor, me_dims, type_id);
}
// if request_dims is empty, use ge tensor's shape,otherwise convert to request shape
// ConvertGeTensor 函数用于将给定的 GeTensor 对象 `ge_tensor` 转换为相应的 MeTensor 对象,并根据给定的 MeTensor 形状 `request_dims` 进行转换。
// 参数 `ge_tensor` 是给定的 GeTensor 对象,表示待转换的 GeTensor。
// 参数 `request_dims` 是要求的 MeTensor 形状,用于与 GeTensor 的形状进行兼容性检查和转换。
MeTensorPtr TransformUtil::ConvertGeTensor(const GeTensorPtr ge_tensor, const ShapeVector &request_dims) {
MS_EXCEPTION_IF_NULL(ge_tensor);
// 获取 GeTensor 的形状,并将其与给定的 MeTensor 形状 `request_dims` 进行兼容性检查和转换
GeShape ge_shape = ge_tensor->GetTensorDesc().GetShape();
vector<int64_t> me_dims = ConvertGeShape(ge_shape, request_dims);
// 输出 GeTensor 的数据类型
MS_LOG(INFO) << "GE tensor type is " << static_cast<int>(ge_tensor->GetTensorDesc().GetDataType());
// Create a tensor with wanted data type and shape
// 创建具有指定数据类型和形状的 MeTensor 对象
TypeId type_id = ConvertGeDataType(ge_tensor->GetTensorDesc().GetDataType());
if (type_id == MeDataType::kTypeUnknown) {
MS_LOG(ERROR) << "Could not convert Ge Tensor because of unsupported data type: "
<< static_cast<int>(ge_tensor->GetTensorDesc().GetDataType());
return nullptr; //如果转换失败,则返回 nullptr
}
return GenerateMeTensor(ge_tensor, me_dims, type_id); //返回其指针,表示转换成功
}
//PrintGeTensor 函数用于打印给定的 GeTensor 对象的数据内容
std::string TransformUtil::PrintGeTensor(const GeTensorPtr ge_tensor) {
std::string ret;
if (ge_tensor == nullptr) { //检查输入的 ge_tensor 是否为空
MS_LOG(ERROR) << "Input ge tensor is nullptr"; //如果为空,则输出错误日志并返回空字符串
return ret;
}
//获取了ge_tensor 的数据类型,并根据数据类型使用 MakeVector 函数将 ge_tensor 的数据内容转换成相应的向量
//根据数据类型的不同,函数将数据内容转换成不同类型的向量,包括 uint32_t、float_t、int32_t、double_t、int64_t、uint64_t、int16_t、uint16_t、int8_t 和 uint8_t。
//使用 PrintVector 函数将转换后的向量打印成字符串,并返回该字符串
MS_LOG(INFO) << "Ge Tensor data type is : " << static_cast<int>(ge_tensor->GetTensorDesc().GetDataType());
switch (static_cast<int>(ge_tensor->GetTensorDesc().GetDataType())) {
case GeDataType::DT_UINT32:
ret = PrintVector(MakeVector<uint32_t>(ge_tensor->GetData(), ge_tensor->GetSize()));
break;
case GeDataType::DT_FLOAT:
ret = PrintVector(MakeVector<float_t>(ge_tensor->GetData(), ge_tensor->GetSize()));
break;
case GeDataType::DT_INT32:
ret = PrintVector(MakeVector<int32_t>(ge_tensor->GetData(), ge_tensor->GetSize()));
break;
case GeDataType::DT_DOUBLE:
ret = PrintVector(MakeVector<double_t>(ge_tensor->GetData(), ge_tensor->GetSize()));
break;
case GeDataType::DT_INT64:
ret = PrintVector(MakeVector<int64_t>(ge_tensor->GetData(), ge_tensor->GetSize()));
break;
case GeDataType::DT_UINT64:
ret = PrintVector(MakeVector<uint64_t>(ge_tensor->GetData(), ge_tensor->GetSize()));
break;
case GeDataType::DT_INT16:
ret = PrintVector(MakeVector<int16_t>(ge_tensor->GetData(), ge_tensor->GetSize()));
break;
case GeDataType::DT_UINT16:
ret = PrintVector(MakeVector<uint16_t>(ge_tensor->GetData(), ge_tensor->GetSize()));
break;
case GeDataType::DT_DUAL_SUB_INT8:
case GeDataType::DT_INT8:
ret = PrintVector(MakeVector<int8_t>(ge_tensor->GetData(), ge_tensor->GetSize()));
break;
case GeDataType::DT_UINT8:
case GeDataType::DT_DUAL_SUB_UINT8:
ret = PrintVector(MakeVector<uint8_t>(ge_tensor->GetData(), ge_tensor->GetSize()));
break;
case GeDataType::DT_FLOAT16:
case GeDataType::DT_BOOL:
case GeDataType::DT_UNDEFINED:
case GeDataType::DT_DUAL:
//如果给定的 ge_tensor 的数据类型不在上述支持的类型列表中(如 DT_FLOAT16、DT_BOOL、DT_UNDEFINED 和 DT_DUAL则输出错误日志并返回空字符串。
default:
MS_LOG(ERROR) << "Unsupported to print type:" << static_cast<int>(ge_tensor->GetTensorDesc().GetDataType())
<< " ge tensor";
break;
}
return ret;
}
} // namespace transform
} // namespace mindspore