Глобальная блокировка интерпретатора (GIL)

Введение

Примеры

  • 3

    Multiprocessing.Pool

    На вопрос, как использовать потоки в Python, ответ прост: «Не используйте вместо этого процессы». Модуль многопроцессорной обработки позволяет создавать процессы с синтаксисом, аналогичным синтаксису создания потоков, но я предпочитаю использовать их удобный объект Pool.

    Используя код , который Дэвид Бизли первым используется , чтобы показать опасность нитей против GIL , мы перепишем его с помощью multiprocessing.Pool :

    Код Дэвида Бизли, который показал проблемы с GIL-потоками

     from threading import Thread
    import time
    def countdown(n):
        while n > 0:
            n -= 1
    
    COUNT = 10000000
    
    t1 = Thread(target=countdown,args=(COUNT/2,))
    t2 = Thread(target=countdown,args=(COUNT/2,))
    start = time.time()
    t1.start();t2.start()
    t1.join();t2.join()
    end = time.time()
    print end-start
    
     

    Переписано с использованием мультипроцессинга.
     import multiprocessing
    import time
    def countdown(n):
        while n > 0:
            n -= 1
    
    COUNT = 10000000
    
    start = time.time()
    with multiprocessing.Pool as pool:
        pool.map(countdown, [COUNT/2, COUNT/2])
    
        pool.close()
        pool.join()
    
    end = time.time()
    print(end-start)
    
     

    Вместо создания потоков это создает новые процессы. Поскольку каждый процесс имеет свой собственный интерпретатор, коллизии GIL отсутствуют. multiprocessing.Pool откроет столько процессов, сколько имеется ядер на машине, хотя в приведенном выше примере потребуется только два. В реальном сценарии вы хотите, чтобы ваш список был как минимум такой же длины, как и процессоры на вашей машине. Пул будет запускать функцию, которую вы скажете ему запускать с каждым аргументом, вплоть до числа процессов, которые он создает. Когда функция завершится, все остальные функции в списке будут запущены в этом процессе.

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

  • 2

    Cython Nogil:

    Cython является альтернативным интерпретатором Python. Он использует GIL, но позволяет отключить его. Смотрите их документации

    В качестве примера, используя код , который Дэвид Бизли первым используется , чтобы показать опасность нитей против GIL , мы перепишем его с помощью nogil:

    Код Дэвида Бизли, который показал проблемы с GIL-потоками

     from threading import Thread
    import time
    def countdown(n):
        while n > 0:
            n -= 1
    
    COUNT = 10000000
    
    t1 = Thread(target=countdown,args=(COUNT/2,))
    t2 = Thread(target=countdown,args=(COUNT/2,))
    start = time.time()
    t1.start();t2.start()
    t1.join();t2.join()
    end = time.time()
    print end-start
    
     

    Переписано с использованием nogil (ТОЛЬКО РАБОТАЕТ НА ЦИФОНЕ):

     from threading import Thread
    import time
    def countdown(n):
        while n > 0:
            n -= 1
    
    COUNT = 10000000
    
    with nogil:
        t1 = Thread(target=countdown,args=(COUNT/2,))
        t2 = Thread(target=countdown,args=(COUNT/2,))
        start = time.time()
        t1.start();t2.start()
        t1.join();t2.join()
    
    end = time.time()
    print end-start
    
     

    Это так просто, если вы используете Cython. Обратите внимание, что в документации сказано, что вы должны быть уверены, что не меняете объекты Python:

    Код в теле оператора не должен каким-либо образом манипулировать объектами Python и не должен вызывать ничего, что манипулирует объектами Python без предварительного повторного получения GIL. Cython в настоящее время не проверяет это.

Синтаксис

Параметры

Примечания