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

时间:2019-01-03 19:25:46

标签: 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() {
        product += a[i] * b[i];
    }
    product
}

这需要两个向量ab(具有相同的长度),并进行逐元素乘法(向量a的值1与向量{{的值1)相乘1}},并将其添加到向量b的值2以及向量a的值2中,依此类推...)。

有没有更有效的方法?如果是,怎么办?

2 个答案:

答案 0 :(得分:3)

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

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

也就是说,您可以考虑更改函数以采用切片引用。这样,您可以传递Vec或数组:

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]));
}

另请参阅:

答案 1 :(得分:1)

我用rayonpacked_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);
}

This code in my Github。我希望这有帮助。