Действительно ли ThreadPoolExecutor в python работает - PullRequest
0 голосов
/ 07 мая 2020

Я пытаюсь писать быстрее python код, используя несколько потоков. Я не хочу использовать ProcessPoolExecutor для сохранения потребления памяти.

Итак, когда я использую ThreadPoolExecutor.map, который отображает итератор на функцию. Это действительно не работает, время, затрачиваемое на код, на самом деле не увеличивается. Затем я прочитал о GIL в python, мой вопрос: если GIL применяется ко всем, почему они создают ThreadPoolExecutor.map, или есть ли лучшая идея использовать ThreadPoolExecutor.map.

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

import concurrent.futures
import math

PRIMES = [
    112272535095293,
    112582705942171,
    112272535095293,
    115280095190773,
    115797848077099,
    1099726899285419]

def is_prime(n):
    if n < 2:
        return False
    if n == 2:
        return True
    if n % 2 == 0:
        return False

    sqrt_n = int(math.floor(math.sqrt(n)))
    for i in range(3, sqrt_n + 1, 2):
        if n % i == 0:
            return False
    return True

def main():
    with concurrent.futures.ThreadPoolExecutor(max_workers = 4) as executor:
        future= executor.map(is_prime, PRIMES)

    print(future.result())

if __name__ == '__main__':
    main()

1 Ответ

0 голосов
/ 07 мая 2020

Как вы заметили, GIL означает, что единовременно может использоваться только 1 ЦП и только 1 «настоящий» поток. Таким образом, использование пула потоков не ускорит код, связанный с процессором. Однако многие функции в стандартной библиотеке и других сторонних библиотеках добровольно освобождают GIL, если они блокируются при вводе-выводе.

Например, если у вас есть код, пытающийся загрузить много вещей из inte rnet вы можете создать пул потоков Python. Когда один поток делает запрос на загрузку чего-либо и ожидает ответа, он может (в зависимости от того, какую библиотеку вы используете для выполнения своих HTTP-запросов) освободить GIL и дать другому потоку возможность запуститься. Это означает, что вы можете сделать очень много запросов до того, как любой из них будет завершен, а затем каждый поток Python будет снова разбужен, когда их ответ станет доступен. Такая Python многопоточность может привести к огромному повышению производительности.

...