LINUX.ORG.RU

Правильно ли я пишу на Rust?

 , ,


1

7

Часто мелькает Rust и в новостях, и в темах. Решил попробовать переписать один тест с С на Rust. Для сравнения написал вариант и на C++. На Rust получилось в 4+ раза медленнее, чем на С и в 2+ раза медленнее, чем на C++. Есть подозрение, что я делаю что-то неправильно, но не знаю что. Помогите, пожалуйста, разобраться.

UPD. Мои цифры:

$ gcc c_v1.c -Ofast -march=native
$ ./a.out 3000
16.439091
-287.250083
$ g++ cpp_v2.cpp -Ofast -march=native
$ ./a.out 3000
31.3826
-287.25
$ rustc rust_v1.rs -C opt-level=3 -C target-cpu=native
$ ./rust_v1 3000
71.570172703s
-287.2500833333321
★★

Последнее исправление: andalevor (всего исправлений: 1)

тут мелькало мнение, что мы несём с собой умение кодить тем-то языком в другие, А вот они, как раз, требуют другого подхода ))) Или знаний ))) А так - benchmark на простую хрень.

n1rdeks
()
Ответ на: комментарий от n1rdeks

Алгоритм довольно примитивный, реализовал теми средствами, что нашёл по книгам и SO.

требуют другого подхода

Собственно, потому и создал тему.

andalevor ★★
() автор топика

Все обращения с проверкой. Вот и думай, почему так медленно.

t[i*n + j] = b[j*n + i]
c[i*n + j]
a[i*n + j]
a[i*n + j]
anonymous
()
Ответ на: комментарий от n1rdeks

тут мелькало мнение, что мы несём с собой умение кодить тем-то языком в другие

Это описывается термином «Программируйте с использованием языка, а не языке».

rumgot ★★★★★
()
Ответ на: комментарий от Legioner

Да, пробовал -O, потом нагуглил -C opt-level=3 -С target-cpu=native. Большой разницы не получилось.

andalevor ★★
() автор топика
Ответ на: комментарий от Eddy_Em

Ээ, я о таком даже не подумал… Просто указал теги, которые связаны с темой. Хм, думаете лучше убрать?

andalevor ★★
() автор топика
Ответ на: комментарий от andalevor

Хм, думаете лучше убрать?

Поздно, эта тема уже набрала потенциал «Русские физики выбирают Slackware».

hbee ★★★★
()

Не может быть, чтобы Rust был медленнее.

Deleted
()
Ответ на: комментарий от andalevor

Это не бенчи. Ну и у вас c++ код не эквивалентен сишному, поэтому и медленнее.

Ну и сравнивать нужно без fast-math, ибо это фича компилятора, а не языка.

RazrFalcon ★★★★★
()
Последнее исправление: RazrFalcon (всего исправлений: 1)

В расте проверка границ в векторе. Можешь ради интереса заменить квадратные скобки на at() в С++ и показать сколько получится

Ну или в расте get_unchecked+unsafe

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от RazrFalcon

Ну и сравнивать нужно без fast-math, ибо это фича компилятора

В Rust использовались аналогичные intrinsic.

Ну и у вас c++ код не эквивалентен сишному

Там рядом есть аналогичный. За вычетом restrict, которого нет в С++.

andalevor ★★
() автор топика

Характерно, что среди уже поступивших предложений от растосектантов есть советы типа «попробуй замедить код на C/C++», но пока нет совета, как ускорить код на Rust.

anonymous
()
Ответ на: комментарий от anonymous

Я посоветовал или то, или то, на выбор. Если применить совет, то будет понятно что в этом основная причина - проверки границ

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от anonymous

Уже несколько раз написали, что тормоза из-за bound checking. Просто ТС не понимает что сравнивает.

RazrFalcon ★★★★★
()
Ответ на: комментарий от menangen

Ты и есть автор этого язычка, что ли? Вроде ты один на ЛОРе пихаешь его во все дыры.

Вольдемар

