Форум сайта python.su
32
py.user.nextЗачем?
не, я запущу обычную работу со списком
py.user.nextНе в этом дело, из-за GIL в один момент времени работает только один питон код, остальные ждут. (вне зависимости потоко безопасен или нет)
из-за того что он не является потокобезопасным, GIL не даёт писать в него двум потокам сразу
[0.19081257699872367, 0.19112992100417614, 0.19095465500140563] [0.34615141399990534, 0.4059502980016987, 0.41062400300143054]
[0.19041931399988243, 0.19169438000244554, 0.19013405599980615] [0.47293585800071014, 0.4308473999990383, 0.42105118300241884]
[0.19209416800003964, 0.19082266299665207, 0.1915774919980322] [0.21658378299616743, 0.214570490999904, 0.2036629600042943]
[0.214321926003322, 0.2150491400025203, 0.2151023120022728] [0.23415685800136998, 0.22996015199896647, 0.22107067499746336]
Отредактировано o7412369815963 (Март 17, 2014 20:02:17)
Офлайн
32
py.user.next
Ваш пример заработал с нормальной скоростью, я просто перекинул кол-во циклов с теста на рабочий цикл,
т.е. тормоз возникает при создании потока и передаче локальной переменной, а без передачи - старт потока не тормозит. Похоже на баг?
У вас какие мысли?
[0.2196149789961055, 0.217363823998312, 0.21051921600155765] [0.23024766399612417, 0.23042914499819744, 0.22344746100134216]
import timeit import threading def lf(lst): for i in range(1000000): lst.append(i) def f1(): lst = [] lf(lst) lf(lst) def f2(): lst = [] lf(lst) t = threading.Thread(target=lf, args=(lst,)) t.start() t.join() def main(): t1 = timeit.Timer('f1()', 'from __main__ import f1') t2 = timeit.Timer('f2()', 'from __main__ import f2') for t in t1, t2: print(t.repeat(3, 1)) if __name__ == '__main__': main()
Офлайн
857
o7412369815963просто задайся вопросом, почему GIL вообще существует ?
Не в этом дело, из-за GIL в один момент времени работает только один питон код, остальные ждут. (вне зависимости потоко безопасен или нет)
o7412369815963ну, чтобы провести вычисленияpy.user.nextЗачем?
не, я запущу обычную работу со списком
o7412369815963дожидаться нужно завершения каждого потока
1) Одновременный запуск f1+f1 - работает в 2 раза медленней чем f1
[guest@localhost threadcmp]$ ./thread_сmp2.py
[0.3121845519999624, 0.3115454389990191, 0.30946677799875033]
[0.7022323320015857, 0.6940970079995168, 0.6638078140003927]
[guest@localhost threadcmp]$
o7412369815963а с чего они будут работать, если они не потокобезопасные ?
т.е. два “потокобезопасные” lst все равно тормозят - не работают в один момент.
o7412369815963это вообще зачем приведено ?
2) f1 запущенный в отдельном потоке работе почти с той же скоростью - с “потокобезопасным” lst
o7412369815963это где там третий ?
3) а тут вообще работа с lst идет из 3-х потоков, при этом скорость почти не падает.
o7412369815963
т.е. пункты 1 и 3 показывают что “не является потокобезопасным” ни причем.
#!/usr/bin/env python3 import timeit import threading lst = [] def lf(): del lst[:] for i in range(10000): lst.append(i) def f1(): lf() lf() def f2(): lf() t = threading.Thread(target=lf) t.start() #t.join() t = threading.Thread(target=lf) t.start() t.join() def main(): t1 = timeit.Timer('f1()', 'from __main__ import f1') t2 = timeit.Timer('f2()', 'from __main__ import f2') for t in t1, t2: print(t.repeat(3, 100)) if __name__ == '__main__': main()
[guest@localhost threadcmp]$ ./thread_сmp3.py
[0.3606604479991802, 0.3605620809994434, 0.36211792700123624]
[1.42527558799884, 1.4459451809998427, 1.4245262650001678]
[guest@localhost threadcmp]$
Отредактировано py.user.next (Март 18, 2014 11:16:48)
Офлайн
857
o7412369815963
Ваш пример заработал с нормальной скоростью, я просто перекинул кол-во циклов с теста на рабочий цикл,
#!/usr/bin/env python3 import timeit import threading def lf(lst): for i in range(1000): lst.append(i) def f1(): lst = [] lf(lst) lf(lst) def f2(): lst = [] lf(lst) t = threading.Thread(target=lf, args=(lst,)) t.start() t.join() def main(): t1 = timeit.Timer('f1()', 'from __main__ import f1') t2 = timeit.Timer('f2()', 'from __main__ import f2') for t in t1, t2: print(t.repeat(3, 1)) if __name__ == '__main__': main()
[guest@localhost threadcmp]$ ./thread_сmp5.py
[0.00031330900128523353, 0.00031356900035461877, 0.0003005090002261568]
[0.0009840080001595197, 0.0008377169997402234, 0.0008744890001253225]
[guest@localhost threadcmp]$
Офлайн
32
py.user.nextВсе правильно, уберите рабочий цикл вообще и получите время запуска потока.
я немножко скинул с рабочего цикла, и всё вернулось обратно
8.416175842285156e-05 8.153915405273438e-05 8.058547973632812e-05 7.987022399902344e-05
py.user.nextТ.е. вы не согласны с моим утверждением? Я сделал акцент не на GIL, а на термин “потокобезопасный”.o7412369815963просто задайся вопросом, почему GIL вообще существует ?
Не в этом дело, из-за GIL в один момент времени работает только один питон код, остальные ждут. (вне зависимости потоко безопасен или нет)
Офлайн
857
o7412369815963которое в программах никуда не девается
Все правильно, уберите рабочий цикл вообще и получите время запуска потока.
o7412369815963что оно работает не быстрее, не столько же, а медленнее
и что вы хотели показать своим тестом с 1 страницы?
o7412369815963речь-то не про потокобезопасность идёт, а про эффективность threading
Я сделал акцент не на GIL, а на термин “потокобезопасный”.
o7412369815963этот тест измеряет время работы со списком
вот тот же тест но без учета старта потока
Офлайн
32
py.user.nextНу в правильных программах обычно используют пулы потоков, поэтому во основное время работы программы это особо не влияет.
которое в программах никуда не девается
py.user.nextЧто-б не путать новичков, тут нужно обязательно оговаривать, что это только для питон “команд”, doza_and выше правильно написал:
то есть, если ты хочешь ускорить работу скрипта за счёт распараллеливания через threading, то оно может сработать в два раза медленнее (чаще не даст прироста по времени, а только усложнит код)
doza_andА у автора топика - сканер портов - io ожидание, т.е. потоки ему дадут профит, но для конкретного случая лучше использовать асинхронность.
Если вы будете запускать из питона долго работающие скомпилированные модули то получите значительное ускорение от применения threading
Офлайн
32
Если отвлечься от темы, то я думаю что питон был бы лучше без потоков и GIL, но с корутинами (greenlet),
как stackless python.
Гвидо упоминал, что ему нравится концепция gevent, но пока не знает как реализовать это в питоне (нативно).
Это было бы лучше чем pep3156.
Офлайн