Oberon space
General Category => Общий раздел => Тема начата: valexey_u от Сентябрь 09, 2016, 10:29:47 pm
-
Собственно я тут с ocaml играюсь, соответственно хотел удостовериться что он более-менее применим на императивных алгоритмов (коих большинство на моих задачах - изображение обработать, обработать данные с датчика (десятки и сотни миллионов элементов в массиве и проч), что не будет внезапных просадок производительности раз эдак в 10 по сравнению с плюсами.
Посему соорудил простейший тест - обычная сортировка пузырьком массива из 40000 элементов (int), массив первоначально отсортирован в обратном порядке, следовательно максимальное число перестановок потребуется.
Ну а поскольку сложно удержаться и не потестить другие ЯП, в итоге было потестировано: ocaml, c++, go, haskell (спасибо geniepro за все варианты кода), component pascal / blackbox.
Итоги выложил на github: https://github.com/valexey/bubble_test
По итогам скажу, что ocaml меня не разочаровал - производительность всего на 20 процентов ниже плюсовой, и достигается очень просто в отличие от haskell'я, где нужно побегать и попрыгать, чтобы он не сливал позорно более чем в 10 раз плюсам.
Ну а Компонентный Паскаль с отключенными проверками на выход за пределы массива, отстает от С++ более чем в 4 раза. См. табличку :-)
-
Кстати, результаты неплохо согласуются с http://lionet.info/pdf/2010-lev-walkin-erlang-experience.pdf
-
Кстати, в камловой реализации unsafe была ошибка, сейчас исправил - решение стало тормозней в 2 раза. Зато через обычный array работает быстрее чем ожидалось.
-
Что-то Go быстрее, чем я думал о_О чой-то он так???
Кстати, у тебя ведь в файле https://github.com/valexey/bubble_test/blob/master/ocaml/bubble_safe.ml используется в одном месте unsafe-операция:
let tmp = Array1.unsafe_get arr j in
то есть это тоже не совсем safe версия.
И ещё, в версии на КП нет двух распечаток массива. Хоть массив и небольшой, но всё же скорость программы на КП завышенная получается...
-
Кстати, в версии на с++ используется доступ к элементам вектора с проверкой индексов, интересно, если использовать метод arr.at(i) без таких проверок -- намного шустрее будет?
-
at() - это как раз с проверкой индексов, а operator [] -- без.
-
Ocaml-косяк поправлю, спасибо.
-
at() - это как раз с проверкой индексов, а operator [] -- без.
хм, и правда о_О http://www.cplusplus.com/reference/vector/vector/at/
std::vector::at
reference at (size_type n);
const_reference at (size_type n) const;
Access element
Returns a reference to the element at position n in the vector.
The function automatically checks whether n is within the bounds of valid elements in the vector, throwing an out_of_range exception if it is not (i.e., if n is greater than, or equal to, its size). This is in contrast with member operator[], that does not check against bounds.
-
Что-то Go быстрее, чем я думал о_О чой-то он так???
А они похоже научились в подобных случаях выпиливать проверки на выход за границы массива.
Кстати, у тебя ведь в файле https://github.com/valexey/bubble_test/blob/master/ocaml/bubble_safe.ml используется в одном месте unsafe-операция:
let tmp = Array1.unsafe_get arr j in
то есть это тоже не совсем safe версия.
Пофиксил. Еще раз тесты прогнал, результаты обновил.
И ещё, в версии на КП нет двух распечаток массива. Хоть массив и небольшой, но всё же скорость программы на КП завышенная получается...
Да, но я не представляю себе как на BB запущенном под Wine что-то эффективно вывести на stdout. То есть так как сейчас это значительно честнее чем если я буду сейчас колхозить на ББ любой вывод массивов в консоль или вообще в log ббшный.
-
Нет желающих rust добавить? :-)
-
Я хотел добавить вариант с супербыстрым хаскельным вектором из пакета Data.Vector, но получил точно такой же результат, как с IOUArray. Странно...
Но, вообще, получается, что хаскельный вариант работает на уровне сишной программы с компилятором GCC, а учитывая, что GHC в качестве бекэнда использует как раз GCC, то резервов для ускорения хаскельной программы с текущим компилятором нет.
Когда-то обещали сделать версию GHC под LLVM, но пока не слышно об успехах этого порта...
-
Кстати, valexey_u, попробуй скомпилять хаскельный вариант с флагом -fllvm -- у тебя же установлен LLVM, так что вроде должен подхватиться компилятором GHC...
-
Кстати, valexey_u, попробуй скомпилять хаскельный вариант с флагом -fllvm -- у тебя же установлен LLVM, так что вроде должен подхватиться компилятором GHC...
ghc от моего llvm тошнит и пучит:
$ ghc -fllvm -O3 bubble_unsafe_array.hs
[1 of 1] Compiling Main ( bubble_unsafe_array.hs, bubble_unsafe_array.o )
You are using an unsupported version of LLVM!
Currently only 3.7 is supported.
We will try though...
opt: /tmp/ghc22577_0/ghc_2.ll:15:29: error: expected comma after alias's type
@__stginit_Main = alias i8* bitcast (%__stginit_Main_struct* @__stginit_Main$def to i8*)
^
`opt' failed in phase `LLVM Optimiser'. (Exit code: 1)
У меня слишком свежий llvm.
-
Ну попробуй установить LLVM 3.7 )) Они наверное смогут параллельно работать...
-
Ну попробуй установить LLVM 3.7 )) Они наверное смогут параллельно работать...
Лениво :-) Попробуй лучше сам у себя все тесты прогнать. Я пока потихоньку готовлю вторую итерацию тестов. Чутка оптимизированных.
-
Я скачал LLVM 3.7, но какой-то он неполноценный -- нет программы opt в нём...
-
Я скачал LLVM 3.7, но какой-то он неполноценный -- нет программы opt в нём...
Ну, таким образом простому пользователю сия опция не доступна :-) Так что вычеркиваем.
-
Так я не понял -- эти LLVM-овцы специально сделали версию LLVM под винду без оптимизатора? а зачем он тогда такой нужен?
-
Этот LLVM под винду вообще какой-то неполноценный -- стандартных инклудников нет, нифига не компилирует с++-ный тест, например...
-
LLVM и не должен вроде как компилировать С++, С++ компилирует clang++ же.
-
ну там есть clang++.exe, но нет обычных хедер-файлов. Например, нет никаких iostream.*, vector.*...
-
Смеха ради реализовал версию на js. Отрабатывает за 3.4 секунды с выводом на консоль и 2.8 секунды без вывода. То есть работает быстрее чем ББ, и при этом является более безопасным (контроль за границами массива включен).
-
обновленная инфа - 2 секунды js.
-
А на своём трансляторе не пробовали?
-
Я подредактировал CP-шный вариант для простого Оберона:
MODULE Bubble;
IMPORT Out;
CONST n = 40000;
PROCEDURE PrintAll(arr: ARRAY OF INTEGER);
VAR i: INTEGER;
BEGIN
FOR i := 0 TO LEN(arr) - 1 DO
Out.Int(arr[i], 0);
Out.Ln
END
END PrintAll;
PROCEDURE DoIt*;
VAR
arr : ARRAY n OF INTEGER;
i, j, tmp : INTEGER;
BEGIN
FOR i := 0 TO n - 1 DO
arr[i] := n-i
END;
PrintAll(arr);
Out.String("---");
Out.Ln;
FOR i:=0 TO n-1 DO
FOR j:=0 TO n-2-i DO
tmp := arr[j];
IF arr[j] > arr[j+1] THEN
arr[j] := arr[j+1];
arr[j+1] := tmp
END
END
END;
PrintAll(arr)
END DoIt;
BEGIN
DoIt
END Bubble.
И прогнал через свой неполноценный транслятор. Оказалось, что на нём до сих пор не был реализован FOR. После добавления поддержки, транслятор выдал такое:
#include <stdlib.h>
#include <stddef.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#define n_cnst 40000
static void PrintAll_(int arr_[/*len0*/], int arr_len0) {
int i_;
for (i_ = 0; i_ <= arr_len0 - 1; ++i_) {
Out_Int(arr_[i_], 0);
Out_Ln();
}
}
extern void Bubble_DoIt(void) {
int arr_[n_cnst];
int i_;
int j_;
int tmp_;
for (i_ = 0; i_ <= n_cnst - 1; ++i_) {
arr_[i_] = n_cnst - i_;
}
PrintAll_(arr_, n_cnst);
Out_String("---", 4);
Out_Ln();
for (i_ = 0; i_ <= n_cnst - 1; ++i_) {
for (j_ = 0; j_ <= n_cnst - 2 - i_; ++j_) {
tmp_ = arr_[j_];
if (arr_[j_] > arr_[j_ + 1]) {
arr_[j_] = arr_[j_ + 1];
arr_[j_ + 1] = tmp_;
}
}
}
PrintAll_(arr_, n_cnst);
}
extern int main(int argc, char **argv) {
Bubble_DoIt();
return 0;
}
При сборке gcc -O3
программа работает 2.19 секунд
для сравнения, c++ вариант отработал за 2.1
и стабильно выполняется быстрей.
-
А на своём трансляторе не пробовали?
Пробовали. Те же 2 секунды примерно.
В общем, обновлю на гитхабе инфу и тесты, можно будет воспроизводить.
-
Я подредактировал CP-шный вариант для простого Оберона:
...
И прогнал через свой неполноценный транслятор. Оказалось, что на нём до сих пор не был реализован FOR. После добавления поддержки, транслятор выдал такое:
...
При сборке gcc -O3
программа работает 2.19 секунд
для сравнения, c++ вариант отработал за 2.1
и стабильно выполняется быстрей.
А где-то можно пощупать транслятор?
gcc на данном варианте тормоз, лучше щупать clang++.
-
Пока нигде, но скоро выложу на github.
-
gcc на данном варианте тормоз, лучше щупать clang++.
Действительно, clang даёт результат 1.35
-
gcc на данном варианте тормоз, лучше щупать clang++.
Действительно, clang даёт результат 1.35
Выходит, что твой кросскомпилер Оберон->C более эффективен, чем компилятор Блекбокса? Тебе надо срочно перевести Блекбокс на твой компилятор ))) Всё русское оберон-сообщество тебе огромное спасибо скажет. Правда, не заплатит ни копейки )))
-
gcc на данном варианте тормоз, лучше щупать clang++.
Действительно, clang даёт результат 1.35
Выходит, что твой кросскомпилер Оберон->C более эффективен, чем компилятор Блекбокса? Тебе надо срочно перевести Блекбокс на твой компилятор ))) Всё русское оберон-сообщество тебе огромное спасибо скажет. Правда, не заплатит ни копейки )))
Ну, тут же нет проверки индексов!
-
Выходит, что твой кросскомпилер Оберон->C более эффективен, чем компилятор Блекбокса? Тебе надо срочно перевести Блекбокс на твой компилятор ))) Всё русское оберон-сообщество тебе огромное спасибо скажет. Правда, не заплатит ни копейки )))
Ценю Ваш юмор.
Но если серьёзно, то, по-моему, лучше создать новую ОС-среду, полностью написанную сообществом и лишённую недостатков Блэкбокса.
-
Но если серьёзно, то, по-моему, лучше создать новую ОС-среду, полностью написанную сообществом и лишённую недостатков Блэкбокса.
Такой вариант уж точно не взлетит. Оберонщики и так уже разобщены кучей версий трансляторов, сред, ещё одна новая среда без библиотек и с несовместимым ни с кем транслятором -- этого никто не оценит...
-
Ну, тут же нет проверки индексов!
Как ни смешно, но не совсем правда. Поскольку транслируется в Си, то проверка индексов может быть дана сишным компилятором.
Сейчас проверил с опциями -fsanitize=address -fsanitize=undefined.
gcc 2.5
clang 3.6
Выход за границы массива срабатывает.
-
Ну, тут же нет проверки индексов!
Как ни смешно, но не совсем правда. Поскольку транслируется в Си, то проверка индексов может быть дана сишным компилятором.
Сейчас проверил с опциями -fsanitize=address -fsanitize=undefined.
gcc 2.5
clang 3.6
Выход за границы массива срабатывает.
Да, я знаю. Относительно недавняя фича в плане отлова UB в рантайме.
-
Попробовал в трёх браузерах выполнить оберон-жс вариант этого теста https://gist.github.com/valexey/e559764622f1b35ce9da799dbcc9e286
У файрфокса действительно какой-то аномально быстрый интерпретатор яваскрипта, скорость лучше чем у GCC и хаскеля:
Firefox 45.3.0 (Tor 6.0.4): 1.4 сек
Iron 52.0.2750.0 (на базе Chrome): 6.3 сек
Opera 12.18: 31 сек
-
А если убрать вывод в с++? У меня при перенаправлении вывода в /dev/null время сокращалось раза в 3
-
Проверил у себя на Blackbox 1.6. Собрать без проверок границ не получилось, но с проверкой получилось 3.35 секунд, что подозрительно, так как у меня все теcты, кроме этого, проходят медленней, чем у Алексея.
Процессор: Intel Core i3-4160
Вывод в консоль: отключён.
g++ -fsanitize=address -O3 : 1.6 сек
clang++ -fsanitize=address -O3 : 1.8 сек
Go : 1.8 сек
BlackBox : 3.4 сек
Нет ли тут злого умысла ;D?
-
А если убрать вывод в с++? У меня при перенаправлении вывода в /dev/null время сокращалось раза в 3
Проверил с GCC -- разница всего в 11% (делал вывод в файл, а не в /dev/null).
На хаскелле практически не было разницы между выводом в файл и без вывода -- разница в пределах погрешности измерения.
c++ с выводом в файл: 1.6 сек
c++ без вывода в файл: 1.4 сек
хаскель с выводом в файл: 1.7 сек
хаскель без вывода в файл: 1.7 сек
-
Проверил у себя на Blackbox 1.6. Собрать без проверок границ не получилось, но с проверкой получилось 3.35 секунд, что подозрительно, так как у меня все теcты, кроме этого, проходят медленней, чем у Алексея.
Процессор: Intel Core i3-4160
Вывод в консоль: отключён.
g++ -fsanitize=address -O3 : 1.6 сек
clang++ -fsanitize=address -O3 : 1.8 сек
Go : 1.8 сек
BlackBox : 3.4 сек
Нет ли тут злого умысла ;D?
Конечно есть! Я, как истинный злодей, запускал BB под Wine в линухе. Ну и система у меня 64битная. О чем и указал в ридмишке.
А какая конфигурация у тебя?
-
Да, до кучи у меня ББ версии 1.7.
-
Ubuntu 16.04 64 bit
wine 1.6.2
Blackbox 1.6
Но в GNU/Linux 64 разрядной версии Blackbox - http://oberon.molpit.com/packs/bbcb_1.7~a1.8_amd64.deb (http://oberon.molpit.com/packs/bbcb_1.7~a1.8_amd64.deb) у меня получился тот же результат.
Как выяснилось, вывод у меня тормозил из-за того, что я использую Terminator в качестве эмулятора терминала. В стандартном гномовском вывод не имеет весомой доли.
-
Ubuntu 16.04 64 bit
wine 1.6.2
Blackbox 1.6
Но в GNU/Linux 64 разрядной версии Blackbox - http://oberon.molpit.com/packs/bbcb_1.7~a1.8_amd64.deb (http://oberon.molpit.com/packs/bbcb_1.7~a1.8_amd64.deb) у меня получился тот же результат.
Как выяснилось, вывод у меня тормозил из-за того, что я использую Terminator в качестве эмулятора терминала. В стандартном гномовском вывод не имеет весомой доли.
Дык ББ вроде 64битной версии не бывает. Компилятор не умеет 64бита делать. То есть один фиг бинарь исполняется 32битный.
Все тесты (кроме ББшного) тестируются как time ./program > /dev/null
Вообще же вывод сделан для того, чтобы:
1) Проверить алгоритм на корректность (и это, кстати, окупилось - одна окамловая версия гнала пургу из за моей невнимательности и незнания языка).
2) Чтобы шибко умный компилятор не выкинул цикл с рассчетом.
-
Тогда всё сходится. Без вывода остальные программы работают быстрей, не только в ББ.
clang (o7 -> c) - 0.49 сек
clang++ (cpp) - 0.53 сек
-
Тогда всё сходится. Без вывода остальные программы работают быстрей, не только в ББ.
clang (o7 -> c) - 0.49 сек
clang++ (cpp) - 0.53 сек
Корректней это назвать "с выводом" с т.з. программы, просто вывод перенаправлен в /dev/null. Но программа то честно пишет в stdout и не в курсе, что можно было бы ничего не писать, ничего не считать, и никто этого не заметил бы :-)
Просто /dev/null это очень быстрое устройство вывода, в отличие от вывода на консоль например. Или вывода в обычный файл.
-
Ubuntu 16.04 64 bit
wine 1.6.2
Blackbox 1.6
Но в GNU/Linux 64 разрядной версии Blackbox - http://oberon.molpit.com/packs/bbcb_1.7~a1.8_amd64.deb (http://oberon.molpit.com/packs/bbcb_1.7~a1.8_amd64.deb) у меня получился тот же результат.
Как выяснилось, вывод у меня тормозил из-за того, что я использую Terminator в качестве эмулятора терминала. В стандартном гномовском вывод не имеет весомой доли.
Не стоит обманываться названием пакета. Это просто сборка для amd64. Приходится разделять из-за проблем с зависимостями. А сам ББ внутри 32-битный. Проблема из-за того, что не существует пакета gnome-icon-theme-full:i386. Поэтому пакета для bbcb оказалось теперь два. Но зато человеческий диалог выбора файлов :)
-
У меня на bbcb для Ubuntu 14.04 на Core i5-3337U CPU @ 1.80GHz × 4
С проверкой 6.23
Без проверки 3.23
Алексей, еще бы на топовых компиляторах протестировать
https://software.intel.com/en-us/intel-compilers
А этот тест выдерживает критику QWERTYProgrammer ?
http://forum.oberoncore.ru/viewtopic.php?f=61&t=4482&p=82278&hilit=ifort#p82223
-
У меня на bbcb для Ubuntu 14.04 на Core i5-3337U CPU @ 1.80GHz × 4
С проверкой 6.23
Без проверки 3.23
Алексей, еще бы на топовых компиляторах протестировать
https://software.intel.com/en-us/intel-compilers
А этот тест выдерживает критику QWERTYProgrammer ?
http://forum.oberoncore.ru/viewtopic.php?f=61&t=4482&p=82278&hilit=ifort#p82223
Ну, интелёвый компилер далеко не всегда сильно у актуального gcc or clang выигрывает, иногда даже проигрывает.
Да, и изначально тут тест производительности не столько компиляторов и языков как таковых, а связки человек + язык + компилятор. То есть вот да, в меру криворукий программист написал какой-то код на языке X и собрал это дело компилятором Y, какой результат производительности он получит и насколько нетривиальные шаги ему придется предпринять, чтобы ускорить этот код?
Например отключить проверку индексов для данного конкретного массива - это простой ход. Простой и относительно безопасный. Отключить проверку индексов для целого модуля - ход тоже простой, но уже не столь безопасный. Если же единственный выход это вообще отключить проверку индексов для всей программы - это совсем плохо.
Если можно пользоваться стандартным массивом (из языка, или стандартной либы) и он не тормозит, это хоршо. Если приходится искать стороннюю либу для массива - это уже плохо. Если же приходится самостоятельно писать код например на Си, оформлять это дело в либу и подключать к проекту на вашем языке для подобных вещей - это ещё хуже.
Если наивная реализация работает достаточно быстро - это хорошо. Если для скорости приходится полностю переписывать реализацию (при том, что алгоритм остается другой) и он становится уже не столь прозрачным для читателя - это плохо.
Если приемлемая производительность достигнута с первого раза - это хорошо, если с десятой попытки, после консультации на форумах, после чтения мануалов и ковырянии в либах и опциях компилятора - это плохо.
Ну и так далее.
Ну и тестировал я в первую очередь пригодность ocaml и haskell для подобных алгоритмов (с мутабельными данными, а точнее - массивами), камло оказалось более пригодным, хотя haskell в итоге показал результат (по скорости) не хуже.
PS. не забываем, что этот алгоритм - банальная сортировка пузырьком. простейший алгоритм. Если даже для подобного приходится как-то изворачиваться, тратить кучу времени и экспериментов для достижения производительности, переписывать код в другой манере и так далее, то связка язык + компилятор не очень хороша как минимум для быстрого прототипирования, так как по итогам такого прототипирования сама идея может быть забракована, ибо прототип покажет, что производительность получается СЛИШКОМ низкая. Либо придется тратить время на нетривиальное вылизывание кода в сторону производительности, но это противоречит самой идее быстрого прототипирования - это уже не быстро.
-
Я тут немного пошаманил на предмет замера в А2.
MODULE BubbleTest;
IMPORT Kernel, Heaps, Objects, Commands, Machine;
CONST n = 40000;
PROCEDURE{ALIGNED(16), ALIGNSTACK(16)} DoIt*( context: Commands.Context );
BEGIN
DoSafe(context);
DoUnchecked(context);
END DoIt;
PROCEDURE{ALIGNED(16), ALIGNSTACK(16)} DoSafe*( context: Commands.Context );
VAR
i, j, tmp: LONGINT;
mhz, time0, time: HUGEINT;
arr: ARRAY n OF LONGINT;
BEGIN
mhz := EstimateCpuClockrate( );
time0 := Objects.CurrentProcessTime( );
FOR i := 0 TO n - 1 DO
arr[ i ] := n - i;
END;
FOR i := 0 TO n - 1 DO
FOR j := 0 TO n - 2 - i DO
IF arr[ j ] > arr[ j + 1 ] THEN
tmp := arr[ j ];
arr[ j ] := arr[ j + 1 ];
arr[ j + 1 ] := tmp;
END;
END;
END;
time := Objects.CurrentProcessTime( );
context.out.String("Safe: ");
context.out.Int( ( time - time0 ) DIV ( 1000 * mhz), 1 ); context.out.String(" ms");
context.out.Ln;
END DoSafe;
PROCEDURE{ALIGNED(16), ALIGNSTACK(16)} DoUnchecked*( context: Commands.Context );
VAR
i, j, tmp: LONGINT;
mhz, time0, time: HUGEINT;
arr{ALIGNED(16)}: ARRAY n OF LONGINT;
BEGIN{UNCHECKED}
mhz := EstimateCpuClockrate( );
time0 := Objects.CurrentProcessTime( );
FOR i := 0 TO n - 1 DO
arr[ i ] := n - i;
END;
FOR i := 0 TO n - 1 DO
FOR j := 0 TO n - 2 - i DO
IF arr[ j ] > arr[ j + 1 ] THEN
tmp := arr[ j ];
arr[ j ] := arr[ j + 1 ];
arr[ j + 1 ] := tmp;
END;
END;
END;
time := Objects.CurrentProcessTime( );
context.out.String("Unchecked: ");
context.out.Int( ( time - time0 ) DIV ( 1000 * mhz), 1 ); context.out.String(" ms");
context.out.Ln;
END DoUnchecked;
PROCEDURE EstimateCpuClockrate(): HUGEINT;
VAR
timer : Kernel.Timer; milliTimer : Kernel.MilliTimer;
startTime, endTime, timeDiff : HUGEINT;
nbrOfGcRuns : LONGINT;
BEGIN
NEW(timer); nbrOfGcRuns := Heaps.Ngc;
Kernel.SetTimer(milliTimer, 1000);
startTime := Machine.GetTimer();
WHILE ~Kernel.Expired(milliTimer) DO
timer.Sleep(1);
IF nbrOfGcRuns # Heaps.Ngc THEN RETURN 0; END;
END;
endTime := Machine.GetTimer();
IF nbrOfGcRuns # Heaps.Ngc THEN RETURN 0; END;
timeDiff := endTime - startTime;
RETURN SHORT (timeDiff DIV (1000*1000));
END EstimateCpuClockrate;
END BubbleTest.
BubbleTest.DoIt ~
BubbleTest.DoSafe~
BubbleTest.DoUnchecked~
SystemTools.Free BubbleTest ~
-
i, j, tmp: LONGINT;
arr: ARRAY n OF LONGINT;
У тебя тут длинные целые (64 бита, видимо?), а у валексея и у меня просто целые (32 бита вроде). Это может влиять на скорость...
-
i, j, tmp: LONGINT;
arr: ARRAY n OF LONGINT;
У тебя тут длинные целые (64 бита, видимо?), а у валексея и у меня просто целые (32 бита вроде). Это может влиять на скорость...
В Обероне LONGINT разве не 32 битные?
-
i, j, tmp: LONGINT;
arr: ARRAY n OF LONGINT;
У тебя тут длинные целые (64 бита, видимо?), а у валексея и у меня просто целые (32 бита вроде). Это может влиять на скорость...
В Активном Обероне LONGINT = SIGNED32, HUGEINT=SIGNED64
-
Попробовал сделать на Rust'е, работает ну очень как-то медленно.
fn print_all(arr: &[i32]) {
for i in 0..arr.len() {
println!("{}", arr[i]);
}
}
fn main() {
const N: usize = 40000;
let mut arr: [i32; N] = [0; N];
for i in 0..arr.len() { arr[i] = (N-i) as i32; }
print_all(&arr);
println!("-----");
for i in 0..arr.len() {
for j in 0..arr.len() - 1 - i {
let tmp = arr[j];
if arr[j] > arr[j + 1] {
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
print_all(&arr);
}
-
Попробовал сделать на Rust'е, работает ну очень как-то медленно.
Это я её без опции -O компилил, с этой опцией стало весьма шустро работать.
Алексей, затести и добавь в таблицу результатов ))
-
Можно ещё ускорить с опцией
-C lto
Возможно, из-за того, что 0..arr.len()
является синтаксическим сахаром для
std::ops::Range {start: 0, end: arr.len()}
-
Нет желающих rust добавить? :-)
Ну я добавил, и что, и где? :o