7个不稳定版本 (3个破坏性更新)
0.4.0-alpha | 2023年8月13日 |
---|---|
0.3.0 | 2023年8月10日 |
0.2.0 | 2023年6月8日 |
0.1.1 | 2023年6月5日 |
#1637 in 算法
84 每月下载量
用于 oscirs
31KB
571 行
oscirs_linalg
Rust的线性代数库
描述
此库允许进行简单的线性代数相关计算,并通过OpenCL 3.0支持GPU并行化。
此库依赖于opencl3库,该库提供了OpenCL 3.0宏的Rust实现。
使用
oscirs_linalg主要依赖于Matrix
结构。您可以使用32位浮点向量创建一个矩阵,除了行数和列数的乘积等于向量的长度外。构造函数new_matrix
在成功返回矩阵之前会检查这一点。数据向量是按行主序排列的。以下是一个示例代码。
use oscirs_linalg::matrix::Matrix;
let data: Vec<f32> = vec![2.0; 6];
let n_rows: usize = 2;
let n_cols: usize = 3;
let mat: Matrix = Matrix::new(data, n_rows, n_cols)
.expect("Failed to create mat");
矩阵可以使用典型的算术运算符相加,就像整数或浮点数一样。矩阵也可以取负值或与浮点数相加/相减。当操作需要维度检查时,您应使用?
运算符或expect()
来处理错误。
let data_2: Vec<f32> = vec![3.0; 6];
let n_rows_2: usize = 2;
let n_cols_2: usize = 3;
let mat_2: Matrix = Matrix::new(data_2, n_rows_2, n_cols_2)
.expect("Failed to create mat_2");
let result: Matrix = (&mat + &mat_2)
.expect("Failed to add mat and mat_2");
assert_eq!(result.get_data(), vec![5.0; 6]);
可以使用嵌套方括号索引矩阵,分别使用row()
和col()
方法分别索引行/列。
assert_eq!(result[[1, 1]], 5.0);
GPU加速
虽然可以使用A * B
语法进行矩阵乘法,但这是一个基于单线程CPU的操作。对于大型矩阵,这很快就会变得低效。oscirs_linalg通过OpenCL支持基于GPU的并行矩阵乘法。
要开始并行化,首先通过init()
函数初始化Calculator
结构。请确保将其声明为可变的,因为它将在内部动态存储矩阵。
use oscirs_linalg::calculator::Calculator;
let mut calc: Calculator = Calculator::init()
.expect("Failed to initialize Calculator");
在进行任何操作之前,矩阵必须存储在计算器的内存中。方法 store_matrix()
返回一个内存索引,该索引将用于在乘法操作中引用该矩阵。
let a_vec: Vec<f32> = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
let b_vec: Vec<f32> = vec![2.0, 1.0, 2.0, 3.0, 2.0, 1.0];
let a_mat: Matrix = Matrix::new(a_vec, 2, 3)
.expect("Failed to create Matrix A");
let b_mat: Matrix = Matrix::new(b_vec, 3, 2)
.expect("Failed to create Matrix B");
let a_idx: usize = calc.store_matrix(a_mat)
.expect("Failed to store Matrix A in calculator memory");
let b_idx: usize = calc.store_matrix(b_mat)
.expect("Failed to store Matrix B in calculator memory");
一旦两个矩阵都存储在计算器的内存中,您就可以在 Calculator
上调用 mat_mul()
方法来乘以两个矩阵。 mat_mul()
的参数是要乘的矩阵的内存索引。
let (c_mat, _c_idx) = calc.mat_mul(a_idx, b_idx)
.expect("Failed to mulitply Matrix A and Matrix B");
assert_eq!(c_mat.get_data(), vec![12.0, 10.0, 30.0, 25.0], "Matrix C data not as expected");
assert_eq!(c_mat.get_rows(), 2, "Matrix C row dimension not as expected");
assert_eq!(c_mat.get_cols(), 2, "Matrix C col dimension not as expected");
mat_mul()
返回一个包含结果矩阵及其在内存中索引的元组。结果矩阵始终存储在计算器的内存中,以便后续计算可以更快地进行,且内存移动更少。
自定义OpenCL内核
oscirs_linalg 还支持使用 Calculator
提供的内存管理工具使用您自己的 OpenCL 内核。这有点复杂,涉及一些不安全的函数,但在 tests 文件夹下的 linalg_tests.rs 中提供了一个示例。它需要创建一个自定义闭包,该闭包从输入矩阵计算输出矩阵的维度和工作大小,一旦完成,就可以轻松地多次执行您的自定义内核。
依赖项
~1.3–1.8MB
~39K SLoC