4 个版本
0.1.3 | 2021 年 7 月 28 日 |
---|---|
0.1.2 | 2020 年 2 月 29 日 |
0.1.1 | 2019 年 5 月 17 日 |
0.1.0 | 2018 年 12 月 1 日 |
#77 在 图形 API 中
938 每月下载量
用于 6 软件包
305KB
4K SLoC
RustaCUDA
RustaCUDA 通过提供灵活、易于使用的接口,帮助您将 GPU 加速功能引入项目。RustaCUDA 使管理 GPU 内存、在 GPU 之间传输数据以及加载和启动用任何语言编写的计算内核变得简单。
目录
目标
主要设计目标包括
- 高级:使用 RustaCUDA 应该对 Rust 程序员来说既熟悉又直观。
- 易于使用:RustaCUDA 应具有良好的文档和设计,足以帮助初学者开始 GPU 编程,同时不会过多限制经验更丰富的用户。
- 安全:许多 GPU 加速计算的方面难以与 Rust 的安全保证相协调,但 RustaCUDA 应该提供合理实用的最安全接口。
- 快速:RustaCUDA 应该尽可能地快,在不与其他目标冲突的情况下。
RustaCUDA 旨在提供一个面向程序员的库,用于与主机端的 CUDA 驱动 API 一起工作。它不旨在帮助将 Rust 代码编译为 CUDA 内核(尽管您可以查看 rust-ptx-builder 了解相关信息)或提供在内核内部使用的设备端实用程序。
RustaCUDA 故意对内核的工作方式或编译方式保持中立。这使得可以使用用 nvcc
编译的 C 内核(例如)。
路线图
RustaCUDA 目前支持 CUDA API 的最小可行子集(基本上,是管理内存和启动基本内核所需的最小内容)。这不包括
- 除了内核启动之外的所有异步操作
- 访问 CUDA 1/2/3D 数组和纹理内存
- 多 GPU 支持
- 运行时链接
- CUDA 图
- 等等!
这些附加功能将在有时间且必要时进行开发。如果您需要尚未支持的功能,请考虑提交一个pull request!
快速入门
在使用RustaCUDA之前,您必须安装适用于您的系统的CUDA开发库。需要版本8.0或更高版本。您还必须安装带有适当驱动程序的CUDA兼容GPU。
首先,将环境变量CUDA_LIBRARY_PATH
设置为CUDA头文件的位置
export CUDA_LIBRARY_PATH="C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.1\lib\x64"
一些Ubuntu用户在使用CUDA_LIBRARY_PATH时遇到了链接错误。如果您看到如下错误
= note: /usr/bin/ld: cannot find -lcudart
/usr/bin/ld: cannot find -lcublas
collect2: error: ld returned 1 exit status
使用LIBRARY_PATH
而不是CUDA_LIBRARY_PATH
似乎有帮助。
现在,开始构建一个基本的CUDA crate。将以下内容添加到您的Cargo.toml
[dependencies]
rustacuda = "0.1"
rustacuda_core = "0.1"
rustacuda_derive = "0.1"
并将其添加到crate根目录下
#[macro_use]
extern crate rustacuda;
#[macro_use]
extern crate rustacuda_derive;
extern crate rustacuda_core;
接下来,从RustaCUDA仓库下载resources/add.ptx
文件,并将其放置在您的应用程序的资源目录中。
在examples/目录中包含了一些示例代码,可以帮助您入门。要执行最简单的示例(在GPU上添加两个数字),将以下代码放置到您的main.rs
文件中。
#[macro_use]
extern crate rustacuda;
use rustacuda::prelude::*;
use rustacuda::memory::DeviceBox;
use std::error::Error;
use std::ffi::CString;
fn main() -> Result<(), Box<dyn Error>> {
// Initialize the CUDA API
rustacuda::init(CudaFlags::empty())?;
// Get the first device
let device = Device::get_device(0)?;
// Create a context associated to this device
let context = Context::create_and_push(
ContextFlags::MAP_HOST | ContextFlags::SCHED_AUTO, device)?;
// Load the module containing the function we want to call
let module_data = CString::new(include_str!("../resources/add.ptx"))?;
let module = Module::load_from_string(&module_data)?;
// Create a stream to submit work to
let stream = Stream::new(StreamFlags::NON_BLOCKING, None)?;
// Allocate space on the device and copy numbers to it.
let mut x = DeviceBox::new(&10.0f32)?;
let mut y = DeviceBox::new(&20.0f32)?;
let mut result = DeviceBox::new(&0.0f32)?;
// Launching kernels is unsafe since Rust can't enforce safety - think of kernel launches
// as a foreign-function call. In this case, it is - this kernel is written in CUDA C.
unsafe {
// Launch the `sum` function with one block containing one thread on the given stream.
launch!(module.sum<<<1, 1, 0, stream>>>(
x.as_device_ptr(),
y.as_device_ptr(),
result.as_device_ptr(),
1 // Length
))?;
}
// The kernel launch is asynchronous, so we wait for the kernel to finish executing
stream.synchronize()?;
// Copy the result back to the host
let mut result_host = 0.0f32;
result.copy_to(&mut result_host)?;
println!("Sum is {}", result_host);
Ok(())
}
如果一切正常,您应该能够运行cargo run
并看到输出
Sum is 30.0
贡献
感谢您的兴趣!欢迎贡献。
请通过上面的issue tracker报告问题、功能请求、疑问和错误报告。特别是,因为RustaCUDA旨在提供良好的文档,请报告任何您认为混乱或不正确的文档内容。
以pull request形式提出的代码或文档改进也是受欢迎的。不过,请在大量工作之前先提交或评论一个issue以允许讨论。
有关更多详细信息,请参阅CONTRIBUTING.md文件。
维护
RustaCUDA目前由Brook Heisler (@bheisler) 维护。
许可证
RustaCUDA根据Apache 2.0许可证和MIT许可证双授权。
要求
RustaCUDA需要安装至少CUDA版本8。
相关项目
- accel是一个完整的CUDA计算框架。感谢accel创建了并维护了
cuda-sys
FFI包装库。 - rust-ptx-builder是一个
build.rs
辅助库,它使将Rust crate编译成CUDA内核变得简单。
依赖关系
~1.5MB
~44K SLoC