Страницы

Поиск по вопросам

пятница, 27 декабря 2019 г.

Почему параллельный map работает на порядки медленнее последовательного?

#распараллеливание #rust


Хотел поэкспериментировать с параллельностью в Rust, в частности - сравнить последовательный
map из стандартной библиотеки и параллельный map из rayon. Вот код бенчмарка:

#![feature(test)]

extern crate test;
extern crate rand;
extern crate rayon;

#[cfg(test)]
mod tests {
    use rayon::prelude::*;
    use test::Bencher;

    #[bench]
    fn iter_test(b: &mut Bencher) {
        let vec: Vec = (0..20000).collect();

        b.iter(|| -> i64 {
            vec.iter().map(|x| x * x).sum()
        });
    }

    #[bench]
    fn par_iter_test(b: &mut Bencher) {
        let vec: Vec = (0..20000).collect();

        b.iter(|| -> i64 {
            vec.par_iter().map(|x| x * x).sum()
        });
    }
}


Результаты:

running 2 tests
test tests::iter_test     ... bench:       8,061 ns/iter (+/- 2,606)
test tests::par_iter_test ... bench:   1,915,544 ns/iter (+/- 40,786,648)


Почему параллельный map настолько медленный? Я конечно понимаю, что на распараллеливание
какие-то ресурсы тратятся, но не столько же. Может последовательный map как-то компилятор
оптимизирует? Как тогда написать бенчмарк, на примере которого можно будет почувствовать
преимущество параллельного map?

P. S. Пробовал под передавать в map рекурсивный факториал - результаты отличаются
не так сильно, но последовательный map все равно быстрее.
    


Ответы

Ответ 1



Потому что накладные расходы на распараллеливание на порядки превышают полезную нагрузку в данном случае. На моей машине (Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz) параллельная версия начинает обгонять на 16 000 000 значений, а на 32 000 000 обгон достигает ~25% и дальше уже сильно не растёт mkpankov@mkpankov-OptiPlex-9020 /tmp/rtest [master *] ± % ➜ cargo bench # 16000000 Compiling rtest v0.1.0 (file:///tmp/rtest) Finished release [optimized] target(s) in 0.70 secs Running target/release/deps/rtest-14d3cc84caf097ae running 2 tests test tests::iter_test ... bench: 8,749,482 ns/iter (+/- 465,264) test tests::par_iter_test ... bench: 7,700,212 ns/iter (+/- 2,354,146) test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured mkpankov@mkpankov-OptiPlex-9020 /tmp/rtest [master *] ± % ➜ cargo bench # 32000000 Compiling rtest v0.1.0 (file:///tmp/rtest) Finished release [optimized] target(s) in 0.70 secs Running target/release/deps/rtest-14d3cc84caf097ae running 2 tests test tests::iter_test ... bench: 17,497,810 ns/iter (+/- 765,301) test tests::par_iter_test ... bench: 13,826,826 ns/iter (+/- 1,615,362) test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured mkpankov@mkpankov-OptiPlex-9020 /tmp/rtest [master *] ± % ➜ cargo bench # 64000000 Compiling rtest v0.1.0 (file:///tmp/rtest) Finished release [optimized] target(s) in 0.71 secs Running target/release/deps/rtest-14d3cc84caf097ae running 2 tests test tests::iter_test ... bench: 34,855,214 ns/iter (+/- 1,047,213) test tests::par_iter_test ... bench: 27,347,082 ns/iter (+/- 236,451) test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured

Комментариев нет:

Отправить комментарий