You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

cuda_helper.cpp 5.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /**
  2. * \file src/core/impl/utils/cuda_helper.cpp
  3. * MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  4. *
  5. * Copyright (c) 2014-2020 Megvii Inc. All rights reserved.
  6. *
  7. * Unless required by applicable law or agreed to in writing,
  8. * software distributed under the License is distributed on an
  9. * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. */
  11. #include "megbrain/common.h"
  12. #include "megbrain/exception.h"
  13. #include "megbrain/utils/cuda_helper.h"
  14. #include <set>
  15. #include <fstream>
  16. #include <string>
  17. #include <sstream>
  18. using namespace mgb;
  19. #ifdef WIN32
  20. #include <io.h>
  21. #include <windows.h>
  22. #else
  23. #include <unistd.h>
  24. #include <dlfcn.h>
  25. #endif
  26. #ifndef PATH_MAX
  27. #define PATH_MAX 4096
  28. #endif
  29. #ifdef WIN32
  30. #define F_OK 0
  31. #define RTLD_LAZY 0
  32. #define RTLD_GLOBAL 0
  33. #define RTLD_NOLOAD 0
  34. #define RTLD_DI_ORIGIN 0
  35. #define access(a, b) false
  36. #define SPLITER ';'
  37. #define PATH_SPLITER '\\'
  38. #define ENV_PATH "Path"
  39. #define NVCC_EXE "nvcc.exe"
  40. void* dlopen(const char* file, int) {
  41. return static_cast<void*>(LoadLibrary(file));
  42. }
  43. int dlinfo(void* handle, int request, char* path) {
  44. if (GetModuleFileName((HMODULE)handle, path, PATH_MAX))
  45. return 0;
  46. else
  47. return -1;
  48. }
  49. void* dlerror() {
  50. const char* errmsg = "dlerror not aviable in windows";
  51. return const_cast<char*>(errmsg);
  52. }
  53. void* dlsym(void* handle, char* name) {
  54. FARPROC symbol = GetProcAddress((HMODULE)handle, name);
  55. return reinterpret_cast<void*>(symbol);
  56. }
  57. int check_file_exist(const char* path, int mode) {
  58. return _access(path, mode);
  59. }
  60. #else
  61. #define SPLITER ':'
  62. #define PATH_SPLITER '/'
  63. #define ENV_PATH "PATH"
  64. #define NVCC_EXE "nvcc"
  65. int check_file_exist(const char* path, int mode) {
  66. return access(path, mode);
  67. }
  68. #endif
  69. std::vector<std::string> split_env(const char* env) {
  70. std::string e(env);
  71. std::istringstream stream(e);
  72. std::vector<std::string> ret;
  73. std::string path;
  74. while (std::getline(stream, path, SPLITER)) {
  75. ret.emplace_back(path);
  76. }
  77. return ret;
  78. }
  79. //! this function will find file_name in each path in envs. It accepts add
  80. //! intermediate path between env and file_name
  81. std::string find_file_in_envs_with_intmd(
  82. const std::vector<std::string>& envs, const std::string& file_name,
  83. const std::vector<std::string>& itmedias = {}) {
  84. for (auto&& env : envs) {
  85. auto ret = getenv(env.c_str());
  86. if (ret) {
  87. for (auto&& path : split_env(ret)) {
  88. auto file_path = std::string(path) + PATH_SPLITER + file_name;
  89. if (!check_file_exist(file_path.c_str(), F_OK)) {
  90. return file_path;
  91. }
  92. if (!itmedias.empty()) {
  93. for (auto&& inter_path : itmedias) {
  94. file_path = std::string(path) + PATH_SPLITER + inter_path + PATH_SPLITER +
  95. file_name;
  96. if (!check_file_exist(file_path.c_str(), F_OK)) {
  97. return file_path;
  98. }
  99. }
  100. }
  101. }
  102. }
  103. }
  104. return std::string{};
  105. }
  106. std::string get_nvcc_root_path() {
  107. auto nvcc_root_path = find_file_in_envs_with_intmd({ENV_PATH}, NVCC_EXE);
  108. if (nvcc_root_path.empty()) {
  109. mgb_throw(MegBrainError,
  110. "nvcc not found. Add your nvcc to your environment Path");
  111. } else {
  112. auto idx = nvcc_root_path.rfind(PATH_SPLITER);
  113. return nvcc_root_path.substr(0, idx + 1);
  114. }
  115. }
  116. std::vector<std::string> mgb::get_cuda_include_path() {
  117. #if MGB_CUDA
  118. std::vector<std::string> paths;
  119. // 1. use CUDA_BIN_PATH
  120. auto cuda_path = getenv("CUDA_BIN_PATH");
  121. if (cuda_path) {
  122. paths.emplace_back(std::string(cuda_path) + PATH_SPLITER + "include");
  123. paths.emplace_back(std::string(cuda_path) + PATH_SPLITER + ".." +
  124. PATH_SPLITER + "include");
  125. }
  126. // 2. use nvcc path
  127. auto nvcc_path = get_nvcc_root_path();
  128. auto cudart_header_path = nvcc_path + ".." + PATH_SPLITER + "include" +
  129. PATH_SPLITER + "cuda_runtime.h";
  130. //! double check path_to_nvcc/../include/cuda_runtime.h exists
  131. auto ret = check_file_exist(cudart_header_path.c_str(), F_OK);
  132. if (ret == 0) {
  133. paths.emplace_back(nvcc_path + "..");
  134. paths.emplace_back(nvcc_path + ".." + PATH_SPLITER + "include");
  135. }
  136. // 3. use libcudart.so library path
  137. char cuda_lib_path[PATH_MAX];
  138. auto handle = dlopen("libcudart.so", RTLD_GLOBAL | RTLD_LAZY);
  139. if(handle != nullptr) {
  140. mgb_assert(dlinfo(handle, RTLD_DI_ORIGIN, cuda_lib_path) != -1, "%s",
  141. dlerror());
  142. paths.emplace_back(std::string(cuda_lib_path) + PATH_SPLITER + ".." +
  143. PATH_SPLITER + "include");
  144. }
  145. mgb_assert(paths.size() > 0,
  146. "can't find cuda include path, check your environment of cuda, "
  147. "try one of this solutions "
  148. "1. set CUDA_BIN_PATH to cuda home path "
  149. "2. add nvcc path in PATH "
  150. "3. add libcudart.so path in LD_LIBRARY_PATH");
  151. return paths;
  152. #else
  153. mgb_throw(MegBrainError, "cuda disabled at compile time");
  154. #endif
  155. }

MegEngine 安装包中集成了使用 GPU 运行代码所需的 CUDA 环境,不用区分 CPU 和 GPU 版。 如果想要运行 GPU 程序,请确保机器本身配有 GPU 硬件设备并安装好驱动。 如果你想体验在云端 GPU 算力平台进行深度学习开发的感觉,欢迎访问 MegStudio 平台