Потоки против нормальных в Python - PullRequest
0 голосов
/ 25 ноября 2018
import time
import threading
import multiprocessing

def fn():
    '''since all 3 functions were identical you can just use one ...'''
    x = 0
    while  x < 100000000:
        x += 1




def TEST_THREADS():
    new_thread1  = threading.Thread(target = fn , args = ())
    new_thread2  = threading.Thread(target = fn, args = ())
    new_thread1.start()
    new_thread2.start()
    new_thread1.join()
    new_thread2.join()

def TEST_NORMAL():
    fn()
    fn()

def TEST_MULTIPROCESSING():
    new_thread1  = multiprocessing.Process(target = fn , args = ())
    new_thread2  = multiprocessing.Process(target = fn, args = ())
    new_thread1.start()
    new_thread2.start()
    new_thread1.join()
    new_thread2.join()
if __name__ == "__main__":  
    '''It is very important to use name == __main__ guard code with threads         and multiprocessing'''
    import timeit
    print ("Time to Run 1x: %0.2fs"%(timeit.timeit(fn,number=1),))
    print ("NORMAL:%0.2fs"%(timeit.timeit(TEST_NORMAL,number=1),))
    print ("Threaded: %0.2fs"%(timeit.timeit(TEST_THREADS,number=1),))
    print ("Multiprocessing: %0.2fs"%    (timeit.timeit(TEST_MULTIPROCESSING,number=1),))

Я нашел интересное представление о GIL и Threading: http://www.dabeaz.com/python/NewGIL.pdf Итак, я написал похожий код, но получаю странные результаты:

Time to Run 1x: 11.60s
NORMAL:23.15s
Threaded: 23.43s
Multiprocessing: 1.19s

Как видите, метод потоков работал быстреечем обычно один или равно (0,28 с не слишком много).Я нашел несколько статей и похожих вопросов, но везде результаты были похожи на презентацию - многопоточность медленнее.

Я что-то делаю не так или новая версия Python улучшила GIL?

Однако многопроцессорность тоже сошла с умаи работать в 20 раз быстрее других!Это нормально?

1 Ответ

0 голосов
/ 25 ноября 2018

В современном Python GIL не так плох, как раньше (ранее можно было ожидать, что многопоточный код с привязкой к ЦП будет работать значительно медленнее), поэтому ваши наблюдения примерно такие, как вы ожидаете.

По личному опыту, куча потоков с привязкой к процессору в CPython 2.7 может использовать почти два ядра процессора и выполнять работу менее чем на 75%.Поскольку они переписали GIL в CPython 3.2 , эти накладные расходы в основном исчезли;вы по-прежнему не получаете ничего от потоков, но в итоге вы используете вычислительные ресурсы 1-1,1 ядра и выполняете 95-100% работы ядра.По сути, GIL больше не замедляет код, но он все еще не позволяет вам получить выгоду от многопоточности с кодом, привязанным к ЦП, который не основан на сторонних GIL-релизных расширениях, таких как numpy.

...