mindspore2022/mindspore/ccsrc/kernel/common_utils.h

309 lines
13 KiB
C++

/**
* 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.
*/
#ifndef MINDSPORE_CCSRC_KERNEL_COMMON_UTILS_H_
#define MINDSPORE_CCSRC_KERNEL_COMMON_UTILS_H_
#include <dirent.h>
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <utility>
#include <tuple>
#include <nlohmann/json.hpp>
#include "include/common/utils/utils.h"
#include "kernel/kernel.h"
#include "kernel/oplib/opinfo.h"
#include "kernel/kernel_build_info.h"
#include "ops/base_operator.h"
namespace mindspore {
namespace kernel {
constexpr auto kAkgKernelMeta = "kernel_meta/";
constexpr auto kProcessorAiCore = "aicore";
constexpr auto kProcessorAiCpu = "aicpu";
constexpr auto kProcessorCuda = "cuda";
constexpr auto kProcessorCpu = "cpu";
constexpr auto kProcessorUnknown = "unknown";
constexpr auto kJsonSuffix = ".json";
constexpr auto kInfoSuffix = ".info";
constexpr unsigned int AUTODIFF_COMPILE_OVERTIME = 600;
const std::vector<std::string> support_devices = {"aicore", "aicpu", "cuda"};
// an enum to indicate a vector or matrix alignment direction.
// real_data: [1,2,3] left_align: [1,2,3,0] right_align:[0,1,2,3]
namespace MatrixDiag {
enum Alignment { RIGHT = 0, LEFT = 1 };
static const mindspore::HashMap<std::string, std::pair<MatrixDiag::Alignment, MatrixDiag::Alignment>> AlignmentMap{
{"RIGHT_LEFT", {MatrixDiag::RIGHT, MatrixDiag::LEFT}},
{"LEFT_RIGHT", {MatrixDiag::LEFT, MatrixDiag::RIGHT}},
{"RIGHT_RIGHT", {MatrixDiag::RIGHT, MatrixDiag::RIGHT}},
{"LEFT_LEFT", {MatrixDiag::LEFT, MatrixDiag::LEFT}}};
} // namespace MatrixDiag
struct KernelMetaInfo {
uintptr_t func_stub_;
uint32_t block_dim_;
};
using KernelMetaPtr = std::shared_ptr<KernelMetaInfo>;
class KernelMeta {
public:
KernelMeta() = default;
void Initialize();
std::string Search(const std::string &kernel_name) const;
bool Insert(const std::string &kernel_name, const std::string &kernel_json);
std::string kernel_meta_path() const { return kernel_meta_path_; }
bool initialized() const { return initialized_; }
static KernelMeta *GetInstance() {
static KernelMeta kernel_meta;
return &kernel_meta;
}
~KernelMeta() = default;
private:
bool initialized_ = false;
std::string kernel_meta_path_;
std::unordered_map<std::string, std::string> kernel_meta_map_;
};
class MatrixInfo {
public:
explicit MatrixInfo(size_t max_index, const std::vector<size_t> &matrix_shapes)
: max_index_(max_index), shapes_(matrix_shapes) {
current_indexes_.resize(shapes_.size(), 0);
}
~MatrixInfo() = default;
bool SetIndex(size_t start, size_t end) {
// check data from start to end whether valid.
if (start < min_index || end > max_index_ || start >= end) {
return false;
}
// initial current indexes.
int last_rank = SizeToInt(current_indexes_.size()) - 1;
for (int i = last_rank; start != 0 && i >= 0; --i) {
size_t position = IntToSize(i);
current_indexes_[position] = start % shapes_.at(position);
start = start / shapes_.at(position);
}
return true;
}
std::vector<size_t> IndexIterator() {
if (is_first_iterator_) {
is_first_iterator_ = false;
return current_indexes_;
}
size_t last_rank = current_indexes_.size() - 1;
current_indexes_[last_rank]++;
for (size_t i = last_rank; current_indexes_.at(i) >= shapes_.at(i) && i > 0; --i) {
current_indexes_[i] = 0;
current_indexes_[i - 1] += 1;
}
is_first_iterator_ = false;
return current_indexes_;
}
private:
bool is_first_iterator_{true};
size_t min_index{0};
size_t max_index_{1};
std::vector<size_t> shapes_;
std::vector<size_t> current_indexes_;
};
using MatrixInfoPtr = std::shared_ptr<MatrixInfo>;
std::pair<MatrixDiag::Alignment, MatrixDiag::Alignment> GetAlignments(const std::string &alignment);
int CalDiagOffset(int diag_index, int max_diag_len, int inner_rows, int inner_cols,
const std::pair<MatrixDiag::Alignment, MatrixDiag::Alignment> &alignment);
std::string GetCompilerCachePath();
bool CheckCache(const std::string &kernel_name);
KernelPackPtr SearchCache(const std::string &kernel_name, const std::string &processor);
KernelPackPtr InsertCache(const std::string &kernel_name, const std::string &processor);
TypeId DtypeToTypeId(const std::string &dtypes);
std::string Dtype2ShortType(const std::string &dtypes);
size_t GetDtypeNbyte(const std::string &dtypes);
bool GetShapeSize(const std::vector<size_t> &shape, const TypePtr &type_ptr, int64_t *size_i);
bool ParseMetadata(const CNodePtr &kernel_node, const std::shared_ptr<const OpInfo> &op_info_ptr, Processor processor,
std::vector<std::shared_ptr<KernelBuildInfo>> *const kernel_info_list);
void SaveJsonInfo(const std::string &json_name, const std::string &info, const std::string &base_path);
std::string GetProcessor(const AnfNodePtr &anf_node);
Processor GetProcessor(const string &processor);
bool IsSameShape(const std::vector<size_t> &shape_a, const std::vector<size_t> &shape_b);
std::vector<std::pair<AnfNodePtr, size_t>> GetOutputIndex(const std::vector<AnfNodePtr> &node_list,
const std::vector<AnfNodePtr> &input_list,
const std::vector<AnfNodePtr> &output_list);
void GetValidKernelNodes(const FuncGraphPtr &func_graph, std::vector<AnfNodePtr> *node_list);
void GetValidKernelNodes(const FuncGraphPtr &func_graph, std::vector<AnfNodePtr> *node_list,
std::vector<AnfNodePtr> *input_list, std::vector<AnfNodePtr> *output_list);
void GetFuncGraphOutputNodes(const FuncGraphPtr &func_graph, std::vector<AnfNodePtr> *output_list);
void GetGraphRealOutput(const FuncGraphPtr &func_graph, std::vector<std::pair<AnfNodePtr, size_t>> *node_list);
bool IsWeightBoundary(const AnfNodePtr &node);
std::vector<int64_t> GetReduceAttrAxis(const CNodePtr &cnode);
std::string GetProcessorStr(const AnfNodePtr &anf_node);
Processor GetProcessorFromContext();
std::string GetStrProcessorFromContext();
float Scaling(size_t in_size, size_t out_size, bool align_corners);
float ScaleGrid(const int x, const float scale);
FusionType GetFusionTypeByName(const std::string &name);
std::string GetFusionNameByType(const kernel::FusionType &type);
std::vector<bool> Dec2Bin(const int64_t &mask);
void FillEmptyDims(const CNodePtr &kernel_node, std::vector<int64_t> *begin, std::vector<int64_t> *end,
std::vector<int64_t> *stride, std::vector<size_t> *input_shape);
void ParseStrideSliceMasks(const CNodePtr &kernel_node, std::vector<int64_t> *begin, std::vector<int64_t> *end,
std::vector<int64_t> *stride, const std::vector<size_t> &input_shape);
struct CachedInterpolation {
size_t lower;
size_t upper;
float lerp;
};
void ComputeInterpolationWeights(const size_t out_size, const size_t in_size, const float scale,
CachedInterpolation *interpolation);
template <typename T>
inline std::string Vector2Str(const std::vector<T> &inputs) {
if (!inputs.empty()) {
std::ostringstream oss;
(void)std::copy(inputs.begin(), inputs.end() - 1, std::ostream_iterator<T>(oss, ", "));
oss << inputs.back();
return oss.str();
}
return "";
}
template <typename T>
inline std::string Map2Str(const std::map<std::string, T> value) {
std::stringstream ss;
ss << "(";
for (auto it = value.begin(); it != value.end(); it++) {
if (it == value.begin()) {
ss << it->first;
} else {
ss << ", " << it->first;
}
}
ss << ")";
return ss.str();
}
template <typename T>
inline std::string Unorderedmap2Str(const std::unordered_map<std::string, T> value) {
std::stringstream ss;
ss << "(";
for (auto it = value.begin(); it != value.end(); it++) {
if (it == value.begin()) {
ss << it->first;
} else {
ss << ", " << it->first;
}
}
ss << ")";
return ss.str();
}
template <typename T>
inline T ComputeLerp(T top_left, T top_right, T bottom_left, T bottom_right, T x_lerp, T y_lerp) {
T top = top_left + (top_right - top_left) * x_lerp;
T bottom = bottom_left + (bottom_right - bottom_left) * x_lerp;
return top + (bottom - top) * y_lerp;
}
void CastShapeSizeToLong(const std::vector<size_t> &shape, std::vector<int64_t> *long_shape);
void CheckSliceValid(const std::vector<int64_t> &start, const std::vector<int64_t> &stop,
const std::vector<int64_t> &step, const std::vector<int64_t> &input_shape);
size_t CalOffset(const std::vector<int64_t> &start, const std::vector<int64_t> &stop,
const std::vector<int64_t> &dim_offset);
std::vector<int64_t> CalDimOffset(const std::vector<int64_t> &input_shape);
size_t GetCopySize(const std::vector<int64_t> &dim_offset, const std::vector<int64_t> &start,
const std::vector<int64_t> &stop);
size_t UnitSizeInBytes(const mindspore::TypeId &t);
class KernelAttr {
public:
using DataType = std::pair<TypeId, std::string>;
KernelAttr() = default;
~KernelAttr() = default;
KernelAttr &AddInputAttr(const TypeId &ms_type, const std::string &format = kOpFormat_DEFAULT);
KernelAttr &AddOutputAttr(const TypeId &ms_type, const std::string &format = kOpFormat_DEFAULT);
KernelAttr &AddAllSameAttr(const bool &all_same);
KernelAttr &AddOutInRef(size_t output_index, size_t input_index);
const DataType &GetInputAttr(const size_t index) const { return input_type_[index]; }
const DataType &GetOutputAttr(const size_t index) const { return output_type_[index]; }
const bool &GetAllSame() const { return all_same_; }
size_t GetInputSize() const { return input_type_.size(); }
size_t GetOutputSize() const { return output_type_.size(); }
const OutputInputRefMap &GetOutInRefMap() const { return out_in_ref_map_; }
void SetInputAttrList(const std::vector<DataType> &addr_list);
private:
std::vector<DataType> input_type_;
std::vector<DataType> output_type_;
bool all_same_{false};
// The map between kernel's output and input ref relationship.
OutputInputRefMap out_in_ref_map_;
};
std::ostream &operator<<(std::ostream &os, KernelAttr kernel_attr);
std::pair<bool, size_t> MatchKernelAttr(const KernelAttr &kernel_attr, const std::vector<KernelAttr> &attr_list);
KernelAttr GetKernelAttrFromBuildInfo(const KernelBuildInfoPtr &build_info);
KernelAttr GetKernelAttrFromNode(const AnfNodePtr &kernel_node);
using KernelArgs = std::tuple<BaseOperatorPtr, std::vector<KernelTensorPtr>, std::vector<KernelTensorPtr>>;
KernelArgs GetArgsFromCNode(const CNodePtr &cnode);
KernelAttr GetKernelAttrFromTensors(const std::vector<KernelTensorPtr> &inputs,
const std::vector<KernelTensorPtr> &outputs);
void SetCpuRefMapToKernelInfo(const CNodePtr &apply_kernel, const std::vector<KernelAttr> &kernel_attrs);
#define CHECK_KERNEL_INPUTS_NUM(actual_inputs_num, expect_inputs_num, kernel_name) \
do { \
if ((actual_inputs_num) != (expect_inputs_num)) { \
MS_LOG(EXCEPTION) << (kernel_name) << " requires " << (expect_inputs_num) << " inputs, but got " \
<< (actual_inputs_num) << "."; \
} \
} while (0)
#define CHECK_KERNEL_OUTPUTS_NUM(actual_outputs_num, expect_outputs_num, kernel_name) \
do { \
if ((actual_outputs_num) != (expect_outputs_num)) { \
MS_LOG(EXCEPTION) << (kernel_name) << " should have " << (expect_outputs_num) << " outputs, but got " \
<< (actual_outputs_num) << "."; \
} \
} while (0)
#define CHECK_KERNEL_WORKSPACE_SIZE(actual_size, expect_size, kernel_name) \
do { \
if ((actual_size) != (expect_size)) { \
MS_LOG(EXCEPTION) << (kernel_name) << " requires " << (expect_size) << " workspace, but got " << (actual_size) \
<< "."; \
} \
} while (0)
} // namespace kernel
} // namespace mindspore
#endif // MINDSPORE_CCSRC_KERNEL_COMMON_UTILS_H_