Как быстрее выполнить поэлементное суммирование векторов различной длины? - PullRequest
0 голосов
/ 18 декабря 2018

Я пытаюсь найти более быстрый способ суммирования сотен этих структур, каждая из которых имеет разную длину:

pub struct StereoWaveform {
    pub l_buffer: Vec<f64>,
    pub r_buffer: Vec<f64>,
}

В настоящее время я делаю это так:

fn sum_all_waveforms(vec_wav: Vec<StereoWaveform>) -> StereoWaveform {
    let mut result = StereoWaveform::new(0);
    for wav in vec_wav {
        result.l_buffer = sum_vec(&result.l_buffer, wav.l_buffer);
        result.r_buffer = sum_vec(&result.r_buffer, wav.r_buffer)
    }

    result
}

fn sum_vec(a: &Vec<f64>, b: Vec<f64>) -> Vec<f64> {
    let vec_len = std::cmp::max(a.len(), b.len());
    let mut acc: Vec<f64> = vec![0.0; vec_len];
    for (i, e) in a.iter().zip_longest(&b).enumerate() {
        match e {
            itertools::EitherOrBoth::Both(v1, v2) => acc[i] = v1 + v2,
            itertools::EitherOrBoth::Left(e) => acc[i] = *e,
            itertools::EitherOrBoth::Right(e) => acc[i] = *e,
        }
    }

    acc
}

Я уже использую Rayon в проекте, поэтому было бы неплохо найти решение, используя это.

1 Ответ

0 голосов
/ 18 декабря 2018

sum_vec будет намного быстрее, если вы извлечете ветвь из цикла и перестанете создавать новые векторы.

fn sum_vec(a: &mut Vec<f64>, b: &[f64]) {
    if a.len() < b.len() {
        a.resize(b.len(), 0.0);
    }

    for (ai, bi) in a.iter_mut().zip(b) {
        *ai += *bi;
    }
}

или что-то такое

Извлечение resize таким образом, что выизменение размера только до максимальной длины будет еще быстрее, а сортировка vec_wav по длине (сначала самой длинной) должна улучшить предсказание ветвлений и локальность кэша.

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