Compare commits
72 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
5b717dbe1e | |
|
|
33c6ac4c6d | |
|
|
d77a6bc0e3 | |
|
|
8d00177b9e | |
|
|
fc4387a315 | |
|
|
fef5b1745f | |
|
|
5b1b14448a | |
|
|
2bebfc7849 | |
|
|
545d5b255f | |
|
|
073f1dedcb | |
|
|
f0e49149b4 | |
|
|
6eef24c510 | |
|
|
47db2ab436 | |
|
|
cd77c72c71 | |
|
|
645e43f2f3 | |
|
|
4ce7ba9637 | |
|
|
dbf45f752c | |
|
|
6bd5d6b028 | |
|
|
b4da936e0a | |
|
|
a55500e409 | |
|
|
dac5730b96 | |
|
|
d39a15cd04 | |
|
|
7c5ab75646 | |
|
|
5a17ea7fe9 | |
|
|
febf01acae | |
|
|
5ee8a81a10 | |
|
|
6c819f6c8d | |
|
|
1b84efbfa2 | |
|
|
ce3dc76a69 | |
|
|
54b288a0f5 | |
|
|
3c42e42e9b | |
|
|
88f8baa480 | |
|
|
f0490dd62e | |
|
|
5eba83c33b | |
|
|
2375e97925 | |
|
|
e6fcc172e1 | |
|
|
419206d9e4 | |
|
|
d8913ceb95 | |
|
|
5047cc9701 | |
|
|
2ace1c5911 | |
|
|
d076ece04e | |
|
|
dcfd6500ea | |
|
|
1092a7e133 | |
|
|
89b0165779 | |
|
|
3ac8b24aaf | |
|
|
0a94cddbc5 | |
|
|
2d2707971c | |
|
|
821dc204d7 | |
|
|
eaaecac92c | |
|
|
ea93d3ff40 | |
|
|
49e7505fe6 | |
|
|
9278c58e1d | |
|
|
26de068866 | |
|
|
cda2b4cfef | |
|
|
3caf864d7e | |
|
|
03afa7be68 | |
|
|
2b388dfe74 | |
|
|
55894bcb49 | |
|
|
b0736de2be | |
|
|
3488782107 | |
|
|
9d4bc71b5f | |
|
|
067065579d | |
|
|
a5c9cf55a0 | |
|
|
f5f8630135 | |
|
|
21ab5fcd03 | |
|
|
5324ac9b68 | |
|
|
43016e4088 | |
|
|
3097502ab4 | |
|
|
c72e8fc76e | |
|
|
eb49fab889 | |
|
|
70cf9f455f | |
|
|
1a3ddc10db |
Binary file not shown.
Binary file not shown.
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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索引为1,sharp索引为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索引为1,paddings索引为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索引为1,paddings索引为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索引为1,axis索引为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索引为1,seq_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索引为1,hypothesis_values索引为2,hypothesis_shape索引为3,
|
||||
// truth_indices索引为4,truth_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索引为0,index索引为1,count索引为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索引为1,index索引为2,count索引为3
|
||||
ATTR_MAP(NonZeroWithValueShape) = EMPTY_ATTR_MAP;
|
||||
//属性映射,设为空
|
||||
OUTPUT_MAP(NonZeroWithValueShape) = {{0, OUTPUT_DESC(out_value)}, {1, OUTPUT_DESC(out_index)}};
|
||||
//输出映射,out_value索引为0,out_index索引为1,out_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
|
||||
|
|
@ -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
|
||||
|
||||
#该函数用于使用标准的SVD(Singular 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
|
||||
|
|
@ -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 Normalization(LessBN)功能
|
||||
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 Normalization(LessBN)功能
|
||||
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
|
||||
}
|
||||
|
|
@ -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)
|
||||
# 检查是否启用 Adasum(All-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
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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索引为1,y索引为2,sum_square_y索引为3,sum_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索引为0,segment_count索引为1,kmean_total_sum索引为2
|
||||
REG_ADPT_DESC(KMeansCentroids, prim::kPrimKMeansCentroids->name(), ADPT_DESC(KMeansCentroids))
|
||||
//注册KMeansCentroids操作的适配器描述kPrimKMeansCentroids预设的name变量
|
||||
} // namespace mindspore::transform
|
||||
|
|
@ -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可能来自env“CUDA_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
|
||||
|
||||
# 默认情况下禁用 NUMA(Non-Uniform Memory Access)支持
|
||||
numa_enable = False
|
||||
|
||||
# 从环境变量中获取 NUMA_ENABLE(DATASET_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 设置为设备的 ID(device_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()
|
||||
|
|
@ -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索引为0,value_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索引为1,pred索引为2
|
||||
OUTPUT_MAP(Switch) = {{0, OUTPUT_DESC(output_false)}, {1, OUTPUT_DESC(output_true)}};
|
||||
//输出映射,output_false索引为0,output_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
|
|
@ -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索引为1,labels_indices索引为2,labels_values索引为3,sequence_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索引为0,gradient索引为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索引为1,sequence_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索引为0,decoded_values索引为1,decoded_shape索引为2,log_probability索引为1
|
||||
REG_ADPT_DESC(CTCGreedyDecoder, kNameCTCGreedyDecoder, ADPT_DESC(CTCGreedyDecoder))
|
||||
//注册CTCGreedyDecoder操作的适配器描述KNameCTCGreedyDecoder
|
||||
} // namespace mindspore::transform
|
||||
|
|
@ -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索引为0,flow索引为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索引为1,index索引为2,value索引为3,flow_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索引为1,indices索引为2,flow_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
|
|
@ -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 数据类型映射到 CDE(MindSpore 数据增强库)的数据类型
|
||||
# 这个字典用于将 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 数据类型映射到 CDE(MindSpore 数据增强库)的数据类型
|
||||
# 这个字典用于将 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
|
||||
|
||||
|
|
@ -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 图形
|
||||
}
|
||||
|
||||
// 该函数用于设置与图形管理器关联的 GE(GraphEngine)会话指针。
|
||||
// 参数 '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 会话指针
|
||||
}
|
||||
|
||||
// 该函数用于获取图形管理器关联的 GE(GraphEngine)会话指针。
|
||||
// 返回类型为 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 会话指针
|
||||
}
|
||||
|
||||
// 该函数用于删除图形管理器关联的 GE(GraphEngine)会话,并清除与该会话相关的数据。
|
||||
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
|
||||
|
|
@ -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
|
||||
|
|
@ -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)): #遍历AST(Abstract 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的接口方法。
|
||||
#这个方法接受一个AST(Abstract 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根节点
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 是否为 LARS(Layer-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的类型不是None、tuple、list或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的维度是否为1,dtype是否为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
|
||||
|
|
@ -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 {
|
||||
// 该函数用于构建 MDDataset(MindSpore Dataset)的图形(Graph)。
|
||||
DfGraphPtr BuildMDDatasetGraph(const DatasetGraphParam ¶m) {
|
||||
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 ¶m, 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
|
||||
|
|
@ -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}")
|
||||
|
|
@ -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 {
|
||||
// 该函数用于创建新的 GE(GraphEngine)会话。
|
||||
// 参数 '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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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索引为1,size索引为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索引为1,size索引为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索引为1,original_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索引为1,size索引为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索引为1,boxes索引为2,box_index索引为3,crop_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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 Normalization(BN)以提高网络性能并保持网络准确性。
|
||||
|
||||
# 定义一个名为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 Normalization(BN)以提高网络性能并保持准确性
|
||||
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)
|
||||
|
|
@ -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
|
||||
|
|
@ -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索引为1,clamp_min索引为2,clamp_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索引为0,clamp_min_mask索引为1,clamp_max_mask索引为2,x_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索引为1,clamp_min_mask索引为2,clamp_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索引为1,clamp_max_mask索引为2,x_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索引为1,clamp__min_mask索引为2,x_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索引为1,range)索引为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索引为1,data_min索引为2,data_max索引为3,cumsum索引为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索引为0,offset索引为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索引为1,target索引为2,weight索引为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索引为0,total_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索引为1,y_grad索引为2,target索引为3,weight索引为4,total_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索引为1,w_min索引为2,w_max索引为3
|
||||
ATTR_MAP(WtsARQ) = {{"num_bits", ATTR_DESC(num_bits, AnyTraits<int64_t>())},
|
||||
{"offset_flag", ATTR_DESC(offset_flag, AnyTraits<bool>())}};
|
||||
//输入映射,num_bits索引为1,offset_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
|
||||
|
|
@ -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
|
|
@ -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索引为1,scale索引为2,offset索引为3,mean索引为4,variance索引为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索引为0,batch_mean索引为1,batch_variance索引为2,reserve_space_1索引为3,reserve_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索引为1,mean索引为2,variance索引为3,momentum索引为4,scale索引为5,offset索引为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索引为1,x索引为2,scale索引为3,reserve_space_1索引为4,reserve_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索引为0,scale_backprop索引为1,offset_backprop索引为2,reserve_space_4索引为3,reserve_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索引为1,y索引为2,dy索引为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
|
||||
|
|
@ -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索引为1,filter索引为2,bias索引为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索引为1,filter索引为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索引为1,filter索引为2,out_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索引为1,filter索引为2,bias索引为3,offset_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索引为1,filter索引为2,bias索引为3,offset_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索引为1,x索引为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索引为1,filter索引为2,bias索引为3,offset_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索引为1,filter索引为2,bias索引为3,offset_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索引为1,filter索引为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索引为1,filter索引为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索引为1,filter索引为2,bias索引为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索引为2,out_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索引为1,out_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
|
||||
|
|
@ -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索引为1,ground_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索引为1,deltas索引为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索引为1,gtboxes索引为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索引为1,img_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索引为0,y2索引为1
|
||||
REG_ADPT_DESC(Sort, kNameSort, ADPT_DESC(Sort))
|
||||
//注册Sort操作的适配器描述KNameSort
|
||||
|
||||
// ROIAlign
|
||||
INPUT_MAP(ROIAlign) = {{1, INPUT_DESC(features)}, {2, INPUT_DESC(rois)}};
|
||||
//输入映射,features索引为1,rois索引为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索引为1,rois索引为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
|
||||
|
|
@ -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索引为1,grad_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索引为1,labels索引为2
|
||||
ATTR_MAP(SoftmaxCrossEntropyWithLogits) = EMPTY_ATTR_MAP;
|
||||
//属性映射,设为空
|
||||
OUTPUT_MAP(SoftmaxCrossEntropyWithLogits) = {{0, OUTPUT_DESC(loss)}, {1, OUTPUT_DESC(backprop)}};
|
||||
//输出映射,loss索引为0,backprop索引为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索引为1,labels索引为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索引为1,labels索引为2,dout索引为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索引为1,labels索引为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索引为1,target索引为2,dout索引为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索引为1,target索引为2,weight索引为3,pos_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索引为1,grad索引为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索引为1,gamma索引为2,beta索引为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索引为0,mean索引为1,variance索引为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索引为1,dy索引为2,variance索引为3,mean索引为4,gamma索引为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索引为0,pd_gamma索引为1,pd_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索引为1,x索引为2,y索引为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索引为1,mask索引为2,keep_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索引为1,y索引为2,weight索引为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索引为1,y索引为2,grad_output索引为3,weight索引为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索引为1,scale索引为2,bias索引为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索引为1,input索引为2,target索引为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
|
||||
|
|
@ -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的索引为1,orig_y的索引为2,grads索引为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的索引为1,orig_y的索引为2,grads索引为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的索引为1,orig_y的索引为2,grads索引为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的索引为1,orig_y的索引为2,grads索引为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的索引为1,input_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索引为0,argmax索引为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的索引为1,grad的索引为2,argmax索引为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的索引为1,grad的索引为2,argmax索引为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
|
||||
|
|
@ -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索引为2,lr索引为3,grad索引为4,momentum索引为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索引为1,g索引为2,w_square_sum索引为3,g_square_sum索引为4,weight_decay索引为5,learning_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索引为1,m索引为2,v索引为3,beta1_power索引为4,beta2_power索引为5,lr索引为6
|
||||
// betal索引为7,beta2索引为8,epsilon索引为9,grad索引为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索引为1,m索引为2,v索引为3,beta1_power索引为4,beta2_power索引为5,lr索引为6
|
||||
// betal索引为7,beta2索引为8,epsilon索引为9,grad索引为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的索引为0,m索引为1,v索引为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索引为1,accum索引为2,lr索引为3,grad索引为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的索引为0,accum索引为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索引为1,accum索引为2,lr索引为3,grad索引为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的索引为0,accum索引为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索引为1,m索引为2,lr索引为3,alpha索引为4,sign_decay索引为5,beta索引为6,grad索引为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的索引为0,m索引为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索引为1,accum索引为2,grad索引为3,indices索引为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的索引为0,accum索引为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索引为1,accum索引为2,accum_update索引为3,lr索引为4,rho索引为5,epsilon索引为6,grad索引为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的索引为0,accum索引为1,accum_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索引为1,m索引为2,v索引为3,beta1_power索引为4,lr索引为5
|
||||
// betal索引为6,beta2索引为7,epsilon索引为8,grad索引为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的索引为0,m索引为1,v索引为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索引为1,alpha索引为2,delta索引为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索引为1,m索引为2,lr索引为3,logbase索引为4,sign_decay索引为5
|
||||
// beta索引为6,grad索引为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的索引为0,m索引为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索引为1,alpha索引为2,l1索引为3,l2索引为4,delta索引为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索引为1,gradient索引为2,lr索引为3,logbase索引为4,sign_decay索引为5,stat索引为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索引为1,accum索引为2,grad索引为3,indices索引为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索引为1,accum索引为2,lr索引为3,l1索引为4,l2索引为5,grad索引为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的索引为0,accum的索引为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索引为1,accum索引为2,lr索引为3,l1索引为4,l2索引为5,grad索引为6,indices索引为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的索引为0,accum的索引为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索引为1,accum索引为2,linear索引为3,grad索引为4,indices索引为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索引为1,accum索引为2,linear索引为3,grad索引为4,indices索引为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的索引为0,accum的索引为1,linear索引为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索引为1,accum索引为2,linear索引为3,grad索引为4,lr索引为5,l1索引为6,l2索引为7,lr_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索引为1,ms索引为2,mom索引为3,lr索引为4,grad索引为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索引为6,momentum索引为7,epsilon索引为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索引为1,mg索引为2,ms索引为3,mom索引为4,grad索引为5,lr索引为6,rho索引为7,momentum索引为8,epsilon索引为9
|
||||
ATTR_MAP(ApplyCenteredRMSProp) = {{"use_locking", ATTR_DESC(use_locking, AnyTraits<bool>())}};
|
||||
// 输入属性映射,rho索引为6,momentum索引为7,epsilon索引为8
|
||||
OUTPUT_MAP(ApplyCenteredRMSProp) = {{0, OUTPUT_DESC(var)}};
|
||||
// 输出映射,var的索引为0
|
||||
REG_ADPT_DESC(ApplyCenteredRMSProp, kNameApplyCenteredRMSProp, ADPT_DESC(ApplyCenteredRMSProp))
|
||||
// 注册ApplyCenteredRMSProp操作的适配器描述kNameApplyCenteredRMSProp
|
||||
} // namespace mindspore::transform
|
||||
|
|
@ -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的索引为0,mask索引为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的索引为1,activations索引为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的索引为1,weight索引为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的索引为1,features索引为2,weights索引为3
|
||||
ATTR_MAP(PReluGrad) = EMPTY_ATTR_MAP;
|
||||
// 属性映射,空
|
||||
OUTPUT_MAP(PReluGrad) = {{0, OUTPUT_DESC(dx)}, {1, OUTPUT_DESC(da)}};
|
||||
// 输出映射,dx的索引为0,da索引为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的索引为1,dy索引为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的索引为1,x索引为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的索引为1,features索引为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的索引为1,features索引为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的索引为1,features索引为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的索引为1,mask索引为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的索引为1,dy索引为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的索引为1,activations索引为2,y索引为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的索引为1,x索引为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
|
||||
|
|
@ -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
|
|
@ -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,可以根据具体需求实现不同的逻辑来计算返回值
|
||||
|
||||
// 该函数用于判断给定的操作是否为自定义操作
|
||||
// 参数:op,OperatorPtr类型的操作指针
|
||||
// 返回: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,表示该操作是自定义操作
|
||||
}
|
||||
|
||||
// 该函数用于生成自定义操作的输入映射表
|
||||
// 参数:op,CusOperatorPtr类型的自定义操作指针
|
||||
// 参数:prim,PrimitivePtr类型的操作原语指针
|
||||
// 返回: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 状态
|
||||
}
|
||||
|
||||
// 该函数用于生成自定义操作的输出映射表
|
||||
// 参数:op,CusOperatorPtr类型的自定义操作指针
|
||||
// 参数:prim,PrimitivePtr类型的操作原语指针
|
||||
// 返回: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 状态
|
||||
}
|
||||
|
||||
// 该函数用于生成自定义操作
|
||||
// 参数:anf,AnfNodePtr类型的节点指针
|
||||
// 返回: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;
|
||||
}
|
||||
|
||||
// 该函数用于设置操作的子图函数
|
||||
// 参数:op,OperatorPtr类型的操作指针
|
||||
// 参数:index,int类型的索引值
|
||||
// 参数:branches,std::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 状态
|
||||
}
|
||||
|
||||
// 该函数用于设置自定义操作的输入
|
||||
// 参数:op,CusOperatorPtr类型的自定义操作指针
|
||||
// 参数:index,int类型的输入索引
|
||||
// 参数:input,OperatorPtr类型的输入操作指针
|
||||
// 返回: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 状态
|
||||
}
|
||||
|
||||
// 该函数用于设置普通操作的输入
|
||||
// 参数:op,OperatorPtr类型的普通操作指针
|
||||
// 参数:index,int类型的输入索引
|
||||
// 参数:input,OperatorPtr类型的输入操作指针
|
||||
// 返回: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 状态
|
||||
}
|
||||
|
||||
// 该函数用于设置操作的输入
|
||||
// 参数:op,OperatorPtr类型的操作指针
|
||||
// 参数:index,int类型的输入索引
|
||||
// 参数:input,OperatorPtr类型的输入操作指针
|
||||
// 返回: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 设置普通操作的输入,并返回状态
|
||||
}
|
||||
}
|
||||
|
||||
// 该函数用于设置自定义操作的输入
|
||||
// 参数:op,CusOperatorPtr类型的自定义操作指针
|
||||
// 参数:index,int类型的输入索引
|
||||
// 参数:handle,OutHandler类型的输出处理器
|
||||
// 返回: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 状态
|
||||
}
|
||||
|
||||
// 该函数用于设置普通操作的输入
|
||||
// 参数:op,OperatorPtr类型的操作指针
|
||||
// 参数:index,int类型的输入索引
|
||||
// 参数:handle,OutHandler类型的输出处理器
|
||||
// 返回: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 状态
|
||||
}
|
||||
|
||||
// 该函数用于设置操作的输入
|
||||
// 参数:op,OperatorPtr类型的操作指针
|
||||
// 参数:index,int类型的输入索引
|
||||
// 参数:handle,OutHandler类型的输出处理器
|
||||
// 返回: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 函数设置普通操作的输入,并将结果转换为整数返回
|
||||
}
|
||||
}
|
||||
|
||||
// 该函数用于设置操作的动态输入
|
||||
|
||||
// 参数:op,OperatorPtr类型的操作指针
|
||||
// 参数:index,int类型的输入索引
|
||||
// 参数:handler_vec,std::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); // 返回未找到的状态码
|
||||
}
|
||||
|
||||
// 该函数用于获取操作的输出处理器
|
||||
// 参数:op,OperatorPtr类型的操作指针
|
||||
// 参数:index,int类型的输出索引
|
||||
// 返回: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 函数获取普通操作的输出处理器
|
||||
}
|
||||
|
||||
// 该函数用于获取自定义操作的输出处理器
|
||||
// 参数:op,OperatorPtr类型的操作指针
|
||||
// 参数:index,int类型的输出索引
|
||||
// 返回: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(); // 返回空的输出处理器
|
||||
}
|
||||
|
||||
// 该函数用于获取普通操作的输出处理器
|
||||
// 参数:op,OperatorPtr类型的操作指针
|
||||
// 参数:index,int类型的输出索引
|
||||
// 返回: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(); // 返回空的输出处理器
|
||||
}
|
||||
}
|
||||
|
||||
// 该函数用于更新单个输出的描述符
|
||||
// 参数:op,OperatorPtr类型的操作指针
|
||||
// 参数:shp,abstract::BaseShapePtr类型的输出形状指针
|
||||
// 参数:type,TypePtr类型的输出数据类型
|
||||
// 参数:format,string类型的输出数据格式
|
||||
// 返回: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_op,CusOperatorPtr类型的自定义操作指针
|
||||
// 返回: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
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,392 @@
|
|||
/**
|
||||
* Copyright 2019 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "transform/graph_ir/op_adapter_util.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "include/common/utils/utils.h"
|
||||
#include "utils/check_convert_utils.h"
|
||||
#include "transform/graph_ir/op_adapter_base.h"
|
||||
#include "transform/graph_ir/io_format_map.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace transform {
|
||||
// ConvertAnyUtil 函数用于将 MindSpore 中的 Tensor(mindspore::tensor::Tensor)转换为 GE(GraphEngine)中的Tensor(GeTensor)。
|
||||
GeTensor ConvertAnyUtil(const ValuePtr &value, const AnyTraits<mindspore::tensor::Tensor> &) {
|
||||
// To-DO the format may read from ME tensor
|
||||
// TODO:可能需要从 ME(MindSpore Execution) Tensor 读取格式信息(format)
|
||||
MS_EXCEPTION_IF_NULL(value);
|
||||
//// 将 value 强制转换为 MeTensorPtr 类型,MeTensorPtr 是一个智能指针,表示 ME Tensor(MindSpore Execution Tensor)。
|
||||
auto me_tensor = value->cast<MeTensorPtr>();
|
||||
// 调用 TransformUtil::ConvertTensor 函数将 ME Tensor 转换为 GE Tensor。
|
||||
// 这里的 kOpFormat_ND 是指定转换后的 GE Tensor 使用的格式,可能是 ND 格式(N-Dimensional)。
|
||||
auto ge_tensor = TransformUtil::ConvertTensor(me_tensor, kOpFormat_ND);
|
||||
// 如果转换后的 GE Tensor 为空,则返回一个空的 GeTensor 对象,否则返回转换后的 GE Tensor。
|
||||
return ge_tensor == nullptr ? GeTensor() : *ge_tensor;
|
||||
}
|
||||
|
||||
// ConvertAnyUtil 函数用于将一个 ValuePtr 类型的值转换为 std::vector<int64_t> 类型。
|
||||
// 转换的方式取决于传入的 name 参数和数据类型 AnyTraits<std::vector<int64_t>>。
|
||||
std::vector<int64_t> ConvertAnyUtil(const ValuePtr &value, const std::string &name,
|
||||
const AnyTraits<std::vector<int64_t>>) {
|
||||
MS_EXCEPTION_IF_NULL(value);
|
||||
std::vector<int64_t> list; // 创建一个 int64_t 类型的 vector,用于存储转换后的结果。
|
||||
if (name == "pad") { // 如果传入的 name 是 "pad",则执行特定的转换逻辑。
|
||||
if (!value->isa<ValueSequence>()) { // 确保 value 是 ValueSequence 类型。
|
||||
MS_LOG(EXCEPTION) << "Value should be ValueTuple, but got" << value->type_name();
|
||||
}
|
||||
auto vec = value->cast<ValueSequencePtr>(); // 将 value 转换为 ValueSequencePtr 类型。
|
||||
// 调整 vector 的大小以容纳转换后的结果。
|
||||
// 由于结果包含两个额外的元素(1和1),因此比 ValueSequence 的大小大2。
|
||||
list.resize(vec->value().size() + 2);
|
||||
// 将额外的两个元素设置为 1。
|
||||
list[0] = 1;
|
||||
list[1] = 1;
|
||||
// 使用 std::transform 将 ValueSequence 中的元素转换为 int64_t,并存储到 vector 中。
|
||||
(void)std::transform(vec->value().begin(), vec->value().end(), list.begin() + 2,
|
||||
[](const ValuePtr &val) { return static_cast<int64_t>(GetValue<int64_t>(val)); });
|
||||
} else { // 如果 name 不是 "pad",则执行通用的转换逻辑。
|
||||
int64_t data = GetValue<int64_t>(value); // 从 value 中获取 int64_t 类型的数据。
|
||||
int size = 2; // 2 int in list // 设置 vector 的大小为2,以容纳两个 int64_t 类型的元素。
|
||||
// 调用 TransformUtil::ConvertIntToList 函数将 int64_t 转换为 std::vector<int64_t>。
|
||||
list = TransformUtil::ConvertIntToList(data, size);
|
||||
}
|
||||
|
||||
return list; // 返回转换后的 std::vector<int64_t> 对象。
|
||||
}
|
||||
|
||||
// ConvertAnyUtil 函数用于将一个 ValuePtr 类型的值转换为 std::string 类型。
|
||||
// 转换的方式取决于传入的数据类型 AnyTraits<std::vector<int64_t>> 和 AnyTraits<std::string>。
|
||||
std::string ConvertAnyUtil(const ValuePtr &value, const AnyTraits<std::vector<int64_t>>, const AnyTraits<std::string>) {
|
||||
MS_EXCEPTION_IF_NULL(value);
|
||||
auto vec = value->cast<ValueTuplePtr>(); // 将 value 转换为 ValueTuplePtr 类型。
|
||||
if (vec == nullptr) { // 如果 vec 为空指针,则抛出异常,说明传入的 value 不是 ValueTuplePtr 类型。
|
||||
MS_LOG(EXCEPTION) << "not ValueTuplePtr";
|
||||
}
|
||||
std::ostringstream buffer; // 创建一个 ostringstream 对象,用于构建字符串。
|
||||
int i = 0; // 用于辅助构建字符串的计数器。
|
||||
for (auto &it : vec->value()) { // 遍历 value 中的元素。
|
||||
if (i != 0) { // 在每个元素之前加入逗号(除了第一个元素)。
|
||||
buffer << ",";
|
||||
}
|
||||
buffer << GetValue<int64_t>(it); // 将元素的值转换为 int64_t,并添加到字符串流中。
|
||||
i++; // 增加计数器。
|
||||
}
|
||||
return buffer.str(); // 返回构建的字符串。
|
||||
}
|
||||
|
||||
// ConvertAnyUtil 函数用于将一个 ValuePtr 类型的值转换为 std::vector<float> 类型。
|
||||
// 转换的方式取决于传入的数据类型 AnyTraits<std::vector<float>> 和 AnyTraits<float>。
|
||||
std::vector<float> ConvertAnyUtil(const ValuePtr &value, const AnyTraits<std::vector<float>>, const AnyTraits<float>) {
|
||||
MS_EXCEPTION_IF_NULL(value);
|
||||
auto vec = value->cast<ValueTuplePtr>(); // 将 value 转换为 ValueTuplePtr 类型。
|
||||
if (vec == nullptr) { // 如果 vec 为空指针,则抛出异常,说明传入的 value 不是 ValueTuplePtr 类型。
|
||||
MS_LOG(EXCEPTION) << "not ValueTuplePtr";
|
||||
}
|
||||
std::vector<float> list; // 创建一个 std::vector<float> 对象,用于存储转换后的结果。
|
||||
list.resize(vec->value().size()); // 调整 vector 的大小以容纳转换后的结果,大小与 ValueTuple 中的元素个数相同。
|
||||
// 使用 std::transform 将 ValueTuple 中的每个元素转换为 float,并存储到 vector 中。
|
||||
(void)std::transform(vec->value().begin(), vec->value().end(), list.begin(),
|
||||
[](const ValuePtr &val) { return static_cast<float>(GetValue<float>(val)); });
|
||||
return list; // 返回转换后的 std::vector<float> 对象。
|
||||
}
|
||||
|
||||
// ConvertAnyUtil 函数用于将一个 ValuePtr 类型的值转换为 std::vector<int64_t> 类型。
|
||||
// 转换的方式取决于传入的 format 参数和数据类型 AnyTraits<std::vector<int64_t>> 和 AnyTraits<int64_t>。
|
||||
std::vector<int64_t> ConvertAnyUtil(const ValuePtr &value, const std::string &format,
|
||||
const AnyTraits<std::vector<int64_t>>, const AnyTraits<int64_t>) {
|
||||
MS_EXCEPTION_IF_NULL(value);
|
||||
auto vec = value->cast<ValueTuplePtr>(); // 将 value 转换为 ValueTuplePtr 类型。
|
||||
if (vec == nullptr) { // 如果 vec 为空指针,则抛出异常,说明传入的 value 不是 ValueTuplePtr 类型。
|
||||
MS_LOG(EXCEPTION) << "not ValueTuplePtr";
|
||||
}
|
||||
std::vector<int64_t> list; // 创建一个 std::vector<int64_t> 对象,用于存储转换后的结果。
|
||||
list.resize(vec->value().size()); // 调整 vector 的大小以容纳转换后的结果,大小与 ValueTuple 中的元素个数相同。
|
||||
// 使用 std::transform 将 ValueTuple 中的每个元素转换为 int64_t,并存储到 vector 中。
|
||||
(void)std::transform(vec->value().begin(), vec->value().end(), list.begin(),
|
||||
[](const ValuePtr &val) { return static_cast<int64_t>(GetValue<int64_t>(val)); });
|
||||
if (format == kOpFormat_NHWC) { // 根据传入的 format 参数执行特定的格式转换。
|
||||
if (list.size() < 4) { // 如果格式为 NHWC,但列表大小小于4,则抛出异常。
|
||||
MS_LOG(EXCEPTION) << "The size of list is less than 4";
|
||||
} else { // 如果格式为 NHWC,并且列表大小大于等于4,则进行格式转换。
|
||||
// 将列表中的第1个元素和第2个元素交换位置,将第3个元素和第4个元素交换位置。
|
||||
int64_t temp = list[1];
|
||||
list[1] = list[2];
|
||||
list[2] = list[3];
|
||||
list[3] = temp;
|
||||
}
|
||||
}
|
||||
return list; // 返回转换后的 std::vector<int64_t> 对象。
|
||||
}
|
||||
|
||||
// ConvertAnyUtil 函数用于将一个 ValuePtr 类型的值转换为 GeDataType(GraphEngine 的数据类型)。
|
||||
// 转换的方式取决于传入的数据类型 AnyTraits<GEType>。
|
||||
GeDataType ConvertAnyUtil(const ValuePtr &value, const AnyTraits<GEType>) {
|
||||
MS_EXCEPTION_IF_NULL(value);
|
||||
if (!value->isa<Type>()) { // 确保 value 是 Type 类型。
|
||||
MS_LOG(EXCEPTION) << "error convert Value to TypePtr for value: " << value->ToString()
|
||||
<< ", type: " << value->type_name() << ", value should be a Typeptr";
|
||||
}
|
||||
auto type = value->cast<TypePtr>(); // 将 value 转换为 TypePtr 类型。
|
||||
MS_EXCEPTION_IF_NULL(type); // 确保转换后的 type 不为空指针。
|
||||
TypeId me_type = type->type_id(); // 获取 TypePtr 对象的 TypeId(MindSpore 中的数据类型标识)。
|
||||
// 如果 TypePtr 对象的 TypeId 是 kObjectTypeTensorType,表示其为 TensorType 类型。
|
||||
// 需要进一步获取其元素类型的 TypeId,以便进行后续的 GraphEngine 数据类型转换。
|
||||
if (kObjectTypeTensorType == me_type) {
|
||||
me_type = dyn_cast<TensorType>(type)->element()->type_id();
|
||||
}
|
||||
return TransformUtil::ConvertDataType(me_type); // 调用 TransformUtil::ConvertDataType 函数将 MindSpore 的数据类型转换为 GraphEngine 的数据类型。
|
||||
}
|
||||
|
||||
// VectorToTensorUtil 函数用于将一个 ValuePtr 类型的值转换为 GeTensor(GraphEngine 的 Tensor)。
|
||||
// 该函数支持将 tuple 或 list 转换为 GeTensor,目前仅支持一维数据。
|
||||
GeTensor VectorToTensorUtil(const ValuePtr &value) {
|
||||
// convert tuple or list to ge tensor, only supported one dim for now
|
||||
// 转换 tuple 或 list 到 ge tensor,目前仅支持一维数据
|
||||
MS_EXCEPTION_IF_NULL(value);
|
||||
// 获取 tuple 或 list 中的元素值。
|
||||
auto vec = value->isa<ValueTuple>() ? value->cast<ValueTuplePtr>()->value() : value->cast<ValueListPtr>()->value();
|
||||
if (vec.empty()) { // 如果 tuple 或 list 为空,则返回一个空的 GeTensor。
|
||||
MS_LOG(WARNING) << "Convert a none tuple to an empty ge tensor";
|
||||
return GeTensor(GeTensorDesc(ge::Shape({0})));
|
||||
}
|
||||
MS_EXCEPTION_IF_NULL(vec[0]); // 获取第一个元素,并确保它不为空。
|
||||
// 根据第一个元素的数据类型执行相应的转换逻辑。
|
||||
// 如果第一个元素是 Int32Imm 类型,表示需要将数据转换为 int32_t 类型的 GeTensor。
|
||||
if (vec[0]->isa<Int32Imm>()) {
|
||||
MS_LOG(INFO) << "convert value to tensor with data type = Int32";
|
||||
// 将数据转换为 int32_t 类型的 std::vector。
|
||||
auto data = ConvertAnyUtil(value, AnyTraits<int32_t>(), AnyTraits<std::vector<int32_t>>());
|
||||
// 获取对应的 GeTensorDesc 描述信息。
|
||||
auto desc = TransformUtil::GetGeTensorDesc({static_cast<int>(vec.size())}, kNumberTypeInt32, kOpFormat_NCHW);
|
||||
// 如果获取描述信息失败,则抛出异常。
|
||||
if (desc == nullptr) {
|
||||
MS_LOG(EXCEPTION) << "Update conversion descriptor failed!";
|
||||
}
|
||||
// 创建 GeTensor,并使用 int32_t 类型的数据填充 Tensor 数据。
|
||||
return GeTensor(*desc, reinterpret_cast<uint8_t *>(data.data()), data.size() * sizeof(int32_t));
|
||||
// 如果第一个元素是 Int64Imm 类型,表示需要将数据转换为 int64_t 类型的 GeTensor。
|
||||
} else if (vec[0]->isa<Int64Imm>()) {
|
||||
MS_LOG(INFO) << "convert value to tensor with data type = Int64";
|
||||
// 将数据转换为 int64_t 类型的 std::vector。
|
||||
auto data = ConvertAnyUtil(value, AnyTraits<int64_t>(), AnyTraits<std::vector<int64_t>>());
|
||||
// 获取对应的 GeTensorDesc 描述信息。
|
||||
auto desc = TransformUtil::GetGeTensorDesc({static_cast<int>(vec.size())}, kNumberTypeInt64, kOpFormat_NCHW);
|
||||
if (desc == nullptr) { // 如果获取描述信息失败,则抛出异常。
|
||||
MS_LOG(EXCEPTION) << "Update conversion descriptor failed!";
|
||||
}
|
||||
// 创建 GeTensor,并使用 int64_t 类型的数据填充 Tensor 数据。
|
||||
return GeTensor(*desc, reinterpret_cast<uint8_t *>(data.data()), data.size() * sizeof(int64_t));
|
||||
// 如果第一个元素是 FP32Imm 类型,表示需要将数据转换为 float 类型的 GeTensor。
|
||||
} else if (vec[0]->isa<FP32Imm>()) {
|
||||
MS_LOG(INFO) << "convert value to tensor with data type = Float32";
|
||||
// 将数据转换为 float 类型的 std::vector。
|
||||
auto data = ConvertAnyUtil(value, AnyTraits<float>(), AnyTraits<std::vector<float>>());
|
||||
// 获取对应的 GeTensorDesc 描述信息。
|
||||
auto desc = TransformUtil::GetGeTensorDesc({static_cast<int>(vec.size())}, kNumberTypeFloat32, kOpFormat_NCHW);
|
||||
if (desc == nullptr) { // 如果获取描述信息失败,则抛出异常。
|
||||
MS_LOG(EXCEPTION) << "Update conversion descriptor failed!";
|
||||
}
|
||||
// 创建 GeTensor,并使用 float 类型的数据填充 Tensor 数据。
|
||||
return GeTensor(*desc, reinterpret_cast<uint8_t *>(data.data()), data.size() * sizeof(float));
|
||||
} else if (vec[0]->isa<BoolImm>()) { // 如果第一个元素是 BoolImm 类型,表示需要将数据转换为 bool 类型的 GeTensor。
|
||||
MS_LOG(INFO) << "convert value to tensor with data type = Bool";
|
||||
// We use uint8_t to save bool type data
|
||||
// 将数据转换为 bool 类型的 std::vector。
|
||||
// 这里使用 uint8_t
|
||||
auto data = ConvertAnyUtil(value, AnyTraits<bool>(), AnyTraits<std::vector<uint8_t>>());
|
||||
auto desc = TransformUtil::GetGeTensorDesc({static_cast<int>(vec.size())}, kNumberTypeBool, kOpFormat_NCHW);
|
||||
if (desc == nullptr) {
|
||||
MS_LOG(EXCEPTION) << "Update conversion descriptor failed!";
|
||||
}
|
||||
return GeTensor(*desc, static_cast<uint8_t *>(data.data()), data.size() * sizeof(uint8_t));
|
||||
} else {
|
||||
MS_LOG(EXCEPTION) << "Unsupported data type of tuple or list elements: " << vec[0]->type_name();
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertAnyUtil 函数用于将一个 ValuePtr 类型的值转换为 GeTensor(GraphEngine 的 Tensor)。
|
||||
// 转换的方式取决于传入的数据类型 AnyTraits<AnyValue>。
|
||||
GeTensor ConvertAnyUtil(const ValuePtr &value, const AnyTraits<AnyValue>) {
|
||||
MS_EXCEPTION_IF_NULL(value);
|
||||
if (value->isa<MeTensor>()) { // 检查 ValuePtr 是否是 MeTensor 类型,如果是,则执行 MeTensor 到 GeTensor 的转换。
|
||||
// convert me tensor to ge tensor
|
||||
// 将 MeTensor 转换为 GeTensor
|
||||
return ConvertAnyUtil(value, AnyTraits<MeTensor>());
|
||||
// 检查 ValuePtr 是否是 ValueList 或 ValueTuple 类型,如果是,则执行 List 或 Tuple 到 GeTensor 的转换。
|
||||
} else if (value->isa<ValueList>() || value->isa<ValueTuple>()) {
|
||||
return VectorToTensorUtil(value);
|
||||
// 检查 ValuePtr 是否是 Int32Imm 类型,如果是,则执行 Int32Imm 到 GeTensor 的转换。
|
||||
} else if (value->isa<Int32Imm>()) {
|
||||
// convert scalar Int to GeTensor
|
||||
// 将标量 Int32 转换为 GeTensor
|
||||
MS_LOG(INFO) << "convert scalar to tensor with data type = Int32";
|
||||
GeTensorDesc desc(GeShape(), ge::FORMAT_NCHW, ge::DT_INT32); // 创建 GeTensorDesc 描述信息。
|
||||
auto v = GetValue<int32_t>(value);
|
||||
desc.SetRealDimCnt(0); // 设置描述信息的实际维度数为0(标量)。
|
||||
return GeTensor(desc, reinterpret_cast<uint8_t *>(&v), sizeof(int32_t)); // 创建 GeTensor,并使用 int32_t 类型的数据填充 Tensor 数据。
|
||||
}
|
||||
// 检查 ValuePtr 是否是 Int64Imm 类型,如果是,则执行 Int64Imm 到 GeTensor 的转换。
|
||||
else if (value->isa<Int64Imm>()) {
|
||||
// convert scalar Int64 to GeTensor
|
||||
// 将标量 Int64 转换为 GeTensor
|
||||
MS_LOG(INFO) << "convert scalar to tensor with data type = Int64";
|
||||
GeTensorDesc desc(GeShape(), ge::FORMAT_NCHW, ge::DT_INT64); // 创建 GeTensorDesc 描述信息。
|
||||
auto v = GetValue<int64_t>(value);
|
||||
desc.SetRealDimCnt(0); // 设置描述信息的实际维度数为0(标量)。
|
||||
return GeTensor(desc, reinterpret_cast<uint8_t *>(&v), sizeof(int64_t)); // 创建 GeTensor,并使用 int64_t 类型的数据填充 Tensor 数据。
|
||||
}
|
||||
// 检查 ValuePtr 是否是 FP32Imm 类型,如果是,则执行 FP32Imm 到 GeTensor 的转换。
|
||||
else if (value->isa<FP32Imm>()) {
|
||||
// convert scalar FP32 to GeTensor
|
||||
MS_LOG(INFO) << "convert scalar to tensor with data type = FP32"; // 将标量 FP32 转换为 GeTensor
|
||||
GeTensorDesc desc(GeShape(), ge::FORMAT_NCHW, ge::DT_FLOAT); // 创建 GeTensorDesc 描述信息。
|
||||
auto v = GetValue<float>(value);
|
||||
desc.SetRealDimCnt(0); // 设置描述信息的实际维度数为0(标量)。
|
||||
return GeTensor(desc, reinterpret_cast<uint8_t *>(&v), sizeof(float)); // 创建 GeTensor,并使用 float 类型的数据填充 Tensor 数据。
|
||||
}
|
||||
// 检查 ValuePtr 是否是 BoolImm 类型,如果是,则执行 BoolImm 到 GeTensor 的转换。
|
||||
else if (value->isa<BoolImm>()) {
|
||||
// convert scalar FP32 to GeTensor
|
||||
// 将标量 Bool 转换为 GeTensor
|
||||
MS_LOG(INFO) << "convert scalar to tensor with data type = Bool";
|
||||
GeTensorDesc desc(GeShape(), ge::FORMAT_NCHW, ge::DT_BOOL); // 创建 GeTensorDesc 描述信息。
|
||||
auto v = GetValue<bool>(value);
|
||||
desc.SetRealDimCnt(0); // 设置描述信息的实际维度数为0(标量)。
|
||||
return GeTensor(desc, reinterpret_cast<uint8_t *>(&v), sizeof(bool)); // 创建 GeTensor,并使用 bool 类型的数据填充 Tensor 数据。
|
||||
}
|
||||
// 检查 ValuePtr 是否是 StringImm 类型,如果是,则执行 StringImm 到 GeTensor 的转换。
|
||||
else if (value->isa<StringImm>()) {
|
||||
// convert String to GeTensor
|
||||
// 将标量 String 转换为 GeTensor
|
||||
MS_LOG(INFO) << "convert string to tensor with data type = String";
|
||||
std::string v = GetValue<std::string>(value); // 获取 string 类型的值。
|
||||
std::vector<int64_t> ge_shape; // 创建 GeTensorDesc 描述信息。
|
||||
GeShape shape(ge_shape);
|
||||
GeTensorDesc desc(shape, ge::FORMAT_NCHW, ge::DT_STRING);
|
||||
GeTensor str_tensor(desc);
|
||||
(void)str_tensor.SetData(v);
|
||||
return str_tensor;
|
||||
} else {
|
||||
MS_LOG(WARNING) << "Unsupported value type: " << value->type_name()
|
||||
<< " to convert to tensor. Value: " << value->ToString();
|
||||
}
|
||||
return GeTensor();
|
||||
}
|
||||
|
||||
// IsCustomPrim 函数用于判断给定的 PrimitivePtr 是否为自定义的操作(Custom Primitive)。
|
||||
bool IsCustomPrim(const PrimitivePtr &prim) {
|
||||
if (prim == nullptr) { // 如果给定的 PrimitivePtr 为空指针,则返回 false。
|
||||
return false;
|
||||
}
|
||||
// 从 Primitive 的属性中获取名为 "_custom_op_flag" 的属性值。
|
||||
ValuePtr flag = prim->GetAttr("_custom_op_flag");
|
||||
if (flag == nullptr) { // 如果获取到的属性值为空指针,则返回 false。
|
||||
return false;
|
||||
}
|
||||
// 将属性值转换为 bool 类型,并存储在变量 is_custom_op 中。
|
||||
bool is_custom_op = GetValue<bool>(flag);
|
||||
// 如果 is_custom_op 为 false,同时 Primitive 的属性中有名为 "_custom_op_impl_config_path" 的属性,
|
||||
// 则抛出异常,提示非自定义操作不应该分配 "_custom_op_impl_config_path" 属性。
|
||||
if (!is_custom_op && prim->GetAttr("_custom_op_impl_config_path") != nullptr) {
|
||||
MS_LOG(EXCEPTION) << "The custom op flag is false, but the op information config path is not null, non-custom op "
|
||||
"can not assign the op information config path.";
|
||||
}
|
||||
|
||||
return is_custom_op; // 返回 is_custom_op,表示给定的 Primitive 是否为自定义的操作。
|
||||
}
|
||||
|
||||
// IsCustomCNode 函数用于判断给定的 AnfNodePtr 是否为自定义的 CNode。
|
||||
// 自定义 CNode 是指其第一个输入是 ValueNode,而该 ValueNode 包含一个自定义的 PrimitivePtr。
|
||||
bool IsCustomCNode(const AnfNodePtr &anf) {
|
||||
if (anf == nullptr) { // 如果给定的 AnfNodePtr 为空指针,则返回 false。
|
||||
return false;
|
||||
}
|
||||
auto node = anf->cast<CNodePtr>(); // 将 AnfNodePtr 转换为 CNodePtr。
|
||||
if (node == nullptr) { // 如果转换失败,说明给定的 AnfNodePtr 不是 CNode,返回 false。
|
||||
return false;
|
||||
}
|
||||
if (node->inputs().empty()) { // 检查 CNode 的输入是否为空,如果为空,抛出异常。
|
||||
MS_LOG(EXCEPTION) << "Length of node inputs is empty";
|
||||
}
|
||||
MS_EXCEPTION_IF_NULL(node->inputs()[0]); // 检查 CNode 的第一个输入是否为空指针,如果是,抛出异常。
|
||||
// 检查 CNode 的第一个输入是否为 ValueNode,如果不是,返回 false,表示不是自定义 CNode。
|
||||
if (!node->inputs()[0]->isa<ValueNode>()) {
|
||||
return false;
|
||||
}
|
||||
// 尝试将 CNode 的第一个输入转换为 ValueNode,并获取其包含的 PrimitivePtr。
|
||||
auto cus_prim = GetValueNode<PrimitivePtr>(node->inputs()[0]);
|
||||
if (cus_prim == nullptr) { // 如果获取的 PrimitivePtr 为空指针,返回 false,表示不是自定义 CNode。
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsCustomPrim(cus_prim); // 调用 IsCustomPrim 函数判断获取的 PrimitivePtr 是否为自定义的操作,返回判断结果。
|
||||
}
|
||||
|
||||
// GetOpIOFormat 函数用于获取给定 AnfNodePtr 对应的操作的输入输出格式(IO Format)。
|
||||
std::string GetOpIOFormat(const AnfNodePtr &anf) {
|
||||
std::string ret;
|
||||
if (anf == nullptr) { // 检查给定的 AnfNodePtr 是否为空指针,如果是,输出错误日志并返回空字符串。
|
||||
MS_LOG(ERROR) << "The anf is nullptr";
|
||||
return ret;
|
||||
}
|
||||
auto node = anf->cast<CNodePtr>(); // 尝试将 AnfNodePtr 转换为 CNodePtr。
|
||||
if (node == nullptr) { // 如果转换失败,说明给定的 AnfNodePtr 不是 CNode,输出错误日志并返回空字符串。
|
||||
MS_LOG(ERROR) << "The anf is not a cnode.";
|
||||
return ret;
|
||||
}
|
||||
if (node->inputs().empty()) { // 检查 CNode 的输入是否为空,如果为空,抛出异常。
|
||||
MS_LOG(EXCEPTION) << "Length of node inputs is empty.";
|
||||
}
|
||||
MS_EXCEPTION_IF_NULL(node->inputs()[0]); // 检查 CNode 的第一个输入是否为空指针,如果是,抛出异常。
|
||||
if (!node->inputs()[0]->isa<ValueNode>()) { // 检查 CNode 的第一个输入是否为 ValueNode,如果不是,输出错误日志并返回空字符串。
|
||||
MS_LOG(ERROR) << "The anf is not a value node.";
|
||||
return ret;
|
||||
}
|
||||
auto prim = GetValueNode<PrimitivePtr>(node->inputs()[0]); // 尝试将 CNode 的第一个输入转换为 ValueNode,并获取其包含的 PrimitivePtr。
|
||||
if (prim == nullptr) { // 如果获取的 PrimitivePtr 为空指针,输出错误日志并返回空字符串。
|
||||
MS_LOG(ERROR) << "The anf is not a Primitive.";
|
||||
return ret;
|
||||
}
|
||||
if (prim->HasAttr("io_format")) { // 检查 PrimitivePtr 是否有名为 "io_format" 的属性,如果有,则返回其属性值作为 IO Format。
|
||||
return GetValue<std::string>(prim->GetAttr("io_format"));
|
||||
}
|
||||
// 如果 PrimitivePtr 没有名为 "io_format" 的属性,则从 IOFormatMap 中查找操作名对应的 IO Format。
|
||||
auto io_format_map = IOFormatMap::get();
|
||||
auto iter = io_format_map.find(prim->name());
|
||||
if (iter == io_format_map.end()) { // 如果在 IOFormatMap 中没有找到对应的 IO Format,则默认返回 "NCHW"。
|
||||
return "NCHW";
|
||||
}
|
||||
// 检查该 IO Format 是否是 "format" 类型的属性,如果是,进一步处理后返回具体的格式值。
|
||||
if (iter->second == "format") {
|
||||
ValuePtr format = prim->GetAttr("format");
|
||||
MS_EXCEPTION_IF_NULL(format);
|
||||
if (format->isa<Int64Imm>()) {
|
||||
bool converted = CheckAndConvertUtils::ConvertAttrValueToString(prim->name(), "format", &format);
|
||||
if (converted) {
|
||||
return GetValue<std::string>(format);
|
||||
}
|
||||
} else {
|
||||
return GetValue<std::string>(format);
|
||||
}
|
||||
}
|
||||
return iter->second; // 如果不是 "format" 类型的属性,直接返回 IO Format。
|
||||
}
|
||||
} // namespace transform
|
||||
} // namespace mindspore
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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索引为1,paddings索引为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索引为1,value索引为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索引为1,paddings索引为2,constant_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索引为1,paddings索引为2,constant_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
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
@ -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索引为1,deq_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
|
||||
|
|
@ -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索引为1,prob索引为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索引为1,stop索引为2,num索引为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索引为0,mask索引为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
|
||||
|
|
@ -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索引为0,square_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索引为1,x索引为2,diff_scale索引为3,diff_offset索引为4,scale索引为5,batch_mean索引为6,batch_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索引为1,x索引为2,diff_scale索引为3,diff_offset索引为4,scale索引为5,batch_mean索引为6,batch_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索引为0,mean索引为1,variance索引为2,batch_mean索引为3,batch_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索引为1,x索引为2,batch_mean索引为3,batch_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索引为0,diff_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
|
||||
|
|
@ -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索引为1,h索引为2,c索引为3,w索引为4,b索引为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索引为0,ht索引为1,it索引为2,jt索引为3,ft索引为4,ot索引为5,tanhct索引为6
|
||||
REG_ADPT_DESC(BasicLSTMCell, kNameBasicLSTMCell, ADPT_DESC(BasicLSTMCell))
|
||||
// 注册BasicLSTMCell操作的适配器描述kNameBasicLSTMCell
|
||||
|
||||
// BasicLSTMCellInputGrad
|
||||
INPUT_MAP(BasicLSTMCellInputGrad) = {{1, INPUT_DESC(dgate)}, {2, INPUT_DESC(w)}};
|
||||
// 输入映射,共两个,dgate索引为1,w索引为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索引为0,dht索引为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索引为1,w索引为2,dgate索引为3
|
||||
ATTR_MAP(BasicLSTMCellWeightGrad) = EMPTY_ATTR_MAP;
|
||||
//属性映射,空
|
||||
OUTPUT_MAP(BasicLSTMCellWeightGrad) = {{0, OUTPUT_DESC(dw)}, {1, OUTPUT_DESC(db)}};
|
||||
// 输出映射,共两个,dw索引为0,db索引为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索引为1,dht索引为2,dct索引为3,it索引为4,jt索引为5,ft索引为6,ot索引为7,tanhct索引为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索引为0,dct_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索引为1,init_c索引为2,di索引为3,dy索引为4,dh索引为5,dc索引为6,i索引为7,j索引为8,f索引为9,o索引为10,tanhct索引为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索引为1,dc_prev索引为2,dgate索引为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索引为1,w索引为2,b索引为3,seq_length索引为4,init_h索引为5,init_c索引为6,wci索引为7,wcf索引为8,wco索引为9,mask索引为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索引为1,w索引为2,b索引为3,seq_length索引为4,init_h索引为5,init_c索引为6,wci索引为7,wcf索引为8,wco索引为9,mask索引为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索引为1,w索引为2,b索引为3,y索引为4,init_h索引为5,init_c索引为6,h索引为7,c索引为8,dy索引为9,dh索引为10,dc索引为11,i索引为12
|
||||
//j索引为13,f索引为14,o索引为15,tanhct索引为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索引为0,db索引为1,dh_prev索引为2,dh_prev索引为3,dc_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索引为1,weight_input索引为2,weight_hidden索引为3,bias_input索引为4,bias_hidden索引为5,seq_length索引为6,init_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索引为0,output_h索引为1,update索引为2,reset索引为3,new索引为4,hidden_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索引为1,weight_input索引为2,weight_hidden索引为3,y索引为4,init_h索引为5,h索引为6,dy索引为7,dh索引为8,
|
||||
//update索引为9,reset索引为10,new索引为11,hidden_new索引为12,seq_length索引为13,mask索引为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索引为0,dw_hidden索引为1,db_input索引为2,db_hidden索引为3,dx索引为4,dh_prev索引为5
|
||||
REG_ADPT_DESC(DynamicGRUV2Grad, kNameDynamicGRUV2Grad, ADPT_DESC(DynamicGRUV2Grad))
|
||||
// 注册DynamicGRUV2Grad操作的适配器描述kNameDynamicGRUV2Grad
|
||||
} // namespace mindspore::transform
|
||||
|
|
@ -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
|
||||
|
|
@ -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索引为1,indices索引为2,updates索引为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索引为1,indices索引为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索引为1,dim索引为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索引为1,y索引为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索引为1,y索引为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索引为1,y索引为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索引为1,x1索引为2,x2索引为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索引为1,shape索引为2,begin索引为3,end索引为4,strides索引为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索引为1,begin索引为2,end索引为3,strides索引为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索引为1,begin索引为2,end索引为3,axes索引为4,strides索引为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索引为1,segment_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索引为1,segment_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索引为1,segment_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索引为1,segment_ids索引为2,num_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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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`)向量转换为对应的 MeTensor(MindSpore
|
||||
// 引擎中的张量)向量,并返回转换后的结果。 `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`)向量转换为对应的 MeTensor(MindSpore 引擎中的张量)向量,并返回转换后的结果。
|
||||
//`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 函数用于将给定的 GeDataType(Ascend AI Core 引擎中的数据类型)转换为对应的 MeDataType(MindSpore引擎中的数据类型)。
|
||||
//`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
|
||||
Loading…
Reference in New Issue