Rust通用工具库cubecl-common的使用,cubecl-common提供高效实用的Rust基础功能模块

Rust通用工具库cubecl-common的使用

cubecl-common是一个高效实用的Rust基础功能模块,为GPU计算提供多平台高性能计算语言扩展。

示例代码

以下是使用cubecl-common的GELU激活函数实现示例:

use cubecl::prelude::*;

#[cube(launch_unchecked)]
/// A [Line] represents a contiguous series of elements where SIMD operations may be available.
/// The runtime will automatically use SIMD instructions when possible for improved performance.
fn gelu_array<F: Float>(input: &Array<Line<F>>, output: &mut Array<Line<F>>) {
    if ABSOLUTE_POS < input.len() {
        output[ABSOLUTE_POS] = gelu_scalar(input[ABSOLUTE_POS]);
    }
}

#[cube]
fn gelu_scalar<F: Float>(x: Line<F>) -> Line<F> {
    // Execute the sqrt function at comptime.
    let sqrt2 = F::new(comptime!(2.0f32.sqrt()));
    let tmp = x / Line::new(sqrt2);

    x * (Line::erf(tmp) + 1.0) / 2.0
}

然后可以使用自动生成的gelu_array::launch_unchecked函数启动内核:

pub fn launch<R: Runtime>(device: &R::Device) {
    let client = R::client(device);
    let input = &[-1., 0., 1., 5.];
    let vectorization = 4;
    let output_handle = client.empty(input.len() * core::mem::size_of::<f32>());
    let input_handle = client.create(f32::as_bytes(input));

    unsafe {
        gelu_array::launch_unchecked::<f32, R>(
            &client,
            CubeCount::Static(1, 1, 1),
            CubeDim::new(input.len() as u32 / vectorization, 1, 1),
            ArrayArg::from_raw_parts::<f32](&input_handle, input.len(), vectorization as u8),
            ArrayArg::from_raw_parts::<f32](&output_handle, input.len(), vectorization as u8),
        )
    };

    let bytes = client.read_one(output_handle.binding());
    let output = f32::from_bytes(&bytes);

    // Should be [-0.1587,  0.0000,  0.8413,  5.0000]
    println!("Executed gelu with runtime {:?} => {output:?}", R::name());
}

要查看实际效果,可以使用以下命令运行GELU示例:

cargo run --example gelu --features cuda  # cuda runtime
cargo run --example gelu --features wgpu  # wgpu runtime

完整示例

以下是一个完整的示例,展示了如何使用cubecl-common库:

use cubecl::prelude::*;

// 定义GELU激活函数
#[cube]
fn gelu_scalar<F: Float>(x: Line<F>) -> Line<F> {
    let sqrt2 = F::new(comptime!(2.0f32.sqrt()));
    let tmp = x / Line::new(sqrt2);
    x * (Line::erf(tmp) + 1.0) / 2.0
}

// 定义数组操作的GELU函数
#[cube(launch_unchecked)]
fn gelu_array<F: Float>(input: &Array<Line<F>>, output: &mut Array<Line<F>>) {
    if ABSOLUTE_POS < input.len() {
        output[ABSOLUTE_POS] = gelu_scalar(input[ABSOLUTE_POS]);
    }
}

// 主函数
fn main() {
    // 初始化CUDA运行时
    let device = cubecl::cuda::Device::default();
    
    // 准备输入数据
    let input_data = vec![-1.0f32, 0.0, 1.0, 5.0];
    
    // 创建客户端
    let client = cubecl::cuda::client(&device);
    
    // 创建输入和输出缓冲区
    let input_handle = client.create(f32::as_bytes(&input_data));
    let output_handle = client.empty(input_data.len() * std::mem::size_of::<f32>());
    
    // 设置向量化因子
    let vectorization = 4;
    
    // 启动内核
    unsafe {
        gelu_array::launch_unchecked::<f32, cubecl::cuda::Runtime>(
            &client,
            CubeCount::Static(1, 1, 1),
            CubeDim::new(input_data.len() as u32 / vectorization, 1, 1),
            ArrayArg::from_raw_parts::<f32](&input_handle, input_data.len(), vectorization as u8),
            ArrayArg::from_raw_parts::<f32](&output_handle, input_data.len(), vectorization as u8),
        );
    }
    
    // 读取结果
    let output_bytes = client.read_one(output_handle.binding());
    let output = f32::from_bytes(&output_bytes);
    
    println!("Input: {:?}", input_data);
    println!("Output: {:?}", output);
}

特性

cubecl-common提供了以下核心特性:

  1. 自动向量化 - 可以指定每个输入变量的向量化因子,运行时能够编译内核并使用最佳指令
  2. Comptime - 允许在首次编译内核时修改编译器IR,实现各种优化和灵活性
  3. 自动调优 - 在运行时运行小型基准测试以确定当前硬件上最佳的内核和配置

支持平台

cubecl-common支持多种平台和运行时:

平台 运行时 编译器 硬件
WebGPU wgpu WGSL 大多数GPU
CUDA CUDA C++ (CUDA) NVIDIA GPU
ROCm HIP C++ (HIP) AMD GPU
Metal wgpu C++ (Metal) Apple GPU
Vulkan wgpu SPIR-V Linux和Windows上的大多数GPU

安装

要使用cubecl-common,可以将以下内容添加到您的Cargo.toml中:

[dependencies]
cubecl-common = "0.6.0"

