Make various updates and fixes:
- Add support for legacy CUDA versions; now compatible with CUDA 12.3 and newer - Add support for NVRTC compilation - Other fixes and code refactoring
This commit is contained in:
+1
-1
@@ -9,7 +9,7 @@
|
||||
namespace deep_gemm {
|
||||
|
||||
class KernelRuntimeCache {
|
||||
std::unordered_map<std::filesystem::path, std::shared_ptr<KernelRuntime>> cache;
|
||||
std::unordered_map<std::string, std::shared_ptr<KernelRuntime>> cache;
|
||||
|
||||
public:
|
||||
// TODO: consider cache capacity
|
||||
|
||||
+128
-21
@@ -1,14 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <ATen/cuda/CUDAContext.h>
|
||||
#include <cuda_runtime.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <nvrtc.h>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
#include "../utils/exception.hpp"
|
||||
#include "../utils/format.hpp"
|
||||
#include "../utils/hash.hpp"
|
||||
#include "../utils/lazy_init.hpp"
|
||||
#include "../utils/system.hpp"
|
||||
#include "cache.hpp"
|
||||
#include "device_runtime.hpp"
|
||||
@@ -16,10 +19,13 @@
|
||||
namespace deep_gemm {
|
||||
|
||||
class Compiler {
|
||||
std::string library_version;
|
||||
std::filesystem::path library_root_path;
|
||||
public:
|
||||
static std::filesystem::path library_root_path;
|
||||
static std::filesystem::path library_include_path;
|
||||
static std::filesystem::path cuda_home;
|
||||
static std::string library_version;
|
||||
|
||||
std::string get_library_version() const {
|
||||
static std::string get_library_version() {
|
||||
std::stringstream ss;
|
||||
for (const auto& f: collect_files(library_include_path / "deep_gemm")) {
|
||||
std::ifstream in(f, std::ios::binary);
|
||||
@@ -28,16 +34,23 @@ class Compiler {
|
||||
return get_hex_digest(ss.str());
|
||||
}
|
||||
|
||||
public:
|
||||
static void prepare_init(const std::string& library_root_path,
|
||||
const std::string& cuda_home_path_by_torch) {
|
||||
Compiler::library_root_path = library_root_path;
|
||||
Compiler::library_include_path = Compiler::library_root_path / "include";
|
||||
Compiler::cuda_home = cuda_home_path_by_torch;
|
||||
Compiler::library_version = get_library_version();
|
||||
}
|
||||
|
||||
std::string signature, flags;
|
||||
std::filesystem::path library_include_path;
|
||||
std::filesystem::path cache_dir_path;
|
||||
|
||||
explicit Compiler(const std::filesystem::path& library_root_path) {
|
||||
// Static library paths
|
||||
this->library_root_path = library_root_path;
|
||||
this->library_include_path = library_root_path / "include";
|
||||
this->library_version = get_library_version();
|
||||
Compiler() {
|
||||
// Check `prepare_init`
|
||||
DG_HOST_ASSERT(not library_root_path.empty());
|
||||
DG_HOST_ASSERT(not library_include_path.empty());
|
||||
DG_HOST_ASSERT(not cuda_home.empty());
|
||||
DG_HOST_ASSERT(not library_version.empty());
|
||||
|
||||
// Cache settings
|
||||
cache_dir_path = std::filesystem::path(get_env<std::string>("HOME")) / ".deep_gemm";
|
||||
@@ -46,10 +59,11 @@ public:
|
||||
|
||||
// The compiler flags applied to all derived compilers
|
||||
signature = "unknown-compiler";
|
||||
std::string ptxas_flags = "--ptxas-options=--register-usage-level=10";
|
||||
if (get_env<int>("DG_JIT_PTXAS_VERBOSE", 0))
|
||||
ptxas_flags += ",--verbose";
|
||||
flags = fmt::format("-std=c++20 --diag-suppress=39,161,174,177,186,940 {}", ptxas_flags);
|
||||
flags = fmt::format("-std=c++{} --diag-suppress=39,161,174,177,186,940 "
|
||||
"--ptxas-options=--register-usage-level=10",
|
||||
get_env<int>("DG_JIT_CPP_STANDARD", 20));
|
||||
if (get_env("DG_JIT_DEBUG", 0) or get_env("DG_JIT_PTXAS_VERBOSE", 0))
|
||||
flags += " --ptxas-options=--verbose";
|
||||
}
|
||||
|
||||
virtual ~Compiler() = default;
|
||||
@@ -102,6 +116,11 @@ public:
|
||||
virtual void compile(const std::string &code, const std::filesystem::path& dir_path, const std::filesystem::path &cubin_path) const = 0;
|
||||
};
|
||||
|
||||
DG_DECLARE_STATIC_VAR_IN_CLASS(Compiler, library_root_path);
|
||||
DG_DECLARE_STATIC_VAR_IN_CLASS(Compiler, library_include_path);
|
||||
DG_DECLARE_STATIC_VAR_IN_CLASS(Compiler, cuda_home);
|
||||
DG_DECLARE_STATIC_VAR_IN_CLASS(Compiler, library_version);
|
||||
|
||||
class NVCCCompiler final: public Compiler {
|
||||
std::filesystem::path nvcc_path;
|
||||
|
||||
@@ -125,11 +144,9 @@ class NVCCCompiler final: public Compiler {
|
||||
}
|
||||
|
||||
public:
|
||||
NVCCCompiler(const std::filesystem::path& library_root_path,
|
||||
const std::filesystem::path& cuda_home_path_by_torch):
|
||||
Compiler(library_root_path) {
|
||||
NVCCCompiler() {
|
||||
// Override the compiler signature
|
||||
nvcc_path = cuda_home_path_by_torch / "bin" / "nvcc";
|
||||
nvcc_path = cuda_home / "bin" / "nvcc";
|
||||
if (const auto& env_nvcc_path = get_env<std::string>("DG_JIT_NVCC_COMPILER"); not env_nvcc_path.empty())
|
||||
nvcc_path = env_nvcc_path;
|
||||
const auto& [nvcc_major, nvcc_minor] = get_nvcc_version();
|
||||
@@ -150,10 +167,10 @@ public:
|
||||
// Compile
|
||||
const auto& command = fmt::format("{} {} -o {} {}", nvcc_path.c_str(), code_path.c_str(), cubin_path.c_str(), flags);
|
||||
if (get_env("DG_JIT_DEBUG", 0) or get_env("DG_JIT_PRINT_COMPILER_COMMAND", 0))
|
||||
printf("Running NVCC command: %s", command.c_str());
|
||||
printf("Running NVCC command: %s\n", command.c_str());
|
||||
const auto& [return_code, output] = call_external_command(command);
|
||||
if (return_code != 0) {
|
||||
printf("NVCC compilation failed: %s", output.c_str());
|
||||
printf("NVCC compilation failed: %s\n", output.c_str());
|
||||
DG_HOST_ASSERT(false and "NVCC compilation failed");
|
||||
}
|
||||
|
||||
@@ -163,6 +180,96 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static std::shared_ptr<Compiler> compiler = nullptr;
|
||||
class NVRTCCompiler final: public Compiler {
|
||||
public:
|
||||
NVRTCCompiler() {
|
||||
// Override the compiler signature
|
||||
int major, minor;
|
||||
DG_NVRTC_CHECK(nvrtcVersion(&major, &minor));
|
||||
signature = fmt::format("NVRTC{}.{}", major, minor);
|
||||
|
||||
// Build include directories list
|
||||
std::string include_dirs;
|
||||
include_dirs += fmt::format("-I{} ", library_include_path.string());
|
||||
include_dirs += fmt::format("-I{} ", (cuda_home / "include").string());
|
||||
|
||||
// Add PCH support for version 12.8 and above
|
||||
// NOTES: PCH is vital for compilation speed
|
||||
std::string pch_flags;
|
||||
if (major > 12 or (major == 12 and minor >= 8)) {
|
||||
pch_flags = "--pch ";
|
||||
if (get_env<int>("DG_JIT_DEBUG", 0))
|
||||
pch_flags += "--pch-verbose=true ";
|
||||
}
|
||||
|
||||
// Override the compiler flags
|
||||
flags = fmt::format("{} {}--gpu-architecture=sm_{}a -default-device {}",
|
||||
flags, include_dirs, device_runtime->get_arch(), pch_flags);
|
||||
}
|
||||
|
||||
void compile(const std::string &code, const std::filesystem::path& dir_path, const std::filesystem::path &cubin_path) const override {
|
||||
// Write the code into the cache directory
|
||||
const auto& code_path = dir_path / "kernel.cu";
|
||||
put(code_path, code);
|
||||
|
||||
// Parse compilation options
|
||||
std::istringstream iss(flags);
|
||||
std::vector<std::string> options;
|
||||
std::string option;
|
||||
while (iss >> option)
|
||||
options.push_back(option);
|
||||
|
||||
// Convert to C-style string array for NVRTC
|
||||
std::vector<const char*> option_cstrs;
|
||||
for (const auto& opt: options)
|
||||
option_cstrs.push_back(opt.c_str());
|
||||
|
||||
// Print compiler command if requested
|
||||
if (get_env<int>("DG_JIT_DEBUG", 0) or get_env<int>("DG_JIT_PRINT_COMPILER_COMMAND", 0)) {
|
||||
printf("Compiling JIT runtime with NVRTC options: ");
|
||||
for (const auto& opt: options)
|
||||
printf("%s ", opt.c_str());
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// Create NVRTC program and compile
|
||||
nvrtcProgram program;
|
||||
DG_NVRTC_CHECK(nvrtcCreateProgram(&program, code.c_str(), "kernel.cu", 0, nullptr, nullptr));
|
||||
const auto& compile_result = nvrtcCompileProgram(program, static_cast<int>(option_cstrs.size()), option_cstrs.data());
|
||||
|
||||
// Get and print compiler log
|
||||
size_t log_size;
|
||||
DG_NVRTC_CHECK(nvrtcGetProgramLogSize(program, &log_size));
|
||||
if (get_env<int>("DG_JIT_DEBUG", 0) or compile_result != NVRTC_SUCCESS) {
|
||||
if (compile_result != NVRTC_SUCCESS)
|
||||
DG_HOST_ASSERT(log_size > 1);
|
||||
if (log_size > 1) {
|
||||
std::string compilation_log(log_size, '\0');
|
||||
DG_NVRTC_CHECK(nvrtcGetProgramLog(program, compilation_log.data()));
|
||||
printf("NVRTC log: %s\n", compilation_log.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Get CUBIN size and data
|
||||
size_t cubin_size;
|
||||
DG_NVRTC_CHECK(nvrtcGetCUBINSize(program, &cubin_size));
|
||||
std::string cubin_data(cubin_size, '\0');
|
||||
DG_NVRTC_CHECK(nvrtcGetCUBIN(program, cubin_data.data()));
|
||||
|
||||
// Write into the file system
|
||||
put(cubin_path, cubin_data);
|
||||
|
||||
// Cleanup
|
||||
DG_NVRTC_CHECK(nvrtcDestroyProgram(&program));
|
||||
}
|
||||
};
|
||||
|
||||
static auto compiler = LazyInit<Compiler>([]() -> std::shared_ptr<Compiler> {
|
||||
if (get_env<int>("DG_JIT_USE_NVRTC", 0)) {
|
||||
return std::make_shared<NVRTCCompiler>();
|
||||
} else {
|
||||
return std::make_shared<NVCCCompiler>();
|
||||
}
|
||||
});
|
||||
|
||||
} // namespace deep_gemm
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
#include <ATen/cuda/CUDAContext.h>
|
||||
|
||||
#include "../utils/exception.hpp"
|
||||
#include "../utils/lazy_init.hpp"
|
||||
|
||||
namespace deep_gemm {
|
||||
|
||||
class DeviceRuntime {
|
||||
int num_sms = 0;
|
||||
int num_sms = 0, tc_util = 0;
|
||||
std::shared_ptr<cudaDeviceProp> cached_prop;
|
||||
|
||||
public:
|
||||
@@ -43,8 +44,17 @@ public:
|
||||
num_sms = get_prop()->multiProcessorCount;
|
||||
return num_sms;
|
||||
}
|
||||
|
||||
void set_tc_util(const int& new_tc_util) {
|
||||
DG_HOST_ASSERT(0 <= new_tc_util and new_tc_util <= 100);
|
||||
tc_util = new_tc_util;
|
||||
}
|
||||
|
||||
int get_tc_util() const {
|
||||
return tc_util == 0 ? 100 : tc_util;
|
||||
}
|
||||
};
|
||||
|
||||
static auto device_runtime = std::make_shared<DeviceRuntime>();
|
||||
static auto device_runtime = LazyInit<DeviceRuntime>([](){ return std::make_shared<DeviceRuntime>(); });
|
||||
|
||||
} // namespace deep_gemm
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
#pragma once
|
||||
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime.h>
|
||||
#include <filesystem>
|
||||
|
||||
#include "../utils/exception.hpp"
|
||||
|
||||
namespace deep_gemm {
|
||||
|
||||
#if CUDART_VERSION >= 12080 or defined(DG_JIT_USE_DRIVER_API)
|
||||
|
||||
// Use CUDA runtime API
|
||||
using LibraryHandle = cudaLibrary_t;
|
||||
using KernelHandle = cudaKernel_t;
|
||||
using LaunchConfigHandle = cudaLaunchConfig_t;
|
||||
using LaunchAttrHandle = cudaLaunchAttribute;
|
||||
|
||||
#define DG_CUDA_UNIFIED_CHECK DG_CUDA_RUNTIME_CHECK
|
||||
|
||||
static KernelHandle load_kernel(const std::filesystem::path& cubin_path, const std::string& func_name,
|
||||
LibraryHandle *library_opt = nullptr) {
|
||||
LibraryHandle library;
|
||||
KernelHandle kernel{};
|
||||
DG_CUDA_RUNTIME_CHECK(cudaLibraryLoadFromFile(&library, cubin_path.c_str(), nullptr, nullptr, 0, nullptr, nullptr, 0));
|
||||
DG_CUDA_RUNTIME_CHECK(cudaLibraryGetKernel(&kernel, library, func_name.c_str()));
|
||||
|
||||
if (library_opt != nullptr)
|
||||
*library_opt = library;
|
||||
return kernel;
|
||||
}
|
||||
|
||||
static void unload_library(const LibraryHandle& library) {
|
||||
const auto& error = cudaLibraryUnload(library);
|
||||
DG_HOST_ASSERT(error == cudaSuccess or error == cudaErrorCudartUnloading);
|
||||
}
|
||||
|
||||
static LaunchConfigHandle construct_launch_config(const KernelHandle& kernel,
|
||||
const cudaStream_t& stream, const int& smem_size,
|
||||
const dim3& grid_dim, const dim3& block_dim, const int& cluster_dim) {
|
||||
if (smem_size > 0)
|
||||
DG_CUDA_RUNTIME_CHECK(cudaFuncSetAttribute(kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, smem_size));
|
||||
|
||||
LaunchConfigHandle config;
|
||||
config.gridDim = grid_dim;
|
||||
config.blockDim = block_dim;
|
||||
config.dynamicSmemBytes = smem_size;
|
||||
config.stream = stream;
|
||||
config.numAttrs = 0;
|
||||
config.attrs = nullptr;
|
||||
|
||||
// NOTES: must use `static` or the `attr` will be deconstructed
|
||||
static LaunchAttrHandle attr;
|
||||
if (cluster_dim > 1) {
|
||||
attr.id = cudaLaunchAttributeClusterDimension;
|
||||
attr.val.clusterDim = {static_cast<unsigned>(cluster_dim), 1, 1};
|
||||
config.attrs = &attr;
|
||||
config.numAttrs = 1;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
template<typename... ActTypes>
|
||||
static auto launch_kernel(const KernelHandle& kernel, const LaunchConfigHandle& config, ActTypes&&... args) {
|
||||
void *ptr_args[] = { &args... };
|
||||
return cudaLaunchKernelExC(&config, kernel, ptr_args);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Use CUDA driver API
|
||||
using LibraryHandle = CUmodule;
|
||||
using KernelHandle = CUfunction;
|
||||
using LaunchConfigHandle = CUlaunchConfig;
|
||||
using LaunchAttrHandle = CUlaunchAttribute;
|
||||
|
||||
#define DG_CUDA_UNIFIED_CHECK DG_CUDA_DRIVER_CHECK
|
||||
|
||||
static KernelHandle load_kernel(const std::filesystem::path& cubin_path, const std::string& func_name,
|
||||
LibraryHandle *library_opt = nullptr) {
|
||||
LibraryHandle library;
|
||||
KernelHandle kernel;
|
||||
DG_CUDA_DRIVER_CHECK(cuModuleLoad(&library, cubin_path.c_str()));
|
||||
DG_CUDA_DRIVER_CHECK(cuModuleGetFunction(&kernel, library, func_name.c_str()));
|
||||
|
||||
if (library_opt != nullptr)
|
||||
*library_opt = library;
|
||||
return kernel;
|
||||
}
|
||||
|
||||
static void unload_library(const LibraryHandle& library) {
|
||||
const auto& error = cuModuleUnload(library);
|
||||
DG_HOST_ASSERT(error == CUDA_SUCCESS or error == CUDA_ERROR_DEINITIALIZED);
|
||||
}
|
||||
|
||||
static LaunchConfigHandle construct_launch_config(const KernelHandle& kernel,
|
||||
const cudaStream_t& stream, const int& smem_size,
|
||||
const dim3& grid_dim, const dim3& block_dim, const int& cluster_dim) {
|
||||
if (smem_size > 0)
|
||||
DG_CUDA_DRIVER_CHECK(cuFuncSetAttribute(kernel, CU_FUNC_ATTRIBUTE_MAX_DYNAMIC_SHARED_SIZE_BYTES, smem_size));
|
||||
|
||||
LaunchConfigHandle config;
|
||||
config.gridDimX = grid_dim.x;
|
||||
config.gridDimY = grid_dim.y;
|
||||
config.gridDimZ = grid_dim.z;
|
||||
config.blockDimX = block_dim.x;
|
||||
config.blockDimY = block_dim.y;
|
||||
config.blockDimZ = block_dim.z;
|
||||
config.sharedMemBytes = smem_size;
|
||||
config.hStream = stream;
|
||||
config.numAttrs = 0;
|
||||
config.attrs = nullptr;
|
||||
|
||||
// NOTES: must use `static` or the `attr` will be deconstructed
|
||||
static LaunchAttrHandle attr;
|
||||
if (cluster_dim > 1) {
|
||||
attr.id = CU_LAUNCH_ATTRIBUTE_CLUSTER_DIMENSION;
|
||||
attr.value.clusterDim.x = cluster_dim;
|
||||
attr.value.clusterDim.y = 1;
|
||||
attr.value.clusterDim.z = 1;
|
||||
config.attrs = &attr;
|
||||
config.numAttrs = 1;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
template<typename... ActTypes>
|
||||
static auto launch_kernel(const KernelHandle& kernel, const LaunchConfigHandle& config, ActTypes&&... args) {
|
||||
void *ptr_args[] = { &args... };
|
||||
return cuLaunchKernelEx(&config, kernel, ptr_args, nullptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace deep_gemm
|
||||
+20
-42
@@ -1,12 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <filesystem>
|
||||
|
||||
#include "../utils/exception.hpp"
|
||||
#include "../utils/format.hpp"
|
||||
#include "../utils/system.hpp"
|
||||
#include "device_runtime.hpp"
|
||||
#include "handle.hpp"
|
||||
|
||||
namespace deep_gemm {
|
||||
|
||||
@@ -23,19 +21,17 @@ struct LaunchArgs {
|
||||
grid_dim(grid_dim), num_threads(num_threads), smem_size(smem_size), cluster_dim(cluster_dim) {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept HasLaunchArgs = requires (const T& t) {
|
||||
{ t.launch_args } -> std::convertible_to<decltype(t.launch_args)>;
|
||||
};
|
||||
|
||||
class KernelRuntime final {
|
||||
public:
|
||||
static std::filesystem::path cuda_home;
|
||||
|
||||
cudaLibrary_t library;
|
||||
cudaKernel_t kernel;
|
||||
LibraryHandle library;
|
||||
KernelHandle kernel;
|
||||
|
||||
explicit KernelRuntime(const std::filesystem::path& dir_path) {
|
||||
// Check `prepare_init`
|
||||
DG_HOST_ASSERT(not cuda_home.empty());
|
||||
|
||||
// NOLINT(*-pro-type-member-init)
|
||||
const auto& cuobjdump_path = cuda_home / "bin" / "cuobjdump";
|
||||
const auto& cubin_path = dir_path / "kernel.cubin";
|
||||
@@ -50,7 +46,8 @@ public:
|
||||
std::istringstream iss(symbols);
|
||||
std::vector<std::string> symbol_names;
|
||||
for (std::string line; std::getline(iss, line); ) {
|
||||
if (line.find("STT_FUNC") == 0 and std::ranges::none_of(illegal_names, [&](const auto& name) { return line.find(name) != std::string::npos; })) {
|
||||
if (line.find("STT_FUNC") == 0 and std::none_of(illegal_names.begin(), illegal_names.end(),
|
||||
[&](const auto& name) { return line.find(name) != std::string::npos; })) {
|
||||
const auto& last_space = line.rfind(' ');
|
||||
symbol_names.push_back(line.substr(last_space + 1));
|
||||
}
|
||||
@@ -64,11 +61,10 @@ public:
|
||||
|
||||
// Load from the library
|
||||
DG_HOST_ASSERT(symbol_names.size() == 1);
|
||||
DG_CUDA_RUNTIME_CHECK(cudaLibraryLoadFromFile(&library, cubin_path.c_str(), nullptr, nullptr, 0, nullptr, nullptr, 0));
|
||||
DG_CUDA_RUNTIME_CHECK(cudaLibraryGetKernel(&kernel, library, symbol_names[0].c_str()));
|
||||
kernel = load_kernel(cubin_path, symbol_names[0], &library);
|
||||
}
|
||||
|
||||
static void set_cuda_home(const std::string& cuda_home_path_by_torch) {
|
||||
static void prepare_init(const std::string& cuda_home_path_by_torch) {
|
||||
cuda_home = cuda_home_path_by_torch;
|
||||
}
|
||||
|
||||
@@ -78,18 +74,16 @@ public:
|
||||
}
|
||||
|
||||
~KernelRuntime() noexcept(false) {
|
||||
const auto& error = cudaLibraryUnload(library);
|
||||
DG_HOST_ASSERT(error == cudaSuccess or error == cudaErrorCudartUnloading);
|
||||
unload_library(library);
|
||||
}
|
||||
};
|
||||
|
||||
// Declare after defining
|
||||
decltype(KernelRuntime::cuda_home) KernelRuntime::cuda_home;
|
||||
DG_DECLARE_STATIC_VAR_IN_CLASS(KernelRuntime, cuda_home);
|
||||
|
||||
template <typename Derived>
|
||||
class LaunchRuntime {
|
||||
public:
|
||||
template <typename Args> requires HasLaunchArgs<Args>
|
||||
template <typename Args>
|
||||
static std::string generate(const Args& args) {
|
||||
const auto& code = Derived::generate_impl(args);
|
||||
if (get_env<int>("DG_JIT_DEBUG", 0))
|
||||
@@ -97,34 +91,18 @@ public:
|
||||
return code;
|
||||
}
|
||||
|
||||
template <typename Args> requires HasLaunchArgs<Args>
|
||||
template <typename Args>
|
||||
static void launch(const std::shared_ptr<KernelRuntime>& kernel_runtime, const Args& args) {
|
||||
const auto& kernel = kernel_runtime->kernel;
|
||||
const auto& stream = at::cuda::getCurrentCUDAStream();
|
||||
const LaunchArgs& launch_args = args.launch_args;
|
||||
|
||||
// Set dynamic shared memory size
|
||||
if (launch_args.smem_size > 0)
|
||||
DG_CUDA_RUNTIME_CHECK(cudaFuncSetAttribute(kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, launch_args.smem_size));
|
||||
|
||||
// Launch config
|
||||
cudaLaunchConfig_t config;
|
||||
config.gridDim = {static_cast<unsigned>(launch_args.grid_dim.first),
|
||||
static_cast<unsigned>(launch_args.grid_dim.second),
|
||||
1};
|
||||
config.blockDim = {static_cast<unsigned>(launch_args.num_threads), 1, 1};
|
||||
config.dynamicSmemBytes = launch_args.smem_size;
|
||||
config.stream = stream;
|
||||
config.numAttrs = 0;
|
||||
|
||||
// Clusters
|
||||
cudaLaunchAttribute attr;
|
||||
if (launch_args.cluster_dim > 1) {
|
||||
attr.id = cudaLaunchAttributeClusterDimension;
|
||||
attr.val.clusterDim = {static_cast<unsigned>(launch_args.cluster_dim), 1, 1};
|
||||
config.attrs = &attr;
|
||||
config.numAttrs = 1;
|
||||
}
|
||||
const dim3& grid_dim = {static_cast<unsigned>(launch_args.grid_dim.first),
|
||||
static_cast<unsigned>(launch_args.grid_dim.second),
|
||||
1};
|
||||
const dim3& block_dim = {static_cast<unsigned>(launch_args.num_threads), 1, 1};
|
||||
auto config = construct_launch_config(kernel, stream, launch_args.smem_size,
|
||||
grid_dim, block_dim, launch_args.cluster_dim);
|
||||
|
||||
// Launch in the derived class
|
||||
if (get_env<int>("DG_JIT_DEBUG")) {
|
||||
|
||||
Reference in New Issue
Block a user