.. _program_listing_file_include_cudawrappers_nvrtc.hpp: Program Listing for File nvrtc.hpp ================================== |exhale_lsh| :ref:`Return to documentation for file ` (``include/cudawrappers/nvrtc.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #if !defined NVRTC_H #define NVRTC_H #include #include #include #include #include #include #include #include #include #include #if !defined(__HIP__) #include #include #else #include #include #include #endif namespace nvrtc { class Error : public std::exception { public: explicit Error(nvrtcResult result) : _result(result) {} const char *what() const noexcept { return nvrtcGetErrorString(_result); } operator nvrtcResult() const { return _result; } private: nvrtcResult _result; }; inline void checkNvrtcCall(nvrtcResult result) { if (result != NVRTC_SUCCESS) throw Error(result); } inline std::string findIncludePath() { std::string path; if (dl_iterate_phdr( [](struct dl_phdr_info *info, size_t, void *arg) -> int { std::string &path = *static_cast(arg); path = info->dlpi_name; #if defined(__HIP__) // HIPRTC symbols are also in libamdhip64.so, although they will be // removed from there see // https://rocm.docs.amd.com/projects/HIP/en/docs-6.1.0/how-to/hip_rtc.html#deprecation-notice // check both libraries for now, as linking with hiprtc is not yet // required return (path.find("libhiprtc.so") != std::string::npos) | (path.find("libamdhip64.so") != std::string::npos); #else return path.find("libnvrtc.so") != std::string::npos; #endif }, &path)) for (size_t pos; (pos = path.find_last_of("/")) != std::string::npos;) { path.erase(pos); // remove last part of path struct stat buffer; #if defined(__HIP__) const std::string filename = path + "/include/hip/hip_runtime.h"; #else const std::string filename = path + "/include/cuda.h"; #endif if (stat(filename.c_str(), &buffer) == 0) { return path + "/include"; } } throw std::runtime_error("Could not find NVRTC include path"); } class Program { public: Program(const std::string &src, const std::string &name, const std::vector &headers = std::vector(), const std::vector &includeNames = std::vector()) { std::vector c_headers; std::transform(headers.begin(), headers.end(), std::back_inserter(c_headers), [](const std::string &header) { return header.c_str(); }); std::vector c_includeNames; std::transform( includeNames.begin(), includeNames.end(), std::back_inserter(c_includeNames), [](const std::string &includeName) { return includeName.c_str(); }); checkNvrtcCall(nvrtcCreateProgram(&program, src.c_str(), name.c_str(), static_cast(c_headers.size()), c_headers.data(), c_includeNames.data())); } explicit Program(const std::string &filename) { std::ifstream ifs(filename); if (!ifs.is_open()) { throw std::runtime_error("Error opening file '" + filename + "' in cudawrappers::nvrtc"); } std::string source(std::istreambuf_iterator{ifs}, {}); checkNvrtcCall(nvrtcCreateProgram(&program, source.c_str(), filename.c_str(), 0, nullptr, nullptr)); } ~Program() { checkNvrtcCall(nvrtcDestroyProgram(&program)); } void compile(const std::vector &options) { std::vector c_options; std::transform(options.begin(), options.end(), std::back_inserter(c_options), [](const std::string &option) { return option.c_str(); }); checkNvrtcCall(nvrtcCompileProgram( program, static_cast(c_options.size()), c_options.data())); } std::string getPTX() { size_t size{}; std::string ptx; checkNvrtcCall(nvrtcGetPTXSize(program, &size)); ptx.resize(size); checkNvrtcCall(nvrtcGetPTX(program, const_cast(ptx.data()))); return ptx; } #if CUDA_VERSION >= 11020 std::vector getCUBIN() { size_t size{}; std::vector cubin; checkNvrtcCall(nvrtcGetCUBINSize(program, &size)); cubin.resize(size); checkNvrtcCall(nvrtcGetCUBIN(program, &cubin[0])); return cubin; } #endif std::string getLog() { size_t size{}; std::string log; checkNvrtcCall(nvrtcGetProgramLogSize(program, &size)); log.resize(size); checkNvrtcCall(nvrtcGetProgramLog(program, &log[0])); return log; } private: nvrtcProgram program{}; }; } // namespace nvrtc #endif