Комментарии 43
Почему именно Rust? На Си будет проще и компиляторы более доступны. Может потому что это стало "стильно-модно-молодёжно", переписывать всё на Rust?
Если вы переписали часть кода на другой язык, то этот код уже не на Python. Так что "ускорить код на Python" звучит как-то сомнительно для меня.
А тема древняя как Java, там тоже выносили критичный код в нативные библиотеки, что ломает принцип Java: "write once, run anywhere", под которым язык рекламировали.
В нативные библиотеки Java выносили код, который должен был работать напрямую с тем, к чему у Java доступа нет, например специфичным железом (считыватель ключей-таблеток) - потому это и называется Java Native Interface. А не потому, что там было быстрей.
Насколько мне известно, по бенчмаркам, несложные арифметические операции типа работы с простыми числами примерно одинаково по производительности выполняются и на компилируемых, и на современных интерпретируемых языках (типа Python, Javascript или PHP). поэтому, да, хотелось бы узнать, почему такая большая разница в скорости у автора.
Даже с числами есть оверхед. Например, в Python все целые числа поддерживают длинную арифметику. При небольших вычислениях это незаметно, но если нужно написать числодробилку, то разница большая.
Насколько мне известно, по бенчмаркам, несложные арифметические операции
типа работы с простыми числами примерно одинаково по производительности
выполняются и на компилируемых, и на современных интерпретируемых
языках (типа Python, Javascript или PHP). поэтому, да, хотелось бы узнать, почему такая большая разница в скорости у автора.
Как раз в скриптах без JIT огромный оверхед, который чаще всего проявляется именно в таком tight CPU bound коде.
компиляторы более доступныА не подскажете, на какой платформе есть Python, но нет Rust?
Я осознаю, что сферический код в вакууме, который должен запускаться на всём, возможно лучше писать на C, но здесь всё же модуль питонячий, и в отрыве от Python он мало смысла имеет (это будет как минимум другой проект).
Что значит «почему именно раст». Потому что гарантированно не покрашится и не потечет, потому что точно не будет гейзенбагов при работе с потоками. Любой одной из этих причин уже достаточно.
Раст на порядок: надёжнее, проще, легче в освоении и самое главное - современный.
Проще отловить любые потенциальные ошибки, проще скомпилировать любой проект (попробуйте это сделать с вашим обилием компиляторов и разных тулзов вроде смейк с почти нулевого порога входа и нулевого опыта), язык намного проще доступен (не беря в расчёт лайфтаймы и турбофиш) и предоставляет современный и удобный уровень взаимодействия с пользователем. (одни инструменты карго чего только стоят или описания ошибок которые тебя не только погладят но ещё и соску дадут)
Си будет быстрее на х процентов в рантайме - но не всегда проще.
Раст на порядок: надёжнее, проще, легче в освоении и самое главное — современный.
Я смеял и хохотался с выделенного. Против всего остального возразить нечего.
Обычно с этого смеются только те, кто раст не осилил. ;)
Как по мне относительно для всех.
Он и правда легче в освоении, если считать язык освоенным когда удаётся начать писать на нём надёжный код.
На Сях начинающий свой первый код напишет, конечно же, быстро. Этот код будет содержать несколько уязвимостей use after free, переполнения буфера и обязательную проблему с кодировками.
А что не так с турбофишем? В плане сложности. Просто странноватое написание да и только.
"и самое главное - современный "
Это действительно самое главное в Rust?
Например, потому что для Си такие инструкции уже есть.
На си будет проще? Это вряд ли. Пока код настолько простой - без разницы, но если код объемный, искать неожиданные ошибки в rust легче (многие из них в rust не возникают).
Речь о ситуации, если вы знаете языки примерно одинаково.
Я не хочу негативить, но о чем статья?
На главный вопрос - почему функция медленная - так и не дали. Что в ней далёкого от идеала, почему оно такое медленное итд. Лишь пару очень воздушных объяснений что мол видите ли виновата архитектура пайтона. А попробовать оптимизировать функцию на самом пайтоне видимо сил уже не хватило, раз она такая далёкая от, идеала.
Всё оставшиеся пункты статьи это пункты вроде - 'как сделать нативный модуль для питона'. Подойдёт для какого нибудь FAQ или ReadMe на главной странице.
На мой взгляд, вполне понятно, о чём статья: инструкция как быстро и просто прикрутить к программе на Python кусочки кода на Rust'е.
Конкретная функция в ней выбрана только для того, чтобы инструкция была с конкретным примером.
Вариант с оптимизацией кода обычно требует большей квалификации программиста или бОльших затрат времени, чем такое переписывание горячего кода. Поэтому такой подход выглядит целесообразным при quick'n'dirty пртотипировании. (Впрочем, и оптимизированные функции на Rust'е будут несколько быстрее, но статья, как я понял, не об этом.)
При прототипировании уже накосячили. Счётчики могут переполнятся. Полагаю, молча.
Портирование не всегда проще оптимизации внутри языка. Пример вообще неудачный - у Питона неограниченные целые, код работает всегда. При портировании типы стали ограниченные - источник ошибок при написании (уже одну нашли) и при использовании (головная боль начнётся на больших входах). Такой себе quick&dirty.
Просто если не козырнуть перфомансом в тайтле (и это будет единственное, что хипстеры и ребята с неокрепшей психикой запомнят из статьи), то можно случайно увидеть какое-то плохо читаемое адище, которое уже никак не пролазит в рамки быстрого прототипирования и требует костыли и пересборку под каждую платформу. А пайтон выбран как единственная ниша, где можно хоть как-то конкурировать "из коробки" на задачах, которые IRL возможно в перфомансе нуждаются вообще в последнюю очередь или для них уже давно есть более подходящая библиотечка на сях, если речь про числодробилки, а если нет, то узкое место будет - источник этих 100к записей)
Автор как будто не уверен в значении терминов ядро, процессор, процесс, задача, поток и использует их наугад. С точкой читаю "В сравнении с первоначальной функцией Python с единственным процессором" — процессор? внутри функции? Ой-ой.
Или вот: "Для разделения всех задач на несколько ядер можно использовать несколько процессоров". На диво бессмысленное утверждение. У моего настольного компьютера 6 физических ядер плюс 6 виртуальных, и всего один CPU — получается, я никак не могу его использовать для ускорения расчетов, он же всего один? Может быть, автор имел в виду не процессоры, а ядра, физические и виртуальные? Или потоки? Наверно, автор хотел сказать "Для разделения всех задач на несколько потоков можно использовать несколько ядер" — утверждение столь же верное, сколь и тривиальное. Спасибо, кэп.
Такой вот перевод
>Для разделения всех задач на несколько ядер можно использовать несколько процессоров
>In our case we could opt for using multiple processes to divide all tasks over multiple cores in stead of the default 1
Автор как будто не уверен в значении терминов ядро, процессор, процесс, задача, поток и использует их наугад.
У моего настольного компьютера 6 физических ядер плюс 6 виртуальных, и всего один CPU
физические ядра - абстракция уровня микроархитектуры (о ней знает процессор).
виртуальные ядра - абстракция уровня архитектуры (о ней знает ваша ОС).
То есть у вас 6 физических ядер и 12 виртуальных (по 2 виртуальных ядра на каждом физическом).
А то, что у вас написано - примерно: "я купил 2 упаковки яиц и ещё 18 яиц". Мягко говоря странновато.
del
Конечно раст это хорошо, но почему это именно то что нужно? Потому что популярно и модно? Почему не numba, которая подобные хотспоты должна разгонять в лет?
Псс.. Потому, что так можно переманить питонистов с игрушечного языка программирования на взрослый.
Согласен. Rust уж очень сильно от питона отличается и требует другой квалификации.
Если и переходить, то на Julia переходить. Писать можно в питоновском стиле (и даже лучше), а производительность будет такая же, как на rust. Это если number-crunching'ом заниматься
Первая же ошибка, повторенная и в коде на rust — проверка значений выше int(sqrt(n)) как делителей.
Первая ошибка - это использование перебора делителей вместо решета Эратосфена. Всё остальное уже несущественно.
вместо решета Эратосфена
… загруженного из файла.
Задание: переставить биты числа в обратном порядке.
Оптимальное решение: таблица поиска на все 256 char'ов. Если нужны 2-4-8-байтные числа -«переставлять» биты с помощью той же таблицы, побайтово.
Можно сколько угодно сидеть и оптимизировать решение «в лоб», но индексация массива всё равно быстрее.
Если уж грузить из файла, то лучше сразу список простых. С ним и работать проще, и места на 30% меньше занимает в бинарном виде...
По-моему, главная глупость статьи в изначальном предположении "программист на python обязательно умеет писать на rust", и далее она же мимикрировала в знание С или других языков. Особенно в свете того, что в школе уже иногда дают python. Конечно, можно написать ТЗ тому, кто знает и умеет - но это тоже отдельное умение.
Ну и конечно, никаких попыток разобраться "почему ж оно тормозит" и "можно ли хоть что-то сделать".
Когда-то в конце 1990х добрался я до l0phtcrack 1.0 опен-сорсного, он был в разы медленнее того, что они продавали. Простая замена связных списков на массив - дала заметный прирост, далее были игры с openssl, разбиением алгоритма шифрования на части так, чтоб в кэш 486 помещался (т.е. считаем 1000 первых половинок, потом 1000 вторых половинок алгоритма), выявление зависимости быстродействия от последовательности .о в makefile... Да, я поднял быстродействие в разы, хоть и не достиг уровня коммерческой версии. Но это были всего-то поверхностные изменения, а не "погружение в алгоритм шифрования вместе с оптимизацией на ассемблере на 486/pentium".
Хоть автор и делает оговорку, что код не оптимизирован - это не освобождает его от ответственности. Для Python существует множество вариантов оптимизации. В частности преобразование в машинный код во время исполнения - PyPy. И совершенно не факт, что оно не будет быстрее.
Нельзя просто так взять неоптимизированный код, перекинуть его на другой ЯП в таком же неоптимизированном виде и сказать "смотрите, оно стало быстрее!".
UPD: Увидел, что это блог "SkillFactory" - всё встало на свои места.
Чем больше диапазон, тем меньше скорость функции.
А разве скорость это не количество операций за единицу времени? При большем входном параметре у меня процессор начинает медленнее выполнять операции?
Статья не раскрывает темы. Всё же вначале нужно было выжать максимум из python, естественно начиная с алгоритма, так как в таком виде она годится только для школьника, постигающего азы программирования. И уже потом максимально оптимизировать в rust. Хотя выбор языка из принципа "модно-молодежно" тоже сомнителен.
Вывод: пишите на брейнфаке, и да пребудет с вами сила!
Как при помощи Rust в 150 раз ускорить код на Python