почему многопоточность python работает как один поток на macos? - PullRequest
3 голосов
/ 01 августа 2020

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

Вот мой код:

import threading
import time
from Crypto.Hash import MD2

def calc_func(text):
    t1 = time.time()
    h = MD2.new()
    total = 10000000
    old_text =text
    for n in range(total):
        h.update(text)
        text = h.hexdigest()
    print(f"thread done: old_text={old_text} new_text={text}, time={time.time()-t1}sec")

def do_3threads():
    t0 = time.time()
    texts = ["abcd", "abcde", "abcdef"]
    ths = []
    for text in texts:
        th = threading.Thread(target=calc_func, args=(text,))
        th.start()
        ths.append(th)
    for th in ths:
        th.join()
    print(f"main done: {time.time()-t0}sec")

def do_single():
    texts = ["abcd", "abcde", "abcdef"]
    for text in texts:
        calc_func(text)

if __name__ == "__main__":
    print("=== 3 threads ===")
    do_3threads()
    print("=== 1 thread ===")
    do_single()

Результат потрясающий, каждый поток занимает примерно в 4 раза больше времени. принимает, если однопоточный:

=== 3 threads ===
thread done: old_text=abcdef new_text=e8f636b1893f12abe956dc019294e923, time=25.460321187973022sec
thread done: old_text=abcd new_text=0d6cae713809c923475ea50dbfbb2c13, time=25.47859835624695sec
thread done: old_text=abcde new_text=cd028131bc5e161671a1c91c62e80f6a, time=25.4807870388031sec
main done: 25.481309175491333sec
=== 1 thread ===
thread done: old_text=abcd new_text=0d6cae713809c923475ea50dbfbb2c13, time=6.393985033035278sec
thread done: old_text=abcde new_text=cd028131bc5e161671a1c91c62e80f6a, time=6.5472939014434814sec
thread done: old_text=abcdef new_text=e8f636b1893f12abe956dc019294e923, time=6.483690977096558sec

Это совсем не то, что я ожидал. Эта задача, очевидно, является задачей с интенсивным использованием ЦП, поэтому я ожидаю, что при многопоточности каждый поток может занять около 6,5 секунд, и весь процесс немного займет это, вместо этого фактически потребовалось ~ 25,5 секунд, что даже хуже, чем в однопоточном режиме, который составляет ~ 20 секунд.

Среда: python 3.7.7, macos 10.15.5, ЦП - 8-ядерный Intel i9, память 16 ГБ.

Может кто-нибудь мне это объяснить? Любой ввод приветствуется.

1 Ответ

1 голос
/ 01 августа 2020

Очевидно, что эта задача требует интенсивного использования ЦП.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...