Какой самый быстрый способ вычислить скалярное произведение двух векторов f64 в Rust? - PullRequest
0 голосов
/ 03 января 2019

Я пишу реализацию нейронной сети в 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
}

Это занимает два вектора, a и b (одинаковой длины) и выполняет поэлементное умножение (умножение значения 1 вектора a на значение 1 вектора b и добавление его к значению 2 вектора a и значение 2 вектора b и т. Д.).

Есть ли более эффективный способ сделать это, и если да, то как?

Ответы [ 2 ]

0 голосов
/ 20 мая 2019

Я использовал rayon и packed_simd для вычисления точечного произведения и нашел способ быстрее, чем Intel 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);
}

Этот код в моем Github .Надеюсь, это поможет.

0 голосов
/ 03 января 2019

Это не полный исчерпывающий ответ, но я хотел бы поделиться небольшим кодом.

Ваша реализация выглядит так же, как и я, если бы я не знал, что это является узким местом в моем приложении.Затем я рассмотрю более эзотерические подходы (возможно, SIMD ).

Тем не менее, вы можете изменить свою функцию, чтобы вместо нее использовать ссылки на фрагменты.Таким образом, вы можете передать 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]));
}

См. Также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...