计算Rust中两个f64向量的点积的最快方法是什么?

计算Rust中两个f64向量的点积的最快方法是什么?,rust,Rust,我正在写一个Rust中神经网络的实现,并试图计算两个矩阵的点积。我有以下代码: fn dot_product(a: Vec<f64>, b: Vec<f64>) -> f64 { // Calculate the dot product of two vectors. asserteq!(a.len(), b.len()); let mut product: f64; for i in 0..a.len() { pro

我正在写一个Rust中神经网络的实现,并试图计算两个矩阵的点积。我有以下代码:

fn dot_product(a: Vec<f64>, b: Vec<f64>) -> f64 {
    // Calculate the dot product of two vectors.
    asserteq!(a.len(), b.len());
    let mut product: f64;
    for i in 0..a.len() {
        product += a[i] * b[i];
    }
    product
}
fn dot_乘积(a:Vec,b:Vec)->f64{
//计算两个向量的点积。
asserteq!(a.len(),b.len());
让mut产品:f64;
对于0..a.len()中的i{
产品+=a[i]*b[i];
}
产品
}
这取两个向量,
a
b
(长度相同)并执行元素相乘(将向量
a
的值1与向量
b
的值1相乘,并将其与向量
a
的值2和向量
b
的值2相加,以此类推……)


有没有更有效的方法来实现这一点,如果有,如何实现?

这并不是一个全面的一般性答案,但我想分享一些代码

除非我知道这是我的应用程序中的瓶颈,否则您的实现看起来很像我将要做的。然后我会研究更深奥的方法(也许)

这样说,你可以考虑改变你的函数来代替切片引用。这样,您可以传递

Vec
s或数组:

fn dot_product(a: &[f64], b: &[f64]) -> f64 {
    // Calculate the dot product of two vectors. 
    assert_eq!(a.len(), b.len()); 
    let mut product = 0.0;
    for i in 0..a.len() {
        product += a[i] * b[i];
    }
    product
}

fn main() {
    println!("{}", dot_product(&[1.0,2.0], &[3.0,4.0]));
    println!("{}", dot_product(&vec![1.0,2.0], &vec![3.0,4.0]));
}
另见:


这不是一个全面的一般性答案,但我想分享一点代码

除非我知道这是我的应用程序中的瓶颈,否则您的实现看起来很像我将要做的。然后我会研究更深奥的方法(也许)

这样说,你可以考虑改变你的函数来代替切片引用。这样,您可以传递

Vec
s或数组:

fn dot_product(a: &[f64], b: &[f64]) -> f64 {
    // Calculate the dot product of two vectors. 
    assert_eq!(a.len(), b.len()); 
    let mut product = 0.0;
    for i in 0..a.len() {
        product += a[i] * b[i];
    }
    product
}

fn main() {
    println!("{}", dot_product(&[1.0,2.0], &[3.0,4.0]));
    println!("{}", dot_product(&vec![1.0,2.0], &vec![3.0,4.0]));
}
另见:


我使用了
人造丝
压缩的simd
来计算点积和 找到了一种比英特尔MKL更快的方法:

extern crate packed_simd;
extern crate rayon;
extern crate time;

use packed_simd::f64x4;
use packed_simd::f64x8;
use rayon::prelude::*;
use std::vec::Vec;

fn main() {
    let n = 100000000;
    let x: Vec<f64> = vec![0.2; n];
    let y: Vec<f64> = vec![0.1; n];

    let res: f64 = x
        .par_chunks(8)
        .map(f64x8::from_slice_unaligned)
        .zip(y.par_chunks(8).map(f64x8::from_slice_unaligned))
        .map(|(a, b)| a * b)
        .sum::<f64x8>()
        .sum();
    println!("res: {}", res);
}
extern板条箱包装\u simd;
外部板条箱人造丝;
外置板条箱时间;
使用压缩单指令多数据::f64x4;
使用压缩单指令多数据::f64x8;
使用人造丝::前奏::*;
使用std::vec::vec;
fn main(){
设n=100000000;
设x:Vec=Vec![0.2;n];
设y:Vec=Vec![0.1;n];
设res:f64=x
.par_块(8)
.map(f64x8::从切片到未对齐)
.zip(y.par_chunks(8.map)(f64x8::from_slice_unaligned))
.地图(|(a,b)| a*b)
.sum::()
.sum();
println!(“res:{}”,res);
}

。我希望这有帮助

我使用
rayon
packed\u simd
计算点积和 找到了一种比英特尔MKL更快的方法:

extern crate packed_simd;
extern crate rayon;
extern crate time;

use packed_simd::f64x4;
use packed_simd::f64x8;
use rayon::prelude::*;
use std::vec::Vec;

fn main() {
    let n = 100000000;
    let x: Vec<f64> = vec![0.2; n];
    let y: Vec<f64> = vec![0.1; n];

    let res: f64 = x
        .par_chunks(8)
        .map(f64x8::from_slice_unaligned)
        .zip(y.par_chunks(8).map(f64x8::from_slice_unaligned))
        .map(|(a, b)| a * b)
        .sum::<f64x8>()
        .sum();
    println!("res: {}", res);
}
extern板条箱包装\u simd;
外部板条箱人造丝;
外置板条箱时间;
使用压缩单指令多数据::f64x4;
使用压缩单指令多数据::f64x8;
使用人造丝::前奏::*;
使用std::vec::vec;
fn main(){
设n=100000000;
设x:Vec=Vec![0.2;n];
设y:Vec=Vec![0.1;n];
设res:f64=x
.par_块(8)
.map(f64x8::从切片到未对齐)
.zip(y.par_chunks(8.map)(f64x8::from_slice_unaligned))
.地图(|(a,b)| a*b)
.sum::()
.sum();
println!(“res:{}”,res);
}

。我希望这有帮助

我觉得不错。我会一直使用它,直到你确信它是一个瓶颈。如果您已经确定需要尽可能快的速度,那么可以研究一下?您可以使用迭代器在一行中完成,如
a.into_iter().zip(b).map(|(a,b)| a*b).sum()
。但我希望它会相当快,而不是明显快(或慢),我觉得很好。我会一直使用它,直到你确信它是一个瓶颈。如果您已经确定需要尽可能快的速度,那么可以研究一下?您可以使用迭代器在一行中完成,如
a.into_iter().zip(b).map(|(a,b)| a*b).sum()
。但我希望它会相当快,而不是明显快(或慢);这是序曲的一部分。为什么时间箱在这里?你能把这与OPs代码的性能和另一个答案进行比较吗?为什么选择未对齐的
?不需要
使用std::vec::vec;这是序曲的一部分。为什么时间箱在这里?你能把这与OPs代码的性能和另一个答案进行比较吗?为什么选择未对齐的