Merge pull request !5140 from zyli2020/add_cuda_path_checktags/v1.0.0
| @@ -177,7 +177,7 @@ KernelPackPtr InsertCache(const std::string &kernel_name, const std::string &pro | |||||
| if (processor == kProcessorAiCore || processor == kProcessorAiCpu) { | if (processor == kProcessorAiCore || processor == kProcessorAiCpu) { | ||||
| kernel_json = kCceKernelMeta; | kernel_json = kCceKernelMeta; | ||||
| } else { | } else { | ||||
| kernel_json = bin_map->GetKernelMetaPath(); | |||||
| kernel_json = bin_map->kernel_meta_path(); | |||||
| } | } | ||||
| (void)kernel_json.append(kernel_name).append(kJsonSuffix); | (void)kernel_json.append(kernel_name).append(kJsonSuffix); | ||||
| KernelPackPtr kernel_pack = std::make_shared<KernelPack>(); | KernelPackPtr kernel_pack = std::make_shared<KernelPack>(); | ||||
| @@ -57,8 +57,8 @@ class KernelMeta { | |||||
| void RemoveKernelCache(); | void RemoveKernelCache(); | ||||
| std::string Search(const std::string &kernel_name) const; | std::string Search(const std::string &kernel_name) const; | ||||
| bool Insert(const std::string &kernel_name, const std::string &kernel_json); | bool Insert(const std::string &kernel_name, const std::string &kernel_json); | ||||
| std::string GetKernelMetaPath() { return kernel_meta_path_; } | |||||
| std::string kernel_meta_path() const { return kernel_meta_path_; } | |||||
| bool initialized() const { return initialized_; } | |||||
| static KernelMeta *GetInstance() { | static KernelMeta *GetInstance() { | ||||
| static KernelMeta kernel_meta; | static KernelMeta kernel_meta; | ||||
| return &kernel_meta; | return &kernel_meta; | ||||
| @@ -0,0 +1,124 @@ | |||||
| /** | |||||
| * 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 "runtime/device/gpu/cuda_env_checker.h" | |||||
| #include <dirent.h> | |||||
| #include <cstdlib> | |||||
| #include <algorithm> | |||||
| #include "utils/log_adapter.h" | |||||
| namespace mindspore { | |||||
| namespace device { | |||||
| namespace gpu { | |||||
| bool CudaEnvChecker::CheckNvccInPath() { | |||||
| if (already_check_nvcc_) { | |||||
| return find_nvcc_; | |||||
| } | |||||
| auto checker = [](const std::string &cuda_path) { | |||||
| bool find_nvcc = false; | |||||
| DIR *dir = opendir(cuda_path.c_str()); | |||||
| if (dir == nullptr) { | |||||
| return find_nvcc; | |||||
| } | |||||
| struct dirent *entry; | |||||
| while ((entry = readdir(dir)) != nullptr) { | |||||
| std::string bin_file = entry->d_name; | |||||
| if (bin_file == kNvcc) { | |||||
| find_nvcc = true; | |||||
| break; | |||||
| } | |||||
| } | |||||
| (void)closedir(dir); | |||||
| return find_nvcc; | |||||
| }; | |||||
| auto cuda_paths = GetCudaRealPaths(); | |||||
| find_nvcc_ = any_of(cuda_paths.begin(), cuda_paths.end(), checker); | |||||
| already_check_nvcc_ = true; | |||||
| return find_nvcc_; | |||||
| } | |||||
| std::vector<std::string> CudaEnvChecker::GetCudaRealPaths() const { | |||||
| std::vector<std::string> res; | |||||
| auto env_paths_ptr = std::getenv(kPathEnv); | |||||
| if (env_paths_ptr == nullptr) { | |||||
| MS_LOG(ERROR) << "Please export env: PATH"; | |||||
| return res; | |||||
| } | |||||
| std::string env_paths = env_paths_ptr; | |||||
| if (env_paths.empty()) { | |||||
| MS_LOG(ERROR) << "env PATH is empty"; | |||||
| return res; | |||||
| } | |||||
| std::string cur_path; | |||||
| for (const auto &ch : env_paths) { | |||||
| if (ch != ':') { | |||||
| cur_path += ch; | |||||
| continue; | |||||
| } | |||||
| auto real_path_pair = IsCudaRealPath(cur_path); | |||||
| if (real_path_pair.second) { | |||||
| res.push_back(real_path_pair.first); | |||||
| } | |||||
| cur_path.clear(); | |||||
| } | |||||
| if (!cur_path.empty()) { | |||||
| auto last_real_path_pair = IsCudaRealPath(cur_path); | |||||
| if (last_real_path_pair.second) { | |||||
| res.push_back(last_real_path_pair.first); | |||||
| } | |||||
| } | |||||
| return res; | |||||
| } | |||||
| std::pair<std::string, bool> CudaEnvChecker::IsCudaRealPath(const std::string &path) const { | |||||
| std::string real_path = path; | |||||
| bool valid_path = false; | |||||
| // 8: string length of kCudaSoftLinkPath | |||||
| if (real_path.size() < 8) { | |||||
| return {"", false}; | |||||
| } | |||||
| // remove redundance space in path | |||||
| auto front_space_pos = real_path.find_first_not_of(' '); | |||||
| if (front_space_pos != 0) { | |||||
| real_path.erase(0, front_space_pos); | |||||
| } | |||||
| auto back_space_pos = real_path.find_last_not_of(' '); | |||||
| if (back_space_pos != real_path.size() - 1) { | |||||
| real_path.erase(back_space_pos + 1); | |||||
| } | |||||
| auto cuda_softlink_path_pos = real_path.rfind(kCudaSoftLinkPath); | |||||
| auto cuda_real_path_pos = real_path.rfind(kCudaRealPath); | |||||
| auto start = (cuda_softlink_path_pos == std::string::npos || cuda_real_path_pos == std::string::npos) | |||||
| ? std::min(cuda_softlink_path_pos, cuda_real_path_pos) | |||||
| : std::max(cuda_softlink_path_pos, cuda_real_path_pos); | |||||
| if (start == std::string::npos) { | |||||
| return {"", false}; | |||||
| } | |||||
| auto end = real_path.find('n', start); | |||||
| valid_path = (end == real_path.size() - 1) ? true : ((end == real_path.size() - 2) && (real_path.back() == '/')); | |||||
| return {real_path.substr(0, end + 1), valid_path}; | |||||
| } | |||||
| } // namespace gpu | |||||
| } // namespace device | |||||
| } // namespace mindspore | |||||
| @@ -0,0 +1,54 @@ | |||||
| /** | |||||
| * 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_CCSRC_RUNTIME_DEVICE_GPU_CUDA_ENV_CHECKER_H_ | |||||
| #define MINDSPORE_CCSRC_RUNTIME_DEVICE_GPU_CUDA_ENV_CHECKER_H_ | |||||
| #include <vector> | |||||
| #include <string> | |||||
| #include <utility> | |||||
| namespace mindspore { | |||||
| namespace device { | |||||
| namespace gpu { | |||||
| class CudaEnvChecker { | |||||
| public: | |||||
| bool CheckNvccInPath(); | |||||
| static CudaEnvChecker &GetInstance() { | |||||
| static CudaEnvChecker instance; | |||||
| return instance; | |||||
| } | |||||
| private: | |||||
| CudaEnvChecker() = default; | |||||
| ~CudaEnvChecker() = default; | |||||
| CudaEnvChecker(const CudaEnvChecker &); | |||||
| CudaEnvChecker &operator=(const CudaEnvChecker &); | |||||
| std::vector<std::string> GetCudaRealPaths() const; | |||||
| std::pair<std::string, bool> IsCudaRealPath(const std::string &path) const; | |||||
| bool already_check_nvcc_ = false; | |||||
| bool find_nvcc_ = false; | |||||
| static constexpr auto kPathEnv = "PATH"; | |||||
| static constexpr auto kNvcc = "nvcc"; | |||||
| static constexpr auto kCudaSoftLinkPath = "cuda/bin"; | |||||
| static constexpr auto kCudaRealPath = "cuda-10.1/bin"; | |||||
| }; | |||||
| } // namespace gpu | |||||
| } // namespace device | |||||
| } // namespace mindspore | |||||
| #endif // MINDSPORE_CCSRC_RUNTIME_DEVICE_GPU_CUDA_ENV_CHECKER_H_ | |||||
| @@ -22,6 +22,7 @@ | |||||
| #include "frontend/operator/ops.h" | #include "frontend/operator/ops.h" | ||||
| #include "backend/session/anf_runtime_algorithm.h" | #include "backend/session/anf_runtime_algorithm.h" | ||||
| #include "backend/session/kernel_build_client.h" | #include "backend/session/kernel_build_client.h" | ||||
| #include "runtime/device/gpu/cuda_env_checker.h" | |||||
| namespace mindspore { | namespace mindspore { | ||||
| namespace device { | namespace device { | ||||
| @@ -29,9 +30,8 @@ namespace gpu { | |||||
| void GpuBuild(const KernelGraphPtr &kernel_graph) { | void GpuBuild(const KernelGraphPtr &kernel_graph) { | ||||
| kernel::KernelMeta *bin_map = kernel::KernelMeta::GetInstance(); | kernel::KernelMeta *bin_map = kernel::KernelMeta::GetInstance(); | ||||
| MS_EXCEPTION_IF_NULL(bin_map); | MS_EXCEPTION_IF_NULL(bin_map); | ||||
| auto pid = mindspore::kernel::GpuKernelBuildClient::Instance().AkgGetPid(); | |||||
| bin_map->Initialize(pid); | |||||
| MS_EXCEPTION_IF_NULL(kernel_graph); | MS_EXCEPTION_IF_NULL(kernel_graph); | ||||
| bool already_check_nvcc = false; | |||||
| auto kernels = kernel_graph->execution_order(); | auto kernels = kernel_graph->execution_order(); | ||||
| for (const auto &kernel : kernels) { | for (const auto &kernel : kernels) { | ||||
| std::string kernel_name = session::AnfRuntimeAlgorithm::GetCNodeName(kernel); | std::string kernel_name = session::AnfRuntimeAlgorithm::GetCNodeName(kernel); | ||||
| @@ -41,6 +41,19 @@ void GpuBuild(const KernelGraphPtr &kernel_graph) { | |||||
| } | } | ||||
| if (session::AnfRuntimeAlgorithm::GetKernelType(kernel) == KernelType::AKG_KERNEL) { | if (session::AnfRuntimeAlgorithm::GetKernelType(kernel) == KernelType::AKG_KERNEL) { | ||||
| if (!bin_map->initialized()) { | |||||
| auto pid = mindspore::kernel::GpuKernelBuildClient::Instance().AkgGetPid(); | |||||
| bin_map->Initialize(pid); | |||||
| } | |||||
| if (!already_check_nvcc) { | |||||
| already_check_nvcc = true; | |||||
| if (!CudaEnvChecker::GetInstance().CheckNvccInPath()) { | |||||
| MS_LOG(EXCEPTION) | |||||
| << "Failed to find nvcc compiler, please add nvcc position to the PATH environment variable, run " | |||||
| "the command: export PATH=${CUDA_PATH}/bin:${PATH}, CUDA_PATH is the installation path of the " | |||||
| "cuda library(eg. /usr/local/cuda)."; | |||||
| } | |||||
| } | |||||
| auto gpu_kernel_ptr = kernel::AkgGpuKernelBuild(kernel); | auto gpu_kernel_ptr = kernel::AkgGpuKernelBuild(kernel); | ||||
| if (!gpu_kernel_ptr) { | if (!gpu_kernel_ptr) { | ||||
| MS_LOG(EXCEPTION) << "Build akg kernel op[" << kernel_name << "] failed"; | MS_LOG(EXCEPTION) << "Build akg kernel op[" << kernel_name << "] failed"; | ||||