170 похожих чатов

Кто может, присоединяйтесь, может кто сразу знает корректные ответы на

все вопросы.

@cutwater Тегаю Вас, извините заранее.
Ваши ссылки прочитал.
Мне всетаки хочется разобраться в безобразии, которое творит питон с потоками. Что там вообще происходит в многопоточности, в частности.

Я создал небольшую песочницу для понимания скорости работы алгоритмов. Понятно, что функция map тут в лидерах, это не оспаривается. Интересуют немного другие приколы.

Код для поиграться здесь. https://pastebin.com/AjJCzmvS

simple_counter Correct 0.008378744125366211
simple_counter_for_gen Correct 0.010663986206054688
simple_counter_for Correct 0.014650106430053711
recursive_counter Correct 0.009507179260253906
recursive_counter_for Correct 0.009685039520263672 <- Вопрос здесь
full_recursive_iter Correct 0.05898594856262207
counter_threads Correct 0.015019893646240234

Вопрос 1: почему recursive_counter_for быстрее генератора simple_counter_for_gen и быстрее simple_counter_for, причем по второму не ожидал, что на столько.

Я знаю, что на мелких расчетах, производимых на месте в функции с небольшими входными данными, рекурсивные функции быстрее. Но тут даже с относительно большими данными без использования систем управления потоками, данные функции оказываются, хоть и незначительно, но быстрее.

Есть объяснения происходящему в питоне как со стороны GIL, так и с других сторон?

PS: Я не настоящий сварщик программист на питоне. Я немного из другой области выпал, поэтому до сих пор считаю себя новичком.

питон 3.11.1 x64

33 ответов

25 просмотров

а вопросы "почему быстрее" учитывают разницу в версиях питона?

Так, ну до того как можно будет что-то обсуждать про скорость, выкинь time.time для замеров и возьми что-нибудь, считаютщее не погоду на марсе. perf_counter, например. А лучше возьми timeit чтобы считало не один раз а несколько. Всё-таки у нас ОС многозадачная.

Alex-Xorm Автор вопроса
evle
Так, ну до того как можно будет что-то обсуждать п...

тоже самое получается, я думаю о профилировании вообще, чтобы понять почему так. Это песочница, по ссылке выше, тоже можете поиграться и подкинуть перфкоунтер.

Alex-Xorm Автор вопроса
evle
Так, ну до того как можно будет что-то обсуждать п...

я вообще за идеи, почему может быть так, и где тут собака порылась, что не смотря на все дополнительные накладные расходы в вызовах функций полно непоняток по последоввательному исполнению кода.

Alex Xorm
тоже самое получается, я думаю о профилировании во...

Ну, я вижу просто вывод про то что map всех победил и подозреваю, что что-то должно быть не так с методикой подсчёта. В сотый раз проверять одно и то же мне уже как-то не очень интересно, но погадать на адекватно полученных результатах можно бы.

Alex-Xorm Автор вопроса
evle
Ну, я вижу просто вывод про то что map всех побед...

Я, как это ни странно, за гадания, как раз. Реально интересно почему происходит именно так, что последовательный вызов со слайсами, оказывается, в среднем, быстрее. За map, я не переживаю, он будет в лидерах именно при этой реализации, это функция C, ее не догнать из питона никак.

Функция на Си не показатель. Она может быть плохо написана (чет душню, и в целом хуйню написал)

Alex-Xorm Автор вопроса
quantum super position
Функция на Си не показатель. Она может быть плохо ...

Ну про map, вопросов нет, там все очень хорошо. Тут вопросы в связке с GIL образуются.

quantum super position
я ставлю на некорректные замеры

Я пока, что называется, not convinced, что функции делают одно и то же. Возможно, что мне станет достаточно скучно, что под кофе почитаю и сравню. :-)

Alex-Xorm Автор вопроса
quantum super position
я ставлю на некорректные замеры

Я код выложил. Я займусь техниками изучения производительности функций в питоне, так же как и профилированием, но на это уйдёт время, которого не так много. Если у Вас есть возможность, то код можно подпилить, под корректные для Вас измерения. Я тут в роли просящего и настаивать ни на чем не имею права. Мне просто нужны идеи, почему так происходит. Идея 1: некорректные метрики производительности.

А можно как-то сформулировать, в чём была идея этих рекурсивных функций? Типа просто нарубить задачу на подзадачи и деревом посчитать? Ну и да, что за global div и нафига оно так при том, что это по сути своей константа?

Alex Xorm
Я код выложил. Я займусь техниками изучения произв...

И да, так задумано? def recursive_counter_for(s, r=False): ... ret += recursive_counter(s[j:i], True) То есть оно какое-то не сильно рекурсивное.

Alex-Xorm Автор вопроса
evle
А можно как-то сформулировать, в чём была идея эти...

