作者尝试优化 Rust 中「10 亿行挑战」的解决方案。从原始的 5 分钟优化到了 9 秒。
作者的主要目标是创建一段简单、可维护且生产就绪的代码,而且没有使用不安全的操作。以下是一些关键经验:
--release 优化构建println!;使用日志库进行调试FromIterator::collect();它会触发新的分配to_owned() 和 clone()FxHashMap 比标准的 HashMap 稍微更快[u8])而不是字符串作者采取了迭代式的方法,每个解决方案都作为一个单独的提交。
Blog: https://naveenaidu.dev/tackling-the-1-billion-row-challenge-in-rust-a-journey-from-5-minutes-to-9-seconds
GitHub: https://github.com/Naveenaidu/rust-1brc
主要更新内容如下:
compilation_options 字段。目前只是将其设置为 Default::default(),如果有特定的编译需求,可以使用这个字段。RenderPipelineDescriptor 和 ComputePipelineDescriptor 现在有一个 cache 字段。这允许在着色器编译过程中提供一个缓存来使用。这主要对 Android 设备有用,因为大多数桌面硬件/驱动程序提供了缓存。目前设置为 None。DeviceDescriptor 现在有一个 memory_hint 字段。可以使用这个字段请求 GPU 优先考虑性能、内存使用情况,或允许请求自定义的内存块大小。不过,这些只是提示,硬件决定最终如何执行。目前设置为 Default::default()。Wgpu是WebGPU API规范的Rust实现。WebGPU是由GPU for the Web社区组发布的规范,旨在以安全可靠的方式让Web代码访问GPU功能。它通过模仿Vulkan API,并将其转换为主机硬件正在使用的API(如DirectX、Metal、Vulkan)来实现这一目的。
Document: https://sotrh.github.io/learn-wgpu/news/22.0/
GitHub: https://github.com/sotrh/learn-wgpu
CubeCL旨在现代化GPU计算,使编写最佳和可移植的内核更加容易。CubeCL允许使用Rust语法的子集编写GPU内核,并正在进行工作以支持更多语言特性。
CubeCL解决了GPU计算中的三个主要挑战:
下面是GELU函数的例子:
use cubecl::prelude::*;
#[cube(launch)]
fn gelu_array<F: Float>(input: &Array<F>, output: &mut Array<F>) {
if ABSOLUTE_POS < input.len() {
output[ABSOLUTE_POS] = gelu_scalar::<F>(input[ABSOLUTE_POS]);
}
}
#[cube]
fn gelu_scalar<F: Float>(x: F) -> F {
x * (F::erf(x / F::sqrt(2.0.into())) + 1.0) / 2.0
}
cube 属性中的 launch 关键字会自动生成一个函数来运行生成的内核:
fn main() {
type Runtime = cubecl::cuda::CudaRuntime;
let device = Default::default();
let client = Runtime::client(&device);
let input = &[-1., 0., 1., 5.];
let output_handle = client.empty(input.len() * core::mem::size_of::<f32>());
let input_handle = client.create(f32::as_bytes(input));
gelu_array::launch::<F32, Runtime>(
&client,
CubeCount::Static(1, 1, 1),
CubeDim::new(input.len() as u32, 1, 1),
ArrayArg::new(&input_handle, input.len()),
ArrayArg::new(&output_handle, input.len()),
);
let bytes = client.read(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:?}", Runtime::name());
}
值得一提的是,这也是burn团队的一个项目。
GitHub: https://github.com/tracel-ai/cubecl
From 日报小组 长琴
社区学习交流平台订阅:
原文作者:Rust语言中文社区;如有侵权,请联系管理员删除。