或者运行以下Cargo命令:

cargo add cubecl-common

1 回复

cubecl-common - Rust通用工具库使用指南

概述

cubecl-common是一个高效实用的Rust基础功能模块集合,提供了日常开发中常用的工具函数和数据结构,帮助开发者提高开发效率。

主要功能

1. 常用数据结构

提供了一些扩展的数据结构实现:

use cubecl_common::collections::{
    DoubleLinkedList, 
    CircularBuffer,
    PriorityQueue
};

fn main() {
    // 双向链表示例
    let mut list = DoubleLinkedList::new();
    list.push_front(1);
    list.push_back(2);
    
    // 环形缓冲区示例
    let mut buf = CircularBuffer::with_capacity(5);
    buf.push(1);
    buf.push(2);
    
    // 优先队列示例
    let mut pq = PriorityQueue::new();
    pq.push("task1", 3);
    pq.push("task2", 1);
}

2. 字符串处理

提供了一系列字符串处理工具:

use cubecl_common::string_utils::{
    camel_to_snake,
    snake_to_camel,
    truncate_string
};

fn main() {
    // 驼峰转蛇形
    let s = camel_to_snake("HelloWorld"); // "hello_world"
    
    // 蛇形转驼峰
    let s = snake_to_camel("hello_world"); // "HelloWorld"
    
    // 字符串截断
    let s = truncate_string("This is a long string", 10); // "This is a..."
}

3. 日期时间处理

简化日期时间操作:

use cubecl_common::datetime::{
    current_timestamp,
    format_timestamp,
    days_between
};

fn main() {
    // 获取当前时间戳
    let now = current_timestamp();
    
    // 格式化时间戳
    let formatted = format_timestamp(now, "%Y-%m-%d %H:%M:%S");
    
    // 计算两个日期之间的天数
    let days = days_between("2023-01-01", "2023-01-10");
}

4. 文件系统操作

提供便捷的文件系统API:

use cubecl_common::fs_utils::{
    read_file_to_string,
    write_string_to_file,
    ensure_dir_exists
};

fn main() -> std::io::Result<()> {
    // 确保目录存在
    ensure_dir_exists("/path/to/dir")?;
    
    // 写入文件
    write_string_to_file("/path/to/file.txt", "Hello, world!")?;
    
    // 读取文件
    let content = read_file_to_string("/path/to/file.txt)?;
    Ok(())
}

5. 加密哈希工具

提供常用哈希算法:

use cubecl_common::crypto::{
    md5_hash,
    sha256_hash,
    generate_salt
};

fn main() {
    // MD5哈希
    let hash = md5_hash("password");
    
    // SHA256哈希
    let hash = sha256_hash("password");
    
    // 生成随机盐值
    let salt = generate_salt(16);
}

完整示例代码

//! cubecl-common 综合使用示例

use cubecl_common::prelude::*;
use cubecl_common::collections::{DoubleLinkedList, PriorityQueue};
use cubecl_common::string_utils::{camel_to_snake, truncate_string};
use cubecl_common::datetime::{current_timestamp, format_timestamp};
use cubecl_common::fs_utils::{read_file_to_string, write_string_to_file, ensure_dir_exists};
use cubecl_common::crypto::{sha256_hash, generate_salt};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 数据结构使用
    let mut list = DoubleLinkedList::new();
    list.push_front("item1");
    list.push_back("item2");
    
    let mut pq = PriorityQueue::new();
    pq.push("高优先级任务", 1);
    pq.push("低优先级任务", 3);
    
    // 2. 字符串处理
    let snake_case = camel_to_snake("UserAccountInfo");
    println!("驼峰转蛇形: {}", snake_case);
    
    let truncated = truncate_string("这是一段很长的文本需要截断处理", 8);
    println!("截断后的字符串: {}", truncated);
    
    // 3. 日期时间处理
    let now = current_timestamp();
    let formatted_time = format_timestamp(now, "%Y-%m-%d %H:%M:%S");
    println!("当前时间: {}", formatted_time);
    
    // 4. 文件操作
    ensure_dir_exists("data")?;
    write_string_to_file("data/example.txt", "测试文件内容")?;
    let content = read_file_to_string("data/example.txt")?;
    println!("文件内容: {}", content);
    
    // 5. 加密哈希
    let password_hash = sha256_hash("my_password");
    let salt = generate_salt(32);
    println!("密码哈希: {:?}", password_hash);
    println!("生成盐值: {:?}", salt);
    
    Ok(())
}

安装方法

在Cargo.toml中添加依赖:

[dependencies]
cubecl-common = "0.1.0"  # 请使用最新版本

性能特点

  1. 零成本抽象:尽可能使用Rust的零成本抽象特性
  2. 无恐慌API:关键函数都提供了Result返回
  3. 线程安全:主要数据结构都实现了Send+Sync

最佳实践

use cubecl_common::prelude::*;  // 导入常用功能

fn process_data() -> Result<(), CommonError> {
    // 使用工具函数处理数据
    let data = read_file_to_string("input.txt")?;
    let processed = data.to_uppercase();
    
    ensure_dir_exists("output")?;
    write_string_to_file("output/result.txt", &processed)?;
    
    Ok(())
}

注意事项

  1. 某些功能可能需要启用特定feature
  2. 生产环境使用时建议锁定版本号
  3. 详细API文档请参考crate文档

cubecl-common持续更新中,欢迎贡献代码和提出建议!

回到顶部