Идея в том, что иногда, для жеской оптимизации вычислений, я не использую многопоточность в ручном виде, а именно использую подход, нарубить по кусочкам и скормить функции, рекурсивно или нет, это вопрос вторичный. Мое понимание работы стека, а каком то месте, видимо не правильно. Я задался вопросом, почему скорость работы некоторых функций не совпадает с пониманием большинства в "затыках с GIL". Далее я решил просто написать тест, и посмотреть, а что будет, если я задачу обработки данных попробую решить разными способами, которые я знаю. Ну и уперся в вопрос, WTF? (ЧЗНХ?), что за странная оптимизация байткода и ускорение, где его, по идее, быть не должно.

Alex-Xorm Автор вопроса
evle
И да, так задумано? def recursive_counter_for(s, r...

Абсолютно верно, это не рекурсия, а просто использование последовательного вызова функции впринципе. Чтобы не захламлять пространство имен, сделано так.

Alex Xorm
Абсолютно верно, это не рекурсия, а просто использ...

В смысле "не захламлять пространство имён"? Не понял.

Alex-Xorm Автор вопроса
evle
И да, так задумано? def recursive_counter_for(s, r...

Чистая рекурсия там тоже есть. Но в данном примере, т.к. количество данных велико, она будет неэффективна. Рекурсии эффективны в расчетах внутри, при малом входящем размере данных и малом исходящем. Иначе можно столкнуться с ожиданием аллокатора и как раз выпасть на GIL.

Alex Xorm
Идея в том, что иногда, для жеской оптимизации выч...

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

Ну, я подумал, что "не захламлять" было про div и на всякий случай удивился.

Alex-Xorm Автор вопроса
evle
Ну, я подумал, что "не захламлять" было про div и ...

А, нет. Писать глобал это привычка. Сразу видно, что внутри функции или класса я использую что-то внешнее, без написания длинных докстрингов и не раздувая параметры.

Alex Xorm
А, нет. Писать глобал это привычка. Сразу видно, ч...

Ну, это скорее наоборот, путь к проблемам, чем что-то хорошее. :⁠-⁠D

Alex-Xorm Автор вопроса
evle
Ну, это скорее наоборот, путь к проблемам, чем что...

Это уровень: "Все трюки сделаны профессионалами, не повторяйте это дома в проде." Много параметров глобала использовать - это вообще ужасная практика. Но использовать константу внешнего мира внутри функции, почему бы и нет?

Alex Xorm
Это уровень: "Все трюки сделаны профессионалами, н...

Не, у тебя тут просто типичная константа и заглавными буквами без всякого global смотрелась бы прекрасно. А так у тебя есть блестящая возможность опечаткой поменять глобальную недоконстанту и потом долго об этом не узнать.

Alex-Xorm Автор вопроса
evle
Не, у тебя тут просто типичная константа и заглавн...

Кстати, вопрос по пути. У меня есть .env и всякие конфиги, я из них все загружаю в переменные глобальные. Глобалы могут быть изменены на ходу, тоесть в конфигах стартовые параметры. Это как практичней делать? Именно от туда у меня пошла привычка глобалы делать.

Alex Xorm
Я код выложил. Я займусь техниками изучения произв...

особо в код не вникал, но после замены time.time на time.perfcounter результаты соответствуют ожиданиям

Alex-Xorm Автор вопроса
evle
Ой, это, видимо, сюда: https://t.me/advice17/6

Это немного не мой прикол. Я из настроек тащу стартовые параметры, которые изменяются по ходу исполнения кода. В Глобал я ток такое засовываю. Кстати, так и было в коде, ссылку на который я давал выше, в стартовом сообщении. Я менял переменную div, для того, чтобы понять, где какая функция начнёт лидировать на каком количестве потоков. В код я это не включил.

Alex Xorm
Это немного не мой прикол. Я из настроек тащу ста...

Ну, примерно так делает джанга со своими настройками. Для чего-то в продакшене — плохая идея как раз по тем причинам, что описаны в посте. Для всяких исследовательских экспедиций, где заморачиваться с нормальным настройками смысла мало — ок. Но это по сути всё ещё глобальные константы, просто с некой отложенной инициализацией, так что нормально их оставлять тупо заглавными. Ключевое слово global тут сбивает с толку и делать так точно не стоит.

Alex-Xorm Автор вопроса
evle
Ну, примерно так делает джанга со своими настройка...

Учту, спасибо. Буду понимать, что нормальная практика, именно, описанная Вами.

evle
Ой, это, видимо, сюда: https://t.me/advice17/6

Ну там рассказали про солид и про то, как НЕ делать. А как делать то?

Похожие вопросы

Обсуждают сегодня

30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
6
Всем привет! Имеется функция: function IsValidChar(ch: UTF8Char): Boolean; var i: Integer; ValidChars: AnsiString; begin ValidChars := 'abcdefghijklmnopqrstuvwxyzABCDE...
Евгений
44
Карта сайта