文档 / 简体中文查看源码 ↗

Ruda 编程指南

文档首页 · Runtime API · 计算库 · English | 日本語 | Deutsch | Русский

1. 主机与设备

主机 Rust 代码负责选择设备、准备输入、构造参数及读取结果。设备 Kernel 描述并行计算,经前端展开为 IR,再由后端编译和执行。

ruda-kernel::dsl 是当前通用 Kernel 前端。Kernel 使用 Rust 语法与该前端提供的类型、宏和操作;这不意味着任意 Rust 程序及其标准库都能直接编译到 GPU。

上层张量框架通过领域库分发运算。应用无需为了调用矩阵乘而自行实现线程级 Kernel。

2. 执行层级

Ruda 概念 用途
RudaCount 一次启动中的工作组数量
RudaDim 每个工作组的执行尺寸
ABSOLUTE_POS 一维逐元素 Kernel 的全局位置
Array<T> Kernel 中的一维数组访问
Tensor<T> 带维度与步长信息的 Kernel 张量访问
Runtime 关联编译器、计算服务和设备类型

这些名称来自当前 API;CUDA 概念对照见兼容性指南。公共导出见 DSL prelude。

3. 第一个 Kernel

下面摘自 ptx-runtime 示例,完整主机代码和执行检查保留在示例中:

use ruda_kernel::dsl::prelude::*;

#[ruda(launch)]
fn add(a: &Array<f32>, b: &Array<f32>, output: &mut Array<f32>) {
    if ABSOLUTE_POS < output.len() {
        output[ABSOLUTE_POS] = a[ABSOLUTE_POS] + b[ABSOLUTE_POS];
    }
}

#[ruda(launch)] 为当前宏名,相关类型由 ruda_kernel::dsl::prelude::* 导入。输出长度用于排除尾部线程;调用者仍需保证输入数组至少具有相同长度。

示例按每组 64 个执行单元、工作组数向上取整启动。64 是该示例的配置,不是所有内核的最优尺寸。

4. 内存与参数

主机端通过 ComputeClient 创建或分配设备缓冲区,使用句柄构造 Kernel 参数。尺寸必须区分字节数和元素数:

克隆句柄或张量不能理解为复制底层设备数据。需要改变布局时,应使用相应的连续化、复制或变换接口;不能只修改元数据来假装存储已经重排。

5. 提交、回读与同步

Kernel 提交与结果可用是不同阶段。主机提交结束不能作为设备计算耗时或执行成功的证据。

read_one 等待回读并返回 Result;read_async 提供异步结果。sync() 返回 future,调用者需要等待其完成。flush() 用于提交积压命令,不应作为读取结果的替代。

多流访问同一份数据时必须满足生产者与消费者的执行依赖。set_stream 是 unsafe 接口,不能仅凭主机变量的生命周期推断设备任务已经完成。

6. 安全边界

类型、所有权和借用机制服务于主机端资源与接口约束;底层封装仍需要维护设备执行的安全条件:

受检查的启动不等于对任意 Kernel 的完整安全证明。当前示例在原始参数构造与启动处保留显式 unsafe 块及安全依据。详细入口见 Runtime API。

7. 从 Kernel 到领域库

通用算子优先使用 ruBLAS、ruDNN、ruPRIM 等库。下沉到 Kernel 层时,明确输入布局、累计精度和执行配置。