1 /** 2 * Copyright 2019-2021 Huawei Technologies Co., Ltd 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #ifndef MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_GPU_GPUKERNELFACTORY_H_ 17 #define MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_GPU_GPUKERNELFACTORY_H_ 18 19 #include <functional> 20 #include <map> 21 #include <string> 22 #include <vector> 23 #include <utility> 24 #include <memory> 25 #include "backend/kernel_compiler/gpu/gpu_kernel.h" 26 #include "runtime/device/gpu/kernel_info_setter.h" 27 #include "backend/kernel_compiler/kernel_build_info.h" 28 29 namespace mindspore { 30 namespace kernel { 31 using mindspore::device::gpu::KernelAttr; 32 using GpuKernelCreater = std::function<GpuKernel *()>; 33 class GpuKernelFactory { 34 public: 35 ~GpuKernelFactory() = default; 36 37 static GpuKernelFactory &GetInstance(); 38 39 void Register(const std::string &kernel_name, const KernelAttr &kernel_attr, GpuKernelCreater &&creator); 40 41 GpuKernel *Create(const std::string &kernel_name, const CNodePtr &apply_kernel); 42 43 bool SearchRegistered(const std::string &kernel_name, const KernelBuildInfoPtr &kernel_info); 44 45 std::string SupportedTypeList(const std::string &kernel_name); 46 47 bool ReducePrecision(const std::string &kernel_name, 48 std::shared_ptr<mindspore::kernel::KernelBuildInfo::KernelBuildInfoBuilder> builder); 49 50 std::pair<std::vector<size_t>, TypeId> reduce_flag_{{}, kNumberTypeInt64}; 51 52 private: 53 GpuKernelFactory() = default; 54 55 GpuKernelFactory(GpuKernelFactory const &); 56 57 GpuKernelFactory &operator=(const GpuKernelFactory &); 58 59 std::pair<bool, size_t> GpuKernelAttrCheck(const std::string &kernel_name, const KernelBuildInfo *kernel_info); 60 void CheckSM(const KernelBuildInfo *kernel_info, const size_t &input_index); 61 bool CheckIOParam(const std::string &kernel_name, const KernelBuildInfo *kernel_info, 62 std::vector<std::pair<KernelAttr, GpuKernelCreater>> *iter_second, size_t attr_index); 63 // map to maintain kernel and creator, KernelAttr object and creator must be registered as a pair. 64 std::map<std::string, std::vector<std::pair<KernelAttr, GpuKernelCreater>>> map_kernel_name_to_creater_; 65 }; 66 67 class GpuKernelRegister { 68 public: GpuKernelRegister(const std::string & kernel_name,const KernelAttr & kernel_attr,GpuKernelCreater && creator)69 GpuKernelRegister(const std::string &kernel_name, const KernelAttr &kernel_attr, GpuKernelCreater &&creator) { 70 GpuKernelFactory::GetInstance().Register(kernel_name, kernel_attr, std::move(creator)); 71 } 72 ~GpuKernelRegister() = default; 73 }; 74 75 // This is necessary for gpu kernels to support uint8 data type. In cuda, an unsigned, 76 // 8 bit integral type is represented by an unsigned char, but the MS_REG_GPU_KERNEL 77 // macros defined below will create compilation errors when datatype T contains a space, 78 // because the variable created by the macro will also contain a space. So, we solve this 79 // problem by writing uchar when calling these macros, and expanding uchar after the 80 // variable has been created. 81 #define uchar unsigned char 82 83 #define UNIQUE_KERNEL_NAME(kernel) KERNEL_NAME(g_##kernel##_gpu_kernel_reg, __COUNTER__) 84 #define KERNEL_NAME(kernel, cnt) MERGE(kernel, cnt) 85 #define MERGE(kernel, cnt) kernel##cnt 86 87 #define MS_REG_GPU_KERNEL(OPNAME, OPCLASS) \ 88 static_assert(std::is_base_of<GpuKernel, OPCLASS>::value, " must be base of GpuKernel"); \ 89 static const GpuKernelRegister UNIQUE_KERNEL_NAME(OPNAME)(#OPNAME, KernelAttr(), []() { return new OPCLASS(); }); 90 91 // regular register of fixed accuracy kernels 92 #define MS_REG_GPU_KERNEL_REGULAR(OPNAME, ATTR, OPCLASS) \ 93 static_assert(std::is_base_of<GpuKernel, OPCLASS>::value, " must be base of GpuKernel"); \ 94 static const GpuKernelRegister UNIQUE_KERNEL_NAME(OPNAME)(#OPNAME, ATTR, []() { return new OPCLASS(); }); 95 96 // register of mixed accuracy kernels which use template and maintain one typename, ignore input num 97 #define MS_REG_GPU_KERNEL_SAME(OPNAME, ATTR, OPCLASS, T) \ 98 static_assert(std::is_base_of<GpuKernel, OPCLASS<T>>::value, " must be base of GpuKernel"); \ 99 static const GpuKernelRegister UNIQUE_KERNEL_NAME(OPNAME)(#OPNAME, ATTR, []() { return new OPCLASS<T>(); }); 100 101 // register of mixed accuracy kernels which use template and maintain one typename 102 #define MS_REG_GPU_KERNEL_ONE(OPNAME, ATTR, OPCLASS, T) \ 103 static_assert(std::is_base_of<GpuKernel, OPCLASS<T>>::value, " must be base of GpuKernel"); \ 104 static const GpuKernelRegister UNIQUE_KERNEL_NAME(OPNAME)(#OPNAME, ATTR, []() { return new OPCLASS<T>(); }); 105 106 // register of mixed accuracy kernels which use template and maintain two typename 107 #define MS_REG_GPU_KERNEL_TWO(OPNAME, ATTR, OPCLASS, T, S) \ 108 static_assert(std::is_base_of<GpuKernel, OPCLASS<T, S>>::value, " must be base of GpuKernel"); \ 109 static const GpuKernelRegister UNIQUE_KERNEL_NAME(OPNAME)(#OPNAME, ATTR, []() { return new OPCLASS<T, S>(); }); 110 111 // register of mixed accuracy kernels which use template and maintain three typename 112 #define MS_REG_GPU_KERNEL_THREE(OPNAME, ATTR, OPCLASS, T, S, G) \ 113 static_assert(std::is_base_of<GpuKernel, OPCLASS<T, S, G>>::value, " must be base of GpuKernel"); \ 114 static const GpuKernelRegister UNIQUE_KERNEL_NAME(OPNAME)(#OPNAME, ATTR, []() { return new OPCLASS<T, S, G>(); }); 115 } // namespace kernel 116 } // namespace mindspore 117 #endif // MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_GPU_GPUKERNELFACTORY_H_ 118