面试题答案
一键面试struct Matrix {
data: Vec<Vec<i32>>,
}
impl std::ops::AddAssign for Matrix {
fn add_assign(&mut self, other: Matrix) {
for (i, row) in self.data.iter_mut().enumerate() {
for (j, cell) in row.iter_mut().enumerate() {
*cell += other.data[i][j];
}
}
}
}
大规模矩阵运算时的性能问题
- 内存访问模式:
Vec<Vec<i32>>
这种二维结构在内存中不是连续存储的,会导致缓存不友好,随机访问性能较差。 - 迭代开销:嵌套的
for
循环在大规模矩阵运算时,迭代的开销较大。
优化策略
- 使用一维数组存储:将二维矩阵数据存储在一个一维
Vec<i32>
中,通过计算偏移量来访问对应元素,提高内存连续性,增强缓存利用率。 - 并行计算:利用多线程并行计算矩阵加法,将矩阵划分成多个部分,每个线程负责一部分的加法运算。
Benchmark测试
首先添加 cargo-bench
依赖,在 Cargo.toml
中添加:
[dev-dependencies]
bencher = "0.5.1"
编写基准测试代码:
#[cfg(test)]
mod benches {
use super::*;
use bencher::Bencher;
#[bench]
fn bench_matrix_addition(b: &mut Bencher) {
let mut matrix1 = Matrix {
data: vec![vec![1; 1000]; 1000],
};
let matrix2 = Matrix {
data: vec![vec![1; 1000]; 1000],
};
b.iter(|| matrix1 += matrix2.clone());
}
}
优化后:
struct MatrixOptimized {
data: Vec<i32>,
rows: usize,
cols: usize,
}
impl MatrixOptimized {
fn new(rows: usize, cols: usize) -> Self {
MatrixOptimized {
data: vec![0; rows * cols],
rows,
cols,
}
}
fn get_index(&self, row: usize, col: usize) -> usize {
row * self.cols + col
}
}
impl std::ops::AddAssign for MatrixOptimized {
fn add_assign(&mut self, other: MatrixOptimized) {
for i in 0..self.data.len() {
self.data[i] += other.data[i];
}
}
}
#[cfg(test)]
mod benches {
use super::*;
use bencher::Bencher;
#[bench]
fn bench_matrix_addition_optimized(b: &mut Bencher) {
let mut matrix1 = MatrixOptimized::new(1000, 1000);
let matrix2 = MatrixOptimized::new(1000, 1000);
b.iter(|| matrix1 += matrix2.clone());
}
}
运行 cargo bench
即可看到优化前后的性能差异。