anonymous
()

Как же уродливо выглядит эта лапша из get_unchecked, fmul_fast, fadd_fast. Ну ничего, может со следующим язычком повезет.

Арсений

anonymous
()
Ответ на: комментарий от vertexua

основная причина - проверки границ

Похоже на то. Замена [] на at() в варианте С++ дало такое же время как у Rust(71.75). Но вот наоборот что-то не совсем получается, я добавил get_unchecked, вариант Rust ускорился(41.40), но всё равно немного медленнее, чем С++. Может быть что-то ещё есть?

andalevor ★★
() автор топика

За раст не знаю, а vector<vector<double>> и malloc(N * N * sizeof(double)) - это разная раскладка по памяти. Код разный.

anonymous
()

Что получается с

    for (i, c_row) in c.chunks_exact_mut(n).enumerate() {
        for (j, c_val) in c_row.iter_mut().enumerate() {
            let a_row = &a[i*n..i*n+n];
            let t_row = &t[j*n..j*n+n];
            *c_val = a_row.iter().zip(t_row.iter()).map(|(&a,&t)| unsafe{ fmul_fast(a,t) } ).sum();
        }
    }
red75prim ★★★
()
Последнее исправление: red75prim (всего исправлений: 1)

Код на C отличается от кода на C++. Плюсовый код совсем не cache friendly. Но ведь это не важно, главное сишный код победил :)

andreyu ★★★★★
()
Ответ на: комментарий от RazrFalcon

Ну и сравнивать нужно без fast-math, ибо это фича компилятора, а не языка.

Лолшто? Ну давай не будем использовать O3 тоже этож тоже фича компилятора…

pon4ik ★★★★★
()
Ответ на: комментарий от andreyu

Но ведь это не важно, главное сишный код победил :)

Какие ещё голоса вы слышите у себя в голове?

Михаил

anonymous
()
Ответ на: комментарий от RazrFalcon

Ну и сравнивать нужно без fast-math, ибо это фича компилятора, а не языка.

Ибо очередной вакуумный недоязычек.

anonymous
()

Даже пожалуй вот так:

    for (i, c_row) in c.chunks_exact_mut(n).enumerate() {
        for (j, c_val) in c_row.iter_mut().enumerate() {
            let a_row = &a[i*n..i*n+n];
            let t_row = &t[j*n..j*n+n];
            *c_val = a_row.iter().zip(t_row.iter()).fold(0.0, |sum, (&a,&t)| unsafe{ fadd_fast(fmul_fast(a,t), sum) } );
        }
    }
red75prim ★★★
()
Ответ на: комментарий от andreyu

У меня на машине C-шный вариант ТС-а с restrict дает 22s, а он же, но без restrict — уже 28s. Разница только в наличии/отсутствии этого ключевого слова.

Так что отсутствие в C++ restrict-а, плюс дополнительные поля в std::vector, которые дают другую раскладку данных в памяти, вероятно, и приводят к такой разнице между C и C++.

eao197 ★★★★★
()
Ответ на: комментарий от pon4ik

Лолшто? Ну давай не будем использовать O3 тоже этож тоже фича компилятора…

Да уж, растишники поражают своей непосредственностью и наивностью.

anonymous
()
Ответ на: комментарий от pon4ik

Сделай векторам reserve - глядишь и догонишь сишную реализацию…

Там сразу делается resize, так что reserve уже не имеет смысла.

andreyu ★★★★★
()
Ответ на: комментарий от RazrFalcon

Напомни, где там у Rust стандарт на nightly фичи.

anonymous
()
Ответ на: комментарий от eao197

дополнительные поля в std::vector, которые дают другую раскладку данных в памяти, вероятно, и приводят к такой разнице между C и C++.

Именно. В плюсовом тесте измеряется не производительность языка, а производительность и размер кеша.

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

Я про вектор который копируется как минимум. Там анон выше уже подметил. Хотя я чёт второй раз не нашёл. Может это жизофрения?

pon4ik ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.