• [基础知识] mindspore代码标注
    MindSpore-MindArmour-master\mindspore-mindarmour\build\bdist.win-amd64\egg\mindarmour\privacy\evaluation_check_config.py的代码标注 本篇博客分析MindSpore的MindArmour模块,继续着眼于AI的安全和隐私问题 下面开始分析隐私泄露评估模块的参数配置检查文件 引入的一个包需要了解一下下 logging包 python的一个包,专门用来写日志的。 官方一共划分了6个等级的log类型,分别对应重要性等级50,40,30,20,10,0: 级别排序:CRITICAL > ERROR > WARNING > INFO > DEBUG >NOTSET 常用的logging模块包含四种角色:logger(负责产生日志信息),filter(负责筛选日志),formatter(控制日志输出格式 ),handler(负责日志输出的目标 ) # 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. """ Verify attack config """ # 引入包进行多维数组的操作 import numpy as np # 引入包检查参数 from mindarmour.utils._check_param import check_param_type # 引入包写日志 from mindarmour.utils.logger import LogUtil # LogUtil类的实例化 LOGGER = LogUtil.get_instance() TAG = "check_config" # 以下是一些判断数据类型的简单函数,在此不做多余的注释,isinstance()相当于typeof() def _is_positive_int(item): """Verify that the value is a positive integer.""" if not isinstance(item, int): return False return item > 0 def _is_non_negative_int(item): """Verify that the value is a non-negative integer.""" if not isinstance(item, int): return False return item >= 0 def _is_positive_float(item): """Verify that value is a positive number.""" if not isinstance(item, (int, float)): return False return item > 0 def _is_non_negative_float(item): """Verify that value is a non-negative number.""" if not isinstance(item, (int, float)): return False return item >= 0 def _is_range_0_1_float(item): if not isinstance(item, (int, float)): return False return 0 = item 1 def _is_positive_int_tuple(item): """Verify that the input parameter is a positive integer tuple.""" if not isinstance(item, tuple): return False for i in item: if not _is_positive_int(i): return False return True def _is_dict(item): """Check whether the type is dict.""" return isinstance(item, dict) def _is_list(item): """Check whether the type is list""" return isinstance(item, list) def _is_str(item): """Check whether the type is str.""" return isinstance(item, str) # 下面是对4种机器学习算法的参数检查列表,用上面的那些简单函数来检查这些机器学习算法的数据类型是否正确,作为标准值方便下面主函数调用检测attack的配置是否正确 _VALID_CONFIG_CHECKLIST = { "knn": { "n_neighbors": [_is_positive_int], "weights": [{"uniform", "distance"}, callable], "algorithm": [{"auto", "ball_tree", "kd_tree", "brute"}], "leaf_size": [_is_positive_int], "p": [_is_positive_int], "metric": [_is_str, callable], "metric_params": [_is_dict, {None}] }, "lr": { "penalty": [{"l1", "l2", "elasticnet", "none"}], "dual": [{True, False}], "tol": [_is_positive_float], "C": [_is_positive_float], "fit_intercept": [{True, False}], "intercept_scaling": [_is_positive_float], "class_weight": [{"balanced", None}, _is_dict], "random_state": None, "solver": [{"newton-cg", "lbfgs", "liblinear", "sag", "saga"}] }, "mlp": { "hidden_layer_sizes": [_is_positive_int_tuple], "activation": [{"identity", "logistic", "tanh", "relu"}], "solver": [{"lbfgs", "sgd", "adam"}], "alpha": [_is_positive_float], "batch_size": [{"auto"}, _is_positive_int], "learning_rate": [{"constant", "invscaling", "adaptive"}], "learning_rate_init": [_is_positive_float], "power_t": [_is_positive_float], "max_iter": [_is_positive_int], "shuffle": [{True, False}], "random_state": None, "tol": [_is_positive_float], "verbose": [{True, False}], "warm_start": [{True, False}], "momentum": [_is_positive_float], "nesterovs_momentum": [{True, False}], "early_stopping": [{True, False}], "validation_fraction": [_is_range_0_1_float], "beta_1": [_is_range_0_1_float], "beta_2": [_is_range_0_1_float], "epsilon": [_is_positive_float], "n_iter_no_change": [_is_positive_int], "max_fun": [_is_positive_int] }, "rf": { "n_estimators": [_is_positive_int], "criterion": [{"gini", "entropy"}], "max_depth": [{None}, _is_positive_int], "min_samples_split": [_is_positive_float], "min_samples_leaf": [_is_positive_float], "min_weight_fraction_leaf": [_is_non_negative_float], "max_features": [{"auto", "sqrt", "log2", None}, _is_positive_float], "max_leaf_nodes": [_is_positive_int, {None}], "min_impurity_decrease": [_is_non_negative_float], "min_impurity_split": [{None}, _is_positive_float], "bootstrap": [{True, False}], "n_jobs": [_is_positive_int, {None}], "random_state": None, "verbose": [_is_non_negative_int], "warm_start": [{True, False}], "class_weight": [{"balanced", "balanced_subsample"}, _is_dict, _is_list], "ccp_alpha": [_is_non_negative_float], "max_samples": [{None}, _is_positive_int, _is_range_0_1_float] } } # 主要是利用引入的_check_param.py文件中的check_param_type来检测攻击的配置参数 def _check_config(attack_config, config_checklist): """ Verify that config_list is valid. Check_params is the valid value range of the parameter. """ for config in attack_config: # 该函数检测是不是字典类型,如果是,略过,如果不是,raise错误 check_param_type("config", config, dict) if set(config.keys()) != {"params", "method"}: msg = "Keys of each config in attack_config must be {}," \ "but got {}.".format({'method', 'params'}, set(config.keys())) LOGGER.error(TAG, msg) raise KeyError(msg) # 对配置的值进行简单处理 method = str.lower(config["method"]) params = config["params"] # 下面是对一些参数是否正确的判断 if method not in config_checklist.keys(): msg = "Method {} is not supported.".format(method) LOGGER.error(TAG, msg) raise NameError(msg) if not params.keys() = config_checklist[method].keys(): msg = "Params in method {} is not accepted, the parameters " \ "that can be set are {}.".format(method, set(config_checklist[method].keys())) LOGGER.error(TAG, msg) raise KeyError(msg) for param_key in params.keys(): param_value = params[param_key] candidate_values = config_checklist[method][param_key] # 检测paragrame_value是不是(list, tuple, np.ndarray)这样的形式 check_param_type('param_value', param_value, (list, tuple, np.ndarray)) if candidate_values is None: continue # 对参数值得检验 for item_value in param_value: flag = False for candidate_value in candidate_values: if isinstance(candidate_value, set) and item_value in candidate_value: flag = True break elif not isinstance(candidate_value, set) and candidate_value(item_value): flag = True break if not flag: msg = "Setting of parmeter {} in method {} is invalid".format(param_key, method) raise ValueError(msg) # 主函数,验证攻击参数配置 def verify_config_params(attack_config): """ External interfaces to verify attack config. """ # 用 _check_config(attack_config, _VALID_CONFIG_CHECKLIST)
  • [MindX SDK] 基于Pipeline的流程开发中对于NLP类模型输入构建的数据类型错误问题
    【功能模块】最近在做nlp方面的模型转化,参考官网提供的bert模型的开发方式。现在需要将一个1*500的词向量作为模型输入没办法直接调用send_data函数。参照bert中的构建protobuf_vec向量。然后调用SendPortobuf函数进行模型输入。此时会报错,而打印protobuf_vec的类型信息显示为:前面多了个roxy of <Swig Object of type (不知道是什么原因) 相关代码L是一个长度为500的int类型的listtensor = np.array(L)tensor = np.expand_dims(tensor, 0)tensor_package_list = MxpiDataType.MxpiTensorPackageList()tensor_package = tensor_package_list.tensorPackageVec.add()array_bytes = tensor.tobytes()data_input = MxDataInput()data_input.data = array_bytestensor_vec = tensor_package.tensorVec.add()tensor_vec.deviceId = 0tensor_vec.memType = 0for i in tensor.shape: tensor_vec.tensorShape.append(i)tensor_vec.dataStr = data_input.datatensor_vec.tensorDataSize = len(array_bytes)key = "appsrc{}".format(appsrc_id).encode('utf-8')print('key='+str(key))protobuf_vec = InProtobufVector()protobuf = MxProtobufIn()protobuf.key = keyprotobuf.type = b'MxTools.MxpiTensorPackageList'protobuf.protobuf = tensor_package_list.SerializeToString()protobuf_vec.push_back(protobuf)print("发送数据流表为")print(protobuf_vec)ret = stream_manager.SendProtobuf(stream_name, appsrc_id, protobuf_vec)
  • [新手课堂] Java数据类型
      Java是一种强类型语言。这就意味着必须为每一个变量声明一种类型。在Java中一共有8种基本类型(primitive type),其中有4种整型、2种浮点类型、一种字符类型char(用于表示Unicode编码的代码单元),和一种用于表示真值的boolean类型(布尔型)。  整型整型用于表示没有小数部分的数值,允许是负数。Java提供了4种整型,如下表所示 类型:                                                       存储需求                                                             取值范围                                       byte            1字节      8bit    -128 ~ 127         short            2字节      16bit      -32 768 ~ 32 767         int            4字节      32bit    -2 147 483 648 ~ 2 147 483 647         long            8字节      64bit    -9 223 372 036 854 775 808 ~ 9 233 372 036 854 775 807浮点类型   类型               存储需求                                                     取值范围                                                                                                                                                          float          4字节     ±3.402 823 47 E+38F( 有效位数为6~7位)       double             8字节    ±1.797 693 134 862 315 70E+308(有效位数15位)     float类型的数值有一个后缀F或f (例如,3.14F)。没有后缀F的浮点数值(如3.14)总是默认为double类型。当然,也可以在浮点数值后面添加后缀D或d(例如,3.14D)。    double表示这种类型的数值精度是float类型的两倍(有人称之为双精度数值)。  char类型    char类型原本用于表示单个字符。不过,现在情况已经有所变化。如今,有些Unicode字符可以用一个char值描述,另外一些Unicode字符则需要两个char值。    char类型字面量值要用单引号括起来。例如:'A'是编码值为65的字符常量。它与"A"不同, "A"是包含一个字符A的字符串。char类型的值可以表示为十六进制值字符是单引号(' ')字符串是双引号(" ")在Java中,char类型描述了UTF-16编码中的一个代码单元。在此强烈建议不要在程序中使用char类型,除非确实需要处理UTF-16代码单元。最好将字符串作为抽象数据类型处理。     boolean类型  boolean(布尔)类型有两个值:false 和 true,用来做判定逻辑条件。布尔值很特殊,整型值和布尔值之间不能进行相互转换。
  • [基础知识] MindSpore Lite理解
    一、关于张量 1.张量(Tensor)是MindSpore中的基本数据结构。张量是现代机器学习的基础。它的核心是一个数据容器,多数情况下,它包含数字,有时候它也包含字符串。可以理解为张量=容器。 有一些存储在各种类型张量的公用数据集类型: 3维=时间序列 4维=图像 5维=视频 2.张量的初始化方式有多种,构造张量时,支持传入`Tensor、float、int、bool、tuple、list`和`NumPy.array`类型。 3.根据数据直接生成 ---可以根据数据创建张量,数据类型可以设置或者自动推断。 从NumPy数组生成 ---可以从NumPy数组创建张量。 继承另一个张量的属性,形成新的张量 4.张量的属性包括形状(shape)和数据类型(dtype)。 形状:Tensor的shape,是一个元组(tuple)。 数据类型:Tensor的dtype,是MindSpore的一个数据类型。 5.张量之间有很多运算,包括算术、线性代数、矩阵处理(转置、标引、切片)、采样等. 二、mindspore Lite中的张量 | 名称 | 功能 | 返回值 | | :------------ | :------------ | :------------ | |MSTensor | MindSpore Lite MSTensor的构造函数 | MindSpore Lite MSTensor的实例 | | ~MSTensor | MindSpore Lite Model的析构函数 | 无 | | data_type | 获取MindSpore Lite MSTensor的数据类型 | MindSpore Lite MSTensor类的MindSpore Lite TypeId | | shape | 获取MindSpore Lite MSTensor的形状 | 一个包含MindSpore Lite MSTensor形状数值的整型向量 | | ElementsNum | 获取MSTensor中的元素个数 | MSTensor中的元素个数 | | Size | 获取MSTensor中的数据的字节数大小 | MSTensor中的数据的字节数大小 | | MutableData | 获取MSTensor中的数据的指针(对MSTensor中的数据进行读取和写入) | 指向MSTensor中的数据的指针 | ```cpp /** * 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. */ #ifndef MINDSPORE_LITE_INCLUDE_MS_TENSOR_H_ #define MINDSPORE_LITE_INCLUDE_MS_TENSOR_H_ #include "include/lite_utils.h" #include "ir/dtype/type_id.h" //定义了MindSpore Lite中的张量 namespace mindspore { namespace tensor { /// \brief MSTensor defined tensor in MindSpore Lite. class MS_API MSTensor { public: /// \brief Constructor of MindSpore Lite MSTensor. /// /// \return Instance of MindSpore Lite MSTensor. MSTensor() = default; /// \brief Destructor of MindSpore Lite Model. virtual ~MSTensor() = default; /// \brief Create a MSTensor. /// /// \return Pointer to an instance of MindSpore Lite MSTensor. static MSTensor *CreateTensor(const String &name, TypeId type, const Vector &shape, const void *data, size_t data_len); /// \brief Get data type of the MindSpore Lite MSTensor. /// /// \note TypeId is defined in mindspore/mindspore/include/api/type_id.h. Only number types in TypeId enum are /// suitable for MSTensor. /// /// \return MindSpore Lite TypeId of the MindSpore Lite MSTensor. virtual TypeId data_type() const = 0; /// \brief Get shape of the MindSpore Lite MSTensor. /// /// \return A vector of int as the shape of the MindSpore Lite MSTensor. virtual Vector shape() const = 0; /// \brief Set the shape of MSTensor. virtual void set_shape(const Vector &shape) = 0; /// \brief Get number of element in MSTensor. /// /// \return Number of element in MSTensor. virtual int ElementsNum() const = 0; /// \brief Get byte size of data in MSTensor. /// /// \return Byte size of data in MSTensor. virtual size_t Size() const = 0; /// \brief Get the name of MSTensor. /// /// \return the name of MSTensor. virtual String tensor_name() const = 0; /// \brief Set the name of MSTensor. virtual void set_tensor_name(const String &name) = 0; /// \brief Get the pointer of data in MSTensor. /// /// \note The data pointer can be used to both write and read data in MSTensor. The memory buffer will be /// automatically allocated. /// /// \return the pointer points to data in MSTensor. virtual void *MutableData() = 0; /// \brief Get the pointer of data in MSTensor. /// /// \note The data pointer can be used to both write and read data in MSTensor. No memory buffer will be /// allocated. /// /// \return the pointer points to data in MSTensor. virtual void *data() = 0; /// \brief Set the data of MSTensor. virtual void set_data(void *data) = 0; }; } // namespace tensor } // namespace mindspore #endif // MINDSPORE_LITE_INCLUDE_MS_TENSOR_H_ ```
  • [活动体验] 关于*/minddata/dataset/core/data_type.cc的注释
    该文件主要用于数据类型的转换适配 (大致为python、Android两种环境以及普通环境)#include "minddata/dataset/core/data_type.h"#ifdef ENABLE_PYTHON#include "minddata/dataset/core/pybind_support.h"#endif/* 这里判断如果是python语言,则用python支持的库文件 */#ifndef ENABLE_ANDROID#include "utils/log_adapter.h"#else#include "mindspore/lite/src/common/log_adapter.h"#endif/* 这里判断如果是Android语言,则用python支持的库文件;否则用common下的数据支持类型的库文件 */namespace mindspore {namespace dataset {// 返回一个数据类型的大小(字节)uint8_t DataType::SizeInBytes() const {if (type_ < DataType::NUM_OF_TYPES)return kTypeInfo[type_].sizeInBytes_;elsereturn 0;}/* 以下是python情况下,作为Numpy类型。 NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。*/ #ifdef ENABLE_PYTHONpy::dtype DataType::AsNumpyType() const {if (type_ < DataType::NUM_OF_TYPES)return py::dtype(kTypeInfo[type_].pybindType_);elsereturn py::dtype("unknown");}#endif/* 以下是Android的情况,是为CVType。CV是指计算机对图像等进行处理识别。*/#ifndef ENABLE_ANDROIDuint8_t DataType::AsCVType() const {uint8_t res = kCVInvalidType;if (type_ < DataType::NUM_OF_TYPES) {res = kTypeInfo[type_].cvType_;}if (res == kCVInvalidType) {std::string type_name = "unknown";if (type_ < DataType::NUM_OF_TYPES) {type_name = std::string(kTypeInfo[type_].name_);}std::string err_msg = "Cannot convert [" + type_name + "] to OpenCV type.";err_msg += " Currently unsupported data type: [uint32, int64, uint64, string]";MS_LOG(ERROR) << err_msg;}return res;} // namespace dataset// 从CVtype下获取数据类型DataType DataType::FromCVType(int cv_type) {auto depth = static_cast<uchar>(cv_type) & static_cast<uchar>(CV_MAT_DEPTH_MASK);switch (depth) {case CV_8S:return DataType(DataType::DE_INT8);case CV_8U:return DataType(DataType::DE_UINT8);case CV_16S:return DataType(DataType::DE_INT16);case CV_16U:return DataType(DataType::DE_UINT16);case CV_32S:return DataType(DataType::DE_INT32);case CV_16F:return DataType(DataType::DE_FLOAT16);case CV_32F:return DataType(DataType::DE_FLOAT32);case CV_64F:return DataType(DataType::DE_FLOAT64);default:MS_LOG(ERROR) << "Cannot convert from OpenCV type, unknown CV type. Unknown data type is returned!";return DataType(DataType::DE_UNKNOWN);}}#endif// 根据不同的type_str对类型进行赋值。DataType::DataType(const std::string &type_str) {if (type_str == "bool")type_ = DE_BOOL;else if (type_str == "int8")type_ = DE_INT8;else if (type_str == "uint8")type_ = DE_UINT8;else if (type_str == "int16")type_ = DE_INT16;else if (type_str == "uint16")type_ = DE_UINT16;else if (type_str == "int32")type_ = DE_INT32;else if (type_str == "uint32")type_ = DE_UINT32;else if (type_str == "int64")type_ = DE_INT64;else if (type_str == "uint64")type_ = DE_UINT64;else if (type_str == "float16")type_ = DE_FLOAT16;else if (type_str == "float32")type_ = DE_FLOAT32;else if (type_str == "float64")type_ = DE_FLOAT64;else if (type_str == "string")type_ = DE_STRING;elsetype_ = DE_UNKNOWN;}// 获取数据类型的名称(字符串类型来表示),成功就返回数据名。失败则返回unknownstd::string DataType::ToString() const {if (type_ < DataType::NUM_OF_TYPES)return kTypeInfo[type_].name_;elsereturn "unknown";}/* 若是python环境下 则把数据转化成python能支持的数据类型若失败则返回(无法从numpy类型转换。返回未知数据类型!)*/#ifdef ENABLE_PYTHONDataType DataType::FromNpArray(const py::array &arr) {if (py::isinstance<py::array_t<bool>>(arr)) {return DataType(DataType::DE_BOOL);} else if (py::isinstance<py::array_t<std::int8_t>>(arr)) {return DataType(DataType::DE_INT8);} else if (py::isinstance<py::array_t<std::uint8_t>>(arr)) {return DataType(DataType::DE_UINT8);} else if (py::isinstance<py::array_t<std::int16_t>>(arr)) {return DataType(DataType::DE_INT16);} else if (py::isinstance<py::array_t<std::uint16_t>>(arr)) {return DataType(DataType::DE_UINT16);} else if (py::isinstance<py::array_t<std::int32_t>>(arr)) {return DataType(DataType::DE_INT32);} else if (py::isinstance<py::array_t<std::uint32_t>>(arr)) {return DataType(DataType::DE_UINT32);} else if (py::isinstance<py::array_t<std::int64_t>>(arr)) {return DataType(DataType::DE_INT64);} else if (py::isinstance<py::array_t<std::uint64_t>>(arr)) {return DataType(DataType::DE_UINT64);} else if (py::isinstance<py::array_t<float16>>(arr)) {return DataType(DataType::DE_FLOAT16);} else if (py::isinstance<py::array_t<std::float_t>>(arr)) {return DataType(DataType::DE_FLOAT32);} else if (py::isinstance<py::array_t<std::double_t>>(arr)) {return DataType(DataType::DE_FLOAT64);} else if (arr.dtype().kind() == 'S' || arr.dtype().kind() == 'U') {return DataType(DataType::DE_STRING);} else {MS_LOG(ERROR) << "Cannot convert from numpy type. Unknown data type is returned!";return DataType(DataType::DE_UNKNOWN);}}// 获取python绑定格式std::string DataType::GetPybindFormat() const {std::string res;if (type_ < DataType::NUM_OF_TYPES) {res = kTypeInfo[type_].pybindFormatDescriptor_;}if (res.empty()) {MS_LOG(ERROR) << "Cannot convert from data type to pybind format descriptor!";}return res;}#endif} // namespace dataset} // namespace mindspore
  • [活动体验] 关于*/minddata/dataset/core/cv_tensor.cc的注释
    关于张量操作的一个文件。 tensor是张量,本质上是一个数组,可以类比numpy中的ndarrays.#include "minddata/dataset/core/cv_tensor.h"#include <memory>#include <vector>#include "minddata/dataset/include/dataset/constants.h"#include "minddata/dataset/core/tensor.h"namespace mindspore {namespace dataset {// 获得一个CV张量CVTensor::CVTensor(std::shared_ptr<Tensor> tensor) : Tensor(std::move(*tensor)) {(void)this->MatInit(GetMutableBuffer(), shape_, type_, &mat_);}// 创建一个空的张量Status CVTensor::CreateEmpty(const TensorShape &shape, DataType type, CVTensorPtr *out) {const CVTensorAlloc *alloc = GlobalContext::Instance()->cv_tensor_allocator();*out = std::allocate_shared<CVTensor>(*alloc, shape, type);int64_t byte_size = (*out)->SizeInBytes();// Don't allocate if we have a tensor with no elements.if (byte_size != 0) {RETURN_IF_NOT_OK((*out)->AllocateBuffer(byte_size));}return (*out)->MatInit((*out)->GetMutableBuffer(), (*out)->shape_, (*out)->type_, &(*out)->mat_);}// 创建一个Mat对象,若不成功则创建一个内存块;若成功则返回OKStatus CVTensor::CreateFromMat(const cv::Mat &mat, CVTensorPtr *out) {TensorPtr out_tensor;cv::Mat mat_local = mat;// 如果输入Mat的内存不连续,请将其复制到一个内存块if (!mat.isContinuous()) mat_local = mat.clone();TensorShape shape(mat.size, mat_local.type());DataType type = DataType::FromCVType(mat_local.type());RETURN_IF_NOT_OK(CreateFromMemory(shape, type, mat_local.data, &out_tensor));*out = AsCVTensor(out_tensor);return Status::OK();}// 这个函数用来判断是否为有效图像,是通过shape.Rank()来判断,进而生成一个2元数组返回。std::pair<std::array<int, 2>, int> CVTensor::IsValidImage(const TensorShape &shape, const DataType &type) {std::array<int, 2> size = {1, 1};if (shape.Rank() <= 2 || (shape.Rank() == 3 && shape[2] <= CV_CN_MAX)) {uint8_t ch = 1;if (shape.Rank() == 3) {ch = static_cast<uint8_t>(shape[2]);}if (shape.Rank() > 0) size[0] = static_cast<int>(shape[0]);if (shape.Rank() > 1) size[1] = static_cast<int>(shape[1]);if (type.AsCVType() == kCVInvalidType) return std::make_pair(size, -1);int cv_type = CV_MAKETYPE(type.AsCVType(), ch);return std::make_pair(size, cv_type);}return std::make_pair(size, -1);}// 这里功能是给一个张量来分配一个共享的指针,一个地址。std::shared_ptr<CVTensor> CVTensor::AsCVTensor(std::shared_ptr<Tensor> t) {std::shared_ptr<CVTensor> cv_t = std::dynamic_pointer_cast<CVTensor>(t);if (cv_t != nullptr) {return cv_t;} else {const CVTensorAlloc *alloc = GlobalContext::Instance()->cv_tensor_allocator();return std::allocate_shared<CVTensor>(*alloc, t);}}// 初始化Mat,以及通过shape.Rank()来判断是否创建成功。成功则返回OK。Status CVTensor::MatInit(uchar *data, const TensorShape &shape, const DataType &type, cv::Mat *mat) {std::pair<std::array<int, 2>, int> cv_shape_type = IsValidImage(shape, type);if (cv_shape_type.second == -1) {std::vector<dsize_t> sizes = shape.AsVector();std::vector<int> sizes32(sizes.begin(), sizes.end()); // 将long转换为int以便与OpenCV一起使用if (static_cast<int>(shape.Rank()) != shape.Rank()) {RETURN_STATUS_UNEXPECTED("Error in creating CV mat. Wrong shape.");//返回创建CV mat时出错。shape不对。}uint8_t cv_type = type.AsCVType();if (cv_type == kCVInvalidType) {RETURN_STATUS_UNEXPECTED("Error in creating CV mat. Invalid type.");//无效类型出错。}*mat = cv::Mat(static_cast<int>(shape.Rank()), &sizes32[0], cv_type, data);} else {*mat = cv::Mat(2, &(cv_shape_type.first[0]), cv_shape_type.second, data);}return Status::OK();}// 重塑shapeStatus CVTensor::Reshape(const TensorShape &shape) {RETURN_IF_NOT_OK(Tensor::Reshape(shape));RETURN_IF_NOT_OK(this->MatInit(GetMutableBuffer(), shape_, type_, &mat_));return Status::OK();}// 扩展尺寸,增加张量的维度Status CVTensor::ExpandDim(const dsize_t &axis) {RETURN_IF_NOT_OK(Tensor::ExpandDim(axis));RETURN_IF_NOT_OK(this->MatInit(GetMutableBuffer(), shape_, type_, &mat_));return Status::OK();}// 挤压void CVTensor::Squeeze() {Tensor::Squeeze();(void)this->MatInit(GetMutableBuffer(), shape_, type_, &mat_);}// 索引处的MatStatus CVTensor::MatAtIndex(const std::vector<dsize_t> &index, cv::Mat *mat) {uchar *start = nullptr;TensorShape remaining({-1});RETURN_IF_NOT_OK(this->StartAddrOfIndex(index, &start, &remaining));RETURN_IF_NOT_OK(this->MatInit(start, remaining, type_, mat));return Status::OK();}} // namespace dataset} // namespace mindspore
  • [算子编译] 【众智】【ST测试】数据类型不支持
    【功能模块】MatrixSolve算子,进行mindspore  CPU迁移后的st测试【操作步骤&问题现象】1、这个输入类型不支持的错误,我看了CPU注册文件里面是支持的,这是什么问题?【截图信息】
  • [新手课堂] python数据类型转换和常见运算符
    一、python数据类型转换        要了解python中数据类型转换。        首先,我们需要知道type()这个东西,它可以帮助我们查看变量的数据类型。        它的()里放的就是你要查看的变量的变量名。        然后就是怎么转换数据类型了        在python中,数据类型的转换其实很简单;        要转换成整型,就是------int()        要转换成浮点型,就是-----float()        要转换成字符型,就是-----str()        ()里依然是变量名,还有么有其他的方法?作者也暂时不知道,dog.jpg二、python的常见运算符        咱们先设个 X 和 Y  吧,这样比较好举例           算数运算符:             加:X+Y        减:X-Y        乘:X*Y        乘方:X**Y        除法要特别说一下,在数学运算中,除法的公式是------X/Y=A---B(X除以Y等于A余B,注这里这个除发说的不对的话,给我留个言吧)        在python中        X/Y        表示 X除Y(在c中这个可是整除,千万别搞错了)        X//Y        表示X整除Y(这个就相当于求上面那个的A)        X%Y        表示X对Y求余(这个相当于求B)比较运算符:        大于:X>Y        小于:X<Y        等于:X==Y        大于等于:X>=Y        小于等于:X<=Y        不等于:X!=Y        注:这里这个比较出来的值,返回的是boolean类型的哟(也就是True或False)!!!逻辑运算符:        和:X and Y        或:X or Y        非:X not Y         (这其实就是按着英语来的,不会有人连这三个单词都看不懂吧,不会吧不会吧!dog.jpg)附值运算符:        X=Y        将Y符给X        X+=Y        相当于X=X+Y        将X+Y符给X                  -=         *=         /=         **=(这四个和上面是一个意思,我就不多说了。)(其实是懒得打字了=。=)三、结尾        python中的数据类型转换和常见的运算符大致就是这么些,有哪些看不明白的可以在评论区回复我,我看到的话能回答的会尽力帮大家解答。这一篇大概就是这么多了,下一篇就讲讲程序控制流程。
  • [活动体验] cpu\update_cache_cpu_kernel.cc代码标注
    # mindspore\mindspore\ccsrc\backend\kernel_compiler\cpu\update_cache_cpu_kernel.cc代码标注 ```c++ /** * 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. */ //导入自定义的库 #include "backend/kernel_compiler/cpu/update_cache_cpu_kernel.h" #include #include "runtime/device/cpu/cpu_device_address.h" //声明双重空间 namespace mindspore { namespace kernel { //初始化内核 void UpdateCacheCPUKernel::InitKernel(const CNodePtr &kernel_node) { MS_EXCEPTION_IF_NULL(kernel_node);//判断节点是否为空 node_wpt_ = kernel_node; input_x_dtype_ = AnfAlgo::GetPrevNodeOutputInferDataType(kernel_node, 0);//获取x的数据类型 indices_dtype_ = AnfAlgo::GetPrevNodeOutputInferDataType(kernel_node, 1);//获取y的数据类型 if (input_x_dtype_ == kNumberTypeFloat32 || input_x_dtype_ == kNumberTypeInt32) { input_x_dtype_size_ = 4; } else if (input_x_dtype_ == kNumberTypeFloat64 || input_x_dtype_ == kNumberTypeInt64) { input_x_dtype_size_ = 8; } else {//错误日志:输入值x只支持 float32, float64, int32, int64的数据类型 MS_LOG(EXCEPTION) "input_x dtype only support float32, float64, int32, int64"; } } //检查数据类型 bool UpdateCacheCPUKernel::Launch(const std::vector &inputs, const std::vector & /*workspace*/, const std::vector &outputs) { if (indices_dtype_ == kNumberTypeInt32) { LaunchKernel(inputs, outputs); } else if (indices_dtype_ == kNumberTypeInt64) { LaunchKernel(inputs, outputs); } else { MS_LOG(ERROR) "indices dtype only support int32, int64"; return false; } return true; } //检查内核 template void UpdateCacheCPUKernel::LaunchKernel(const std::vector &inputs, const std::vector &outputs) { auto node_ = node_wpt_.lock();//获取节点 if (!node_) {//节点工作空间失效 MS_LOG(EXCEPTION) "node_wpt_ is expired."; } auto indices_shape = AnfAlgo::GetPrevNodeOutputInferShape(node_, 1); auto update_shape = AnfAlgo::GetPrevNodeOutputInferShape(node_, 2); batch_size_ = 1;//初始化变量 for (size_t i = 0; i indices_shape.size(); ++i) {//循环遍历获取批处理大小 batch_size_ *= indices_shape[i]; } MS_LOG(INFO) "UpdateCache batch_size:" batch_size_;//更新批处理大小 update_size_ = 1; for (size_t i = 0; i update_shape.size(); ++i) { update_size_ *= update_shape[i]; } update_length_ = update_shape[1]; //类型转换 char *input_x = reinterpret_cast(inputs[0]->addr); T *indices = reinterpret_cast(inputs[1]->addr); char *update = reinterpret_cast(inputs[2]->addr); max_num_ = *reinterpret_cast(inputs[3]->addr); size_t one_length_size = input_x_dtype_size_ * update_length_; auto max_size = inputs[0]->size; for (size_t i = 0; i batch_size_; ++i) { if (indices[i] 0 || indices[i] >= max_num_) continue; char *tmp = update + i * one_length_size; if (indices[i] * one_length_size + one_length_size = max_size) { int ret = memcpy_s(input_x + indices[i] * one_length_size, max_size - indices[i] * one_length_size, tmp, one_length_size); if (ret != 0) { MS_LOG(EXCEPTION) "memcpy_s error, errorno" ret; } } else {//字符串拷贝c MS_LOG(EXCEPTION) "Memcpy out of size"; } } } } // namespace kernel } // namespace mindspore ```
  • [活动体验] cpu\unsorted_segment_sum_cpu_kernel.cc代码标注
    # mindspore\mindspore\ccsrc\backend\kernel_compiler\cpu\unsorted_segment_sum_cpu_kernel.cc代码标注 ```c++ /** * 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. */ //导入自定义的库 #include "backend/kernel_compiler/cpu/unsorted_segment_sum_cpu_kernel.h" //导入系统自带的库 #include #include "runtime/device/cpu/cpu_device_address.h" //导入自定义的库 #include "common/thread_pool.h" //双重空间 namespace mindspore { namespace kernel { //初始化内核 void UnsortedSegmentSumCPUKernel::InitKernel(const CNodePtr &kernel_node) { MS_EXCEPTION_IF_NULL(kernel_node);//判断内核是否为空 size_t input_num = AnfAlgo::GetInputTensorNum(kernel_node);//获取输入值个数 if (input_num != 2) {//如果输入值个数不为2,则记录错误日志:输入值个数是...,但是内核需要2个输入 MS_LOG(EXCEPTION) "Input number is " input_num ", but UnsortedSegmentSum needs 2 input."; } size_t output_num = AnfAlgo::GetOutputTensorNum(kernel_node); if (output_num != 1) {//如果输出值个数不为2,则记录错误日志:输出值个数是...,但是内核需要1个输出 MS_LOG(EXCEPTION) "Output number is " output_num ", but UnsortedSegmentSum needs 1 output."; } dtype_ = AnfAlgo::GetPrevNodeOutputInferDataType(kernel_node, 0);//获取数据类型 segment_ids_dtype_ = AnfAlgo::GetPrevNodeOutputInferDataType(kernel_node, 1);//获取片段数据类型 auto input_shape = AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, 0);//获取输入值形状 auto segment_ids_shape = AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, 1); auto output_shape = AnfAlgo::GetOutputInferShape(kernel_node, 0); for (size_t i = 0; i input_shape.size(); ++i) { unit_num_ *= input_shape[i]; if (i >= segment_ids_shape.size()) { input_dim1_ *= input_shape[i]; } } output_dim0_ = output_shape[0]; for (size_t j = 1; j output_shape.size(); j++) { output_dim1_ *= output_shape[j]; } } //检查数据类型 bool UnsortedSegmentSumCPUKernel::Launch(const std::vector &inputs, const std::vector & /*workspace*/, const std::vector &outputs) { bool ret{true}; if (dtype_ == kNumberTypeInt32 && segment_ids_dtype_ == kNumberTypeInt32) { ret = LaunchKernel(inputs, outputs); } else if (dtype_ == kNumberTypeFloat32 && segment_ids_dtype_ == kNumberTypeInt32) { ret = LaunchKernel(inputs, outputs); } else if (dtype_ == kNumberTypeInt32 && segment_ids_dtype_ == kNumberTypeInt64) { ret = LaunchKernel(inputs, outputs); } else if (dtype_ == kNumberTypeFloat32 && segment_ids_dtype_ == kNumberTypeInt64) { ret = LaunchKernel(inputs, outputs); } else {//错误日志:输入值x仅支持int32 and float32, indices int32 and int64的数据类型 MS_LOG(ERROR) "Only support input_x int32 and float32, indices int32 and int64"; return false; } return ret; } //检查内核 template bool UnsortedSegmentSumCPUKernel::LaunchKernel(const std::vector &inputs, const std::vector &outputs) { //类型转换 S *input_addr = reinterpret_cast(inputs[0]->addr); T *indices_addr = reinterpret_cast(inputs[1]->addr); S *output_addr = reinterpret_cast(outputs[0]->addr); auto ret = memset_s(output_addr, outputs[0]->size, 0, outputs[0]->size); if (ret != EOK) {//错误日志:输出增幅函数s MS_LOG(ERROR) "Output buff memset fail. ret:" ret; return false; } for (size_t i = 0; i unit_num_; ++i) { size_t j = i / input_dim1_; size_t k = i % input_dim1_; T index = indices_addr[j]; if (index 0 || index >= SizeToInt(output_dim0_)) { continue; } size_t output_index = index * output_dim1_ + k; output_addr[output_index] += input_addr[i]; } return true; } } // namespace kernel } // namespace mindspore ```
  • [活动体验] lite\tools\benchmark\benchmark.cc&quot;注释6
    ** "\lite\tools\benchmark\benchmark.cc"注释6** ================================= ```python //转储 MS 张量函数 std::string DumpMSTensor(tensor::MSTensor *tensor) { if (tensor == nullptr) {//判断输入的tensor是否为null return "Tensor is nullptr"; } 创建字符流 std::ostringstream oss; oss " DataType: " tensor->data_type();//存进数据type oss " Shape:"; for (auto &dim : tensor->shape()) {//遍历shape oss " " dim; } oss std::endl " Data:"; switch (tensor->data_type()) {//对不同的数据类型进行不同的存储方式 case kNumberTypeFloat32: { oss DataToString(tensor->data(), tensor->ElementsNum()); } break; case kNumberTypeFloat16: { oss DataToString(tensor->data(), tensor->ElementsNum()); } break; case kNumberTypeInt32: { oss DataToString(tensor->data(), tensor->ElementsNum()); } break; case kNumberTypeInt16: { oss DataToString(tensor->data(), tensor->ElementsNum()); } break; case kNumberTypeInt8: { oss DataToString(tensor->data(), tensor->ElementsNum()); } break; default://输出不支持的数据类型错误 oss "Unsupported data type to print"; break; } return oss.str();//返回字符流 } //生成输出文件名函数 std::string GenerateOutputFileName(tensor::MSTensor *tensor, const std::string &op_name, const std::string &file_type, const size_t &idx) { std::string file_name = op_name; //寻找文件中'/'的位置 auto pos = file_name.find_first_of('/'); while (pos != std::string::npos) { file_name.replace(pos, 1, ".");//replace文件名 pos = file_name.find_first_of('/'); } file_name += "_" + file_type + "_" + std::to_string(idx) + "_shape_";//格式化文件名 for (const auto &dim : tensor->shape()) {// file_name += std::to_string(dim) + "_";//储存filename } //将type格式化进filename if (TYPE_ID_MAP.find(tensor->data_type()) != TYPE_ID_MAP.end()) { file_name += TYPE_ID_MAP.at(tensor->data_type()); } //定义张量格式 auto tensor_format = static_cast(tensor)->format(); //将张量格式化进filename if (TENSOR_FORMAT_MAP.find(tensor_format) != TENSOR_FORMAT_MAP.end()) { file_name += "_" + TENSOR_FORMAT_MAP.at(tensor_format) + ".bin"; } //完成文件名的创建并返回 return file_name; } } // namespace //初始化打印张量数据回调参数 int Benchmark::InitPrintTensorDataCallbackParameter() { // 回调前 before_call_back_ = [&](const std::vector &before_inputs, const std::vector &before_outputs, const CallBackParam &call_param) { return true; }; // 回调后 after_call_back_ = [&](const std::vector &after_inputs, const std::vector &after_outputs, const CallBackParam &call_param) { std::cout "================================================================" std::endl; std::cout call_param.node_name " inputs : " std::endl;//输出回调参数的信息 //输出inputs的所有的tensor for (auto ms_tensor : after_inputs) { std::cout DumpMSTensor(ms_tensor) std::endl; } std::cout "----------------------------------------------------------------" std::endl; std::cout call_param.node_name " outputs : " std::endl; //输出output的所有tensor for (const auto ms_tensor : after_outputs) { std::cout DumpMSTensor(ms_tensor) std::endl; } std::cout "================================================================" std::endl; return true; }; return RET_OK; } //初始化转储张量数据回调参数 int Benchmark::InitDumpTensorDataCallbackParameter() { // before callback before_call_back_ = [&](const std::vector &before_inputs, const std::vector &before_outputs, const CallBackParam &call_param) { //定义转储模式 auto dump_mode = dump_cfg_json_[dump::kSettings][dump::kMode].get(); auto input_output_mode = dump_cfg_json_[dump::kSettings][dump::kInputOutput].get();//输入输出模式 auto kernels = dump_cfg_json_[dump::kSettings][dump::kKernels].get>(); //判断转储模式以及内核等是否符合标准 if (dump_mode == 0 || std::find(kernels.begin(), kernels.end(), call_param.node_name) != kernels.end()) { if (input_output_mode == 0 || input_output_mode == 1) { for (size_t i = 0; i before_inputs.size(); i++) {//对文件数据进行遍历读写 auto ms_tensor = before_inputs.at(i); auto file_name = GenerateOutputFileName(ms_tensor, call_param.node_name, "input", i); auto abs_file_path = dump_file_output_dir_ + "/" + file_name; if (WriteToBin(abs_file_path, ms_tensor->data(), ms_tensor->Size()) != RET_OK) { // 将数据保存进文件 MS_LOG(ERROR) "write tensor data to file failed.";//判断是否保存成功 return false; } } } } return true; }; // after callback after_call_back_ = [&](const std::vector &after_inputs, const std::vector &after_outputs, const CallBackParam &call_param) { auto dump_mode = dump_cfg_json_[dump::kSettings][dump::kMode].get();//获取回调后的性能 auto input_output_mode = dump_cfg_json_[dump::kSettings][dump::kInputOutput].get(); auto kernels = dump_cfg_json_[dump::kSettings][dump::kKernels].get>(); if (dump_mode == 0 || std::find(kernels.begin(), kernels.end(), call_param.node_name) != kernels.end()) {//判断性能是否符合标准 if (input_output_mode == 0 || input_output_mode == 2) { for (size_t i = 0; i after_outputs.size(); i++) { auto ms_tensor = after_outputs.at(i);//获取性能数据 auto file_name = GenerateOutputFileName(ms_tensor, call_param.node_name, "output", i); auto abs_file_path = dump_file_output_dir_ + "/" + file_name; if (WriteToBin(abs_file_path, ms_tensor->data(), ms_tensor->Size()) != RET_OK) { // 保存进文件 MS_LOG(ERROR) "write tensor data to file failed.";//判断是否保存成功 return false; } } } } return true; }; return RET_OK; } ```
  • [活动体验] cpu\transpose_cpu_kernel.cc代码标注
    # mindspore\mindspore\ccsrc\backend\kernel_compiler\cpu\transpose_cpu_kernel.cc代码标注 ```c++ /** * 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 "backend/kernel_compiler/cpu/transpose_cpu_kernel.h" //导入系统自带的库 #include #include //导入自定义的库 #include "runtime/device/cpu/cpu_device_address.h" namespace mindspore {//声明一个空间 namespace kernel {//空间嵌套 //初始化内核 void TransposeCPUFwdKernel::InitKernel(const CNodePtr &kernel_node) { MS_EXCEPTION_IF_NULL(kernel_node);//判断内核是否为空 input_shape_ = AnfAlgo::GetInputDeviceShape(kernel_node, 0);//获取输入值的形状 output_shape_ = AnfAlgo::GetOutputDeviceShape(kernel_node, 0);//获取输出值的形状 auto tmp = AnfAlgo::GetNodeAttr>(kernel_node, "perm");//获取节点地址 axes_ = {tmp.begin(), tmp.end()}; dtype_ = AnfAlgo ::GetPrevNodeOutputDeviceDataType(kernel_node, 0);//获取节点输出值数据类型 if (dtype_ == kTypeUnknown) { dtype_ = AnfAlgo::GetPrevNodeOutputInferDataType(kernel_node, 0); } launch_map_[kNumberTypeInt8] = &TransposeCPUFwdKernel::LaunchKernel; launch_map_[kNumberTypeInt16] = &TransposeCPUFwdKernel::LaunchKernel; launch_map_[kNumberTypeInt32] = &TransposeCPUFwdKernel::LaunchKernel; launch_map_[kNumberTypeInt64] = &TransposeCPUFwdKernel::LaunchKernel; launch_map_[kNumberTypeUInt8] = &TransposeCPUFwdKernel::LaunchKernel; launch_map_[kNumberTypeUInt16] = &TransposeCPUFwdKernel::LaunchKernel; launch_map_[kNumberTypeUInt32] = &TransposeCPUFwdKernel::LaunchKernel; launch_map_[kNumberTypeUInt64] = &TransposeCPUFwdKernel::LaunchKernel; launch_map_[kNumberTypeFloat32] = &TransposeCPUFwdKernel::LaunchKernel; launch_map_[kNumberTypeBool] = &TransposeCPUFwdKernel::LaunchKernel; auto iter = launch_map_.find(dtype_);//获取数据类型 if (iter != launch_map_.end()) { launch_func_ = iter->second; } else {//若输入数据类型不在数据类型图中,则记录错误日志:输入数据类型:...Transpose内核CPU不支持此类数据类型 MS_LOG(EXCEPTION) "Input data type: " dtype_ "is not supported for Transpose kernel on CPU."; } } //检查输入输出值 bool TransposeCPUFwdKernel::Launch(const std::vector &inputs, const std::vector & /*workspace*/, const std::vector &outputs) { launch_func_(this, inputs, outputs); return true; } //检查内核参数 template void TransposeCPUFwdKernel::LaunchKernel(const std::vector &inputs, const std::vector &outputs) { //类型转换 auto input_addr = reinterpret_cast(inputs[0]->addr);//获取输入值地址并进行类型转换 auto output_addr = reinterpret_cast(outputs[0]->addr);//获取输出值地址并进行类型转换 size_t size = IntToSize(inputs[0]->size / sizeof(T)); TransposeIterator base_iter(output_shape_, axes_, input_shape_); auto task = [&base_iter, input_addr, output_addr](size_t start, size_t end) {//h auto iter = base_iter; iter.SetPos(start); for (size_t i = start; i end; ++i) { output_addr[i] = input_addr[iter.GetPos()]; iter.GenNextPos(); } }; CPUKernelUtils::ParallelFor(task, size); } } // namespace kernel } // namespace mindspore ```
  • [活动体验] cpu\topk_cpu_kernel.cc代码标注
    # mindspore\mindspore\ccsrc\backend\kernel_compiler\cpu\topk_cpu_kernel.cc代码标注 ```c++ /** * 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. */ //导入系统自带的库 #include #include #include #include //导入自定义的库 #include "backend/kernel_compiler/cpu/topk_cpu_kernel.h" #include "runtime/device/cpu/cpu_device_address.h" namespace mindspore {//声明一个空间 namespace kernel {//空间嵌套 template //检查内核输入输出值 void TopKCPUKernel::LaunchKernel(const std::vector &inputs, const std::vector &outputs) { if (inputs.size() != 2 || outputs.size() != 2) {//TopK内核需要2个输入和2个输出,但获取输入是... MS_LOG(EXCEPTION) "TopK needs 2 inputs and 2 outputs, but get inputs: " inputs.size() "outputs: " outputs.size(); } if (inputs[0]->size != outer_size_ * inner_size_ * sizeof(T)) {//错误的输入数据类型 MS_LOG(EXCEPTION) "Error input data size!"; } if (inputs[1]->size != sizeof(int)) {//输入值k的数据类型必须为int MS_LOG(EXCEPTION) "Input K must be int!"; } //类型转换 auto input = reinterpret_cast(inputs[0]->addr); int k = reinterpret_cast(inputs[1]->addr)[0]; auto output = reinterpret_cast(outputs[0]->addr); auto indices = reinterpret_cast(outputs[1]->addr); if (k 1) {//输入值k必须大于0 MS_LOG(EXCEPTION) "Input k must > 0!"; } int k_num = std::min(inner_size_, k); if (outputs[0]->size != outer_size_ * k_num * sizeof(T)) {//错误的输出值数据类型大小 MS_LOG(EXCEPTION) "Error output data size!"; } for (size_t i = 0; i outer_size_; ++i) { std::vector idx(inner_size_); auto base_input = i * inner_size_; std::iota(idx.begin(), idx.end(), base_input); std::stable_sort(idx.begin(), idx.end(), [&input](size_t index_1, size_t index_2) { return input[index_1] > input[index_2]; }); auto base_output = i * k_num; if (!sorted_) { std::stable_sort(idx.begin(), idx.begin() + k_num); } for (int j = 0; j k_num; ++j) { indices[base_output + j] = idx[j] - base_input; output[base_output + j] = input[idx[j]]; } } } //初始化内核 void TopKCPUKernel::InitKernel(const CNodePtr &kernel_node) { MS_EXCEPTION_IF_NULL(kernel_node); auto x_shape_ = AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, 0);//获取输入值参数形状 for (size_t i = 0; i x_shape_.size() - 1; ++i) { outer_size_ *= x_shape_[i]; } inner_size_ = x_shape_[x_shape_.size() - 1];//获取内层大小 sorted_ = AnfAlgo::GetNodeAttr(kernel_node, "sorted");//排序 dtype_ = AnfAlgo::GetPrevNodeOutputInferDataType(kernel_node, 0);//获取数据类型 } //j bool TopKCPUKernel::Launch(const std::vector &inputs, const std::vector &, const std::vector &outputs) { if (dtype_ == kNumberTypeFloat16) { LaunchKernel(inputs, outputs); } else if (dtype_ == kNumberTypeFloat32) { LaunchKernel(inputs, outputs); } return true; } } // namespace kernel } // namespace mindspore ```
  • [活动体验] cpu\tile_cpu_kernel.cc代码标注
    # mindspore\mindspore\ccsrc\backend\kernel_compiler\cpu\tile_cpu_kernel.cc代码标注 ```c++ /** * 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 "backend/kernel_compiler/cpu/tile_cpu_kernel.h" #include #include "runtime/device/cpu/cpu_device_address.h" namespace mindspore {//声明一个空间 namespace kernel {//空间嵌套 //初始化内核 void TileCPUKernel::InitKernel(const CNodePtr &kernel_node) { CheckParam(kernel_node); x_shape_ = AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, 0);//获取变量的形状 y_shape_ = AnfAlgo::GetOutputInferShape(kernel_node, 0);//获取输出值节点的形状 std::vector multiples_me = AnfAlgo::GetNodeAttr>(kernel_node, "multiples"); (void)std::transform(multiples_me.begin(), multiples_me.end(), std::back_inserter(multiples_), [](const int64_t &value) { return static_cast(value); }); dtype_ = AnfAlgo ::GetPrevNodeOutputDeviceDataType(kernel_node, 0); if (dtype_ == kTypeUnknown) { dtype_ = AnfAlgo::GetPrevNodeOutputInferDataType(kernel_node, 0); } //数据类型图 launch_map_[kNumberTypeInt8] = &TileCPUKernel::LaunchKernel; launch_map_[kNumberTypeInt16] = &TileCPUKernel::LaunchKernel; launch_map_[kNumberTypeInt32] = &TileCPUKernel::LaunchKernel; launch_map_[kNumberTypeInt64] = &TileCPUKernel::LaunchKernel; launch_map_[kNumberTypeUInt8] = &TileCPUKernel::LaunchKernel; launch_map_[kNumberTypeUInt16] = &TileCPUKernel::LaunchKernel; launch_map_[kNumberTypeUInt32] = &TileCPUKernel::LaunchKernel; launch_map_[kNumberTypeUInt64] = &TileCPUKernel::LaunchKernel; launch_map_[kNumberTypeFloat32] = &TileCPUKernel::LaunchKernel; launch_map_[kNumberTypeBool] = &TileCPUKernel::LaunchKernel; auto iter = launch_map_.find(dtype_); if (iter != launch_map_.end()) { launch_func_ = iter->second; } else {//输入的数据类型:...CPU内核不支持这样的数据类型 MS_LOG(EXCEPTION) "Input data type: " dtype_ "is not supported for Tile kernel on CPU."; } } //检查输入输出值 bool TileCPUKernel::Launch(const std::vector &inputs, const std::vector & /*workspace*/, const std::vector &outputs) { launch_func_(this, inputs, outputs); return true; } //j template void TileRecTask(const T *x, T *y, size_t dim, size_t *offset, std::vector *pos, const std::vector &multiples, const std::vector &cargo_x, const std::vector &cargo_y, const std::vector &x_shape) { if (dim == x_shape.size()) { return; } for (size_t i = 0; i x_shape[dim]; ++i) { (*pos)[dim] = i; if (dim == x_shape.size() - 1) { size_t x_offset = 0; for (size_t j = 0; j (*pos).size(); ++j) { x_offset += (*pos)[j] * cargo_x[j]; } memcpy_s(y + *offset, sizeof(T), x + x_offset, sizeof(T)); *offset += 1; continue; } TileRecTask(x, y, dim + 1, offset, pos, multiples, cargo_x, cargo_y, x_shape); } size_t dim_size = cargo_y[dim] * sizeof(T); for (int m = 0; m multiples[dim] - 1; ++m) { size_t y_offset = *offset - cargo_y[dim]; memcpy_s(y + *offset, dim_size, y + y_offset, dim_size); *offset += cargo_y[dim]; } } //检查内核 template void TileCPUKernel::LaunchKernel(const std::vector &inputs, const std::vector &outputs) { //类型转换 auto x_addr = reinterpret_cast(inputs[0]->addr); auto y_addr = reinterpret_cast(outputs[0]->addr); size_t ones = multiples_.size() - x_shape_.size(); if (ones > 0) { for (size_t i = 0; i ones; ++i) { x_shape_.insert(x_shape_.begin(), 1); } } int d = multiples_.size(); std::vector pos(d, 0); std::vector cargo_x(d, 1); std::vector cargo_y = x_shape_; for (int i = d - 2; i >= 0; --i) {//遍历数组 cargo_x[i] = x_shape_[i + 1] * cargo_x[i + 1]; cargo_y[i] *= cargo_y[i + 1] * multiples_[i + 1]; } size_t offset = 0; TileRecTask(x_addr, y_addr, 0, &offset, &pos, multiples_, cargo_x, cargo_y, x_shape_); } //检查输入输出参数个数 void TileCPUKernel::CheckParam(const CNodePtr &kernel_node) { size_t input_num = AnfAlgo::GetInputTensorNum(kernel_node); if (input_num != 1) {//输入值个数是...但是内核需要的是一个输入 MS_LOG(EXCEPTION) "Input number is " input_num ", but TileCPUKernel needs 1 input."; } size_t output_num = AnfAlgo::GetOutputTensorNum(kernel_node); if (output_num != 1) {//输出值个数是...但是内核需要的是一个输出 MS_LOG(EXCEPTION) "Output number is " output_num ", but TileCPUKernel needs 1 output."; } } } // namespace kernel } // namespace mindspore ```
  • [活动体验] cpu\layer_norm_grad_cpu_kernel.cc代码标注
    # mindspore\mindspore\ccsrc\backend\kernel_compiler\cpu\layer_norm_grad_cpu_kernel.cc代码标注 ```c++ /** * 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 "backend/kernel_compiler/cpu/layer_norm_grad_cpu_kernel.h" #include "backend/kernel_compiler/common_utils.h" #include "runtime/device/cpu/cpu_device_address.h" #include "common/thread_pool.h" namespace mindspore {//声明一个空间 namespace kernel {//空间嵌套 void LayerNormGradCPUKernel::InitKernel(const CNodePtr &kernel_node) {//初始化内核 CheckParam(kernel_node);//检查参数 dtype_ = AnfAlgo::GetPrevNodeOutputInferDataType(kernel_node, 0);//获取数据类型 std::vector x_shape = AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, 0);//获取参数x的形状 auto begin_norm_axis = AnfAlgo::GetNodeAttr(kernel_node, "begin_norm_axis");//获取begin_norm_axis节点地址 auto begin_params_axis = AnfAlgo::GetNodeAttr(kernel_node, "begin_params_axis");//获取begin_params_axis节点地址 if (begin_norm_axis 0) { begin_norm_axis += x_shape.size(); } if (begin_params_axis 0) { begin_params_axis += x_shape.size(); } //计算代码块大小 for (size_t i = 0; i IntToSize(begin_norm_axis); i++) { block_num_ *= x_shape[i]; } for (size_t i = IntToSize(begin_norm_axis); i x_shape.size(); i++) { block_size_ *= x_shape[i]; } //计算参数的数量 for (size_t i = 0; i IntToSize(begin_params_axis); i++) { param_size_ *= x_shape[i]; } for (size_t i = begin_params_axis; i x_shape.size(); i++) { param_num_ *= x_shape[i]; } if (block_num_ = 0 || block_size_ = 0) { MS_LOG(EXCEPTION) "LayerNormGradCPUKernel input shape error, input shape: " x_shape; } } //核对数据类型 bool LayerNormGradCPUKernel::Launch(const std::vector &inputs, const std::vector &workspace, const std::vector &outputs) { if (dtype_ == kNumberTypeFloat16) { LaunchKernel(inputs, workspace, outputs); } else if (dtype_ == kNumberTypeFloat32 || dtype_ == kNumberTypeFloat64) { LaunchKernel(inputs, workspace, outputs); } else {//输入数据类型只支持float16, float32, float64 MS_LOG(EXCEPTION) "input dtype only support float16, float32, float64"; } return true; } template void LayerNormGradCPUKernel::LaunchKernel(const std::vector &inputs, const std::vector &workspace, const std::vector &outputs) { //转换参数类型 auto x = reinterpret_cast(inputs[0]->addr); auto dy = reinterpret_cast(inputs[1]->addr); auto var = reinterpret_cast(inputs[2]->addr); auto mean = reinterpret_cast(inputs[3]->addr); auto gamma = reinterpret_cast(inputs[4]->addr); auto dx = reinterpret_cast(outputs[0]->addr); auto dg = reinterpret_cast(outputs[1]->addr); auto db = reinterpret_cast(outputs[2]->addr); size_t thread_num = common::ThreadPool::GetInstance().GetSyncRunThreadNum();//获取线程数量 auto thread_num1 = param_num_ thread_num ? param_num_ : thread_num;//线程数量1取thread_num 和 param_num_小的一个 std::vector tasks1; tasks1.reserve(thread_num1); auto thread_num2 = block_num_ thread_num ? block_num_ : thread_num;//线程数量1取thread_num 和 block_num_小的一个 std::vector tasks2; tasks2.reserve(thread_num2); auto task1 = [&](size_t start, size_t end) { for (size_t c = 0; c ceil(static_cast(param_num_) / thread_num1); ++c) { if (c * thread_num1 + start >= param_num_) { continue; } size_t param_index = c * thread_num1 + start; T dgamma = (T)0.0;//初始化变量 T dbeta = (T)0.0;//初始化变量 for (size_t j = param_index; j param_size_ * param_num_; j += param_num_) { auto norm_shift = static_cast(j / block_size_); dgamma += dy[j] * (T)std::pow(static_cast(var[norm_shift]) + eps_, -0.5) * (x[j] - mean[norm_shift]); dbeta += dy[j]; } dg[param_index] = dgamma; db[param_index] = dbeta; } }; auto task2 = [&](size_t start, size_t end) { for (size_t c = 0; c ceil(static_cast(block_num_) / thread_num2); ++c) { if (c * thread_num2 + start >= block_num_) { continue; } size_t block_index = c * thread_num2 + start; T sum1 = (T)0.0; T sum2 = (T)0.0; T sum3 = (T)0.0; for (size_t j = block_index * block_size_; j (block_index + 1) * block_size_; ++j) { auto param_shift = j % param_num_; auto norm_shift = static_cast(j / block_size_); auto dxm = x[j] - mean[norm_shift]; auto dyg = dy[j] * gamma[param_shift]; sum1 += (T)(-0.5) * dyg * dxm * (T)std::pow(static_cast(var[norm_shift]) + eps_, -1.5); sum2 += dyg; sum3 += (T)(-2.0) * dxm; } for (size_t j = block_index * block_size_; j (block_index + 1) * block_size_; ++j) { auto param_shift = j % param_num_; auto norm_shift = static_cast(j / block_size_); auto var_sqrt = (T)std::pow(static_cast(var[norm_shift]) + eps_, -0.5); auto dx1 = dy[j] * gamma[param_shift] * var_sqrt; auto dx2 = sum1 * (T)2.0 / block_size_ * (x[j] - mean[norm_shift]); auto dx3 = ((T)(-1.0) * var_sqrt * sum2 + ((T)1.0 / block_size_) * sum1 * sum3) * ((T)1.0 / block_size_); dx[j] = dx1 + dx2 + dx3; } } }; for (size_t i = 0; i thread_num1; ++i) { auto block = [&, i]() { task1(i, i + 1); return common::SUCCESS; }; tasks1.emplace_back(block); } common::ThreadPool::GetInstance().SyncRun(tasks1); for (size_t i = 0; i thread_num2; ++i) { auto block = [&, i]() { task2(i, i + 1); return common::SUCCESS; }; tasks2.emplace_back(block);//原地创建一个对象block } common::ThreadPool::GetInstance().SyncRun(tasks2); } void LayerNormGradCPUKernel::CheckParam(const CNodePtr &kernel_node) { size_t input_num = AnfAlgo::GetInputTensorNum(kernel_node); if (input_num != 5) {//LayerNormCPUKernel需要5个输入,但是获取的输入值数量是. MS_LOG(EXCEPTION) "LayerNormGradCPUKernel needs 5 inputs, but gets " input_num; } size_t output_num = AnfAlgo::GetOutputTensorNum(kernel_node); if (output_num != 3) {//LayerNormCPUKernel期待3个输出,但是获取的输c值数量是... MS_LOG(EXCEPTION) "LayerNormGradCPUKernel expects 3 output, but gets" output_num; } } } // namespace kernel } // namespace mindspore ```