LibreCUDA 使用教程
LibreCuda 项目地址: https://gitcode.com/gh_mirrors/li/LibreCuda
1. 项目介绍
LibreCUDA 是一个开源项目,旨在替代 CUDA 驱动 API,使开发者能够在不依赖 NVIDIA 的专有 CUDA 运行时的条件下,通过直接与硬件通信(使用 ioctls 和 NVIDIA 的 MMIO 命令队列结构),在 NVIDIA GPU 上运行 CUDA 代码。
2. 项目快速启动
要使用 LibreCUDA,首先需要克隆项目仓库并链接到 driverapi
库。
git clone --recurse https://github.com/mikex86/LibreCuda.git
然后在你的 CMake 项目中添加 LibreCUDA 作为子目录:
add_subdirectory(LibreCuda)
接着链接到 driverapi
库:
target_link_libraries(YourTarget PRIVATE driverapi)
在代码中包含 LibreCUDA 头文件:
#include <librecuda.h>
以下是一个简单的示例代码,展示如何使用 LibreCUDA 初始化、加载模块、分配内存、执行内核和释放资源:
int main() {
libreCuInit(0);
int device_count;
libreCuDeviceGetCount(&device_count);
std::cout << "Device count: " << device_count << std::endl;
LibreCUdevice device;
libreCuDeviceGet(&device, 0);
LibreCUcontext ctx;
libreCuCtxCreate_v2(&ctx, CU_CTX_SCHED_YIELD, device);
LibreCUmodule module;
uint8_t *image;
size_t n_bytes;
{
std::ifstream input("write_float.cubin", std::ios::binary);
std::vector<uint8_t> bytes((std::istreambuf_iterator<char>(input)), (std::istreambuf_iterator<char>()));
input.close();
image = new uint8_t[bytes.size()];
doMemcpy(image, bytes.data(), bytes.size());
n_bytes = bytes.size();
}
libreCuModuleLoadData(&module, image, n_bytes);
uint32_t num_funcs;
libreCuModuleGetFunctionCount(&num_funcs, module);
std::cout << "Num functions: " << num_funcs << std::endl;
LibreCUFunction *functions = new LibreCUFunction[num_funcs];
libreCuModuleEnumerateFunctions(functions, num_funcs, module);
for (size_t i = 0; i < num_funcs; i++) {
LibreCUFunction func = functions[i];
const char *func_name;
libreCuFuncGetName(&func_name, func);
std::cout << "function \"" << func_name << "\"" << std::endl;
}
delete[] functions;
LibreCUFunction func;
libreCuModuleGetFunction(&func, module, "write_float");
LibreCUstream stream;
libreCuStreamCreate(&stream, 0);
void *float_dst_va;
libreCuMemAlloc(&float_dst_va, sizeof(float), true);
float float_value = 3.1415f;
void *float_src_va;
libreCuMemAlloc(&float_src_va, sizeof(float), true);
*(float *)(float_src_va) = float_value;
std::cout << "Src value: " << float_value << std::endl;
std::cout << "Dst value (pre exec): " << *(float *)(float_dst_va) << std::endl;
void *params[] = {&float_dst_va, &float_src_va};
libreCuLaunchKernel(func, 1, 1, 1, 1, 1, 1, 0, stream, params, sizeof(params) / sizeof(void *), nullptr);
libreCuStreamCommence(stream);
libreCuStreamAwait(stream);
std::cout << "Dst value (post exec): " << *(float *)(float_dst_va) << std::endl;
libreCuMemFree(float_dst_va);
libreCuStreamDestroy(stream);
libreCuModuleUnload(module);
libreCuCtxDestroy(ctx);
return 0;
}
编译并运行上述代码,你将看到设备计数、函数数量以及内核执行前后的值。
3. 应用案例和最佳实践
- 设备管理:使用
libreCuDeviceGetCount
和libreCuDeviceGet
来查询和选择设备。 - 上下文管理:创建和销毁上下文,使用
libreCuCtxCreate_v2
和libreCuCtxDestroy
。 - 模块管理:加载和卸载模块,使用
libreCuModuleLoadData
和libreCuModuleUnload
。 - 内存管理:分配和释放 GPU 内存,使用
libreCuMemAlloc
和libreCuMemFree
。 - 内核执行:启动 CUDA 内核,使用
libreCuLaunchKernel
。
4. 典型生态项目
目前,LibreCUDA 还处于早期阶段,实现了基本的 CUDA 功能。它在开源社区中可以找到一些潜在的使用场景,尤其是对于那些希望避免使用专有驱动程序的用户。与 LibreCUDA 相似的其他项目包括:
- ROCm:AMD 的开源 GPU 计算框架。
- OpenCL:一个开放的、跨平台的并行计算标准,可用于多种类型的处理设备。
LibreCUDA 可以为这些生态系统提供补充,为开发者提供更多的选择和灵活性。