Как решить проблемы со спин-блокировкой с многопоточным python?

Я пишу многопоточное приложение на Python и столкнулся с проблемой, когда время ядра резко возрастает. Используя perf, я вижу, что это действительно спин-блокировка:

  54.89%         python  [kernel.kallsyms]            [k] __ticket_spin_lock

Код, вызывающий спин-блокировку, приведен ниже:

for i in range(0, my_uuids_len):
    while threading.active_count() >= concurrency:
      time.sleep(0.1)

    threading.Thread(target=read_benchmark,args=(read_times,my_uuids.pop(),)).start()
    counter += 1

person Community    schedule 01.03.2014    source источник
comment
Неудивительно, что вы проводите там время, спин-блокировки предназначены для ожидания, пока вы не сможете прогрессировать. Пробовали ли вы увеличить лимит concurrency?   -  person Leeor    schedule 01.03.2014
comment
Старайтесь не использовать спин-блокировки, если только... на самом деле ничего.   -  person Martin James    schedule 01.03.2014
comment
Весь смысл спин-блокировок заключается в том, чтобы избежать дорогостоящих вызовов ядра - вызов sleep внутри одного, очевидно, не очень хорошая идея. Кроме того, спин-блокировки - это низкоуровневая оптимизация производительности, которую вы не должны использовать в своем коде самостоятельно, это для библиотеки, которая реализует wait/notify (что вам действительно нужно здесь).   -  person Voo    schedule 01.03.2014
comment
@josten Пропустил запись perf и в итоге сосредоточился на показанном вами цикле - цикл while следует переписать, чтобы избежать всех этих ненужных переключений контекста. Однако это не объясняет, что ваша спин-блокировка вызывает себя.   -  person Voo    schedule 01.03.2014
comment
Какую реализацию Python вы используете, и можете ли вы определить, на какой спин-блокировке работает ваш код?   -  person Michael Foukarakis    schedule 01.04.2014


Ответы (1)


Я действительно не знаю, что это за спин-блокировка, но сколько потоков вы запускаете?

Как насчет запускать не потоки, а процессы?

взгляните на многопроцессорность или в Python 3.

from concurrent.futures import ThreadPoolExecutor # should do exactly what your code does now
from concurrent.futures import ProcessPoolExecutor # I recommend that

Если ProcessPoolExecutor не решает проблему, то переключение между потоками Python не должно быть проблемой.

person User    schedule 01.03.2014
comment
Хм, у вас может быть 5000 потоков в C-Python? Я думал, что у вас может быть только 800+ что-то. - person User; 01.03.2014
comment
Это разрешено, когда вы используете процессы? Тогда это может быть проблема внутренней потоковой обработки Python. Я не ясно видел, что мы знаем источник проблемы. - person User; 01.03.2014