[英]Creating a struct with an array (Matrices)
我目前正在做一个简单的项目来让自己熟悉 Rust。 我没有太多的系统编程经验,但我希望学习!
我正在尝试创建一个 Matrix 结构,但我发现很难弄清楚我应该如何存储数据。 我觉得我应该能够使用数组。 矩阵的大小必须在构造时定义,所以我希望我可以将数组存储在堆栈中。
现在我的代码是这样的:
use std::ops::Mul;
use std::ops::Add;
use std::ops::Div;
struct Matrix {
cols: i32,
rows: i32,
// Of course this doesn't work!
data: [f32; ..cols*rows]
}
// Below here are a bunch of stub methods.
impl Mul<f32> for Matrix {
type Output = Matrix;
fn mul(self, m: f32) -> Matrix {
return self;
}
}
impl Mul<Matrix> for Matrix {
type Output = Matrix;
fn mul(self, m: Matrix) -> Matrix {
// Will use Strassen algorithm if large, traditional otherwise
return self;
}
}
impl Add<Matrix> for Matrix {
type Output = Matrix;
fn add(self, m: Matrix) -> Matrix {
return self;
}
}
impl Div<f32> for Matrix {
type Output = Matrix;
fn div(self, f: f32) -> Matrix {
return self;
}
}
最简单的方法是使用Vec
。
struct Matrix {
cols: i32,
rows: i32,
data: Vec<f32>
}
impl Matrix {
fn new(cols: i32, rows: i32) -> Matrix {
Matrix {
cols: cols,
rows: rows,
data: vec![0.0; cols * rows]
}
}
}
如果您不想将数据存储在堆上,您可以将Matrix
为动态大小的类型,但这很难做到并且不受真正支持。 请参阅有关该主题的 Reddit 线程。
如果您不想使用Vec
但可以将数据存储在堆上,则可以改用盒装切片 ( Box<[f32]>
)。 请参阅Vec::into_boxed_slice
了解一种创建方法。
当然,如果你真的不想使用堆,你可以为不同大小的矩阵制作不同的Matrix
类型。 这就是板条箱代数所做的。
您还可以使用向量的向量 ( Vec<Vec<T>>
),而无需实现您自己的Matrix
或使用库。 但这在索引方面比 Adrian 的方法要慢一些。 nalgebra
擅长矢量化计算,但在按nalgebra
运算时,它的性能比由Vec<T>
或Vec<Vec<T>>
组成的简单矩阵差。 以下是一些基准:
test bench_vec ... bench: 84,694,933 ns/iter (+/- 7,412,836)
test bench_vec_of_vec ... bench: 87,083,636 ns/iter (+/- 1,171,842)
test bench_vec_unsafe ... bench: 41,440,947 ns/iter (+/- 752,463)
test bench_vec_of_vec_unsafe ... bench: 44,532,595 ns/iter (+/- 629,209)
test bench_nalgebra ... bench: 452,872,630 ns/iter (+/- 40,284,295)
#![feature(test)]
extern crate test;
use na::Matrix;
use na::{Dynamic, VecStorage};
use nalgebra as na;
type DMatrixi32 = Matrix<u8, Dynamic, Dynamic, VecStorage<u8, Dynamic, Dynamic>>;
use test::Bencher;
#[bench]
fn bench_vec_of_vec(b: &mut Bencher) {
let (m, n) = (10000, 10000);
let mut matrix = vec![vec![0u8; n]; m];
b.iter(|| {
for i in 0..m {
for j in 0..n {
matrix[i][j] = 1u8;
}
}
});
}
#[bench]
fn bench_vec(b: &mut Bencher) {
let (m, n) = (10000, 10000);
let mut matrix = vec![0u8; n * m];
b.iter(|| {
for i in 0..m {
for j in 0..n {
matrix[i * n + j] = 1u8;
}
}
});
}
#[bench]
fn bench_vec_of_vec_unsafe(b: &mut Bencher) {
let (m, n) = (10000, 10000);
let mut matrix = vec![vec![0u8; n]; m];
b.iter(|| {
for i in 0..m {
for j in 0..n {
unsafe {
*matrix.get_unchecked_mut(i).get_unchecked_mut(j) = 1u8;
}
}
}
});
}
#[bench]
fn bench_vec_unsafe(b: &mut Bencher) {
let (m, n) = (10000, 10000);
let mut matrix = vec![0u8; n * m];
b.iter(|| {
for i in 0..m {
for j in 0..n {
unsafe { *matrix.get_unchecked_mut(i * n + j) = 1u8 };
}
}
});
}
#[bench]
fn bench_nalgebra(b: &mut Bencher) {
let (m, n) = (10000, 10000);
let mut matrix = DMatrixi32::from_vec(m, n, vec![0u8; n * m]);
b.iter(|| {
for i in 0..m {
for j in 0..n {
matrix[(i, j)] = 1u8;
}
}
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.