#python #python-3.x #multithreading #locks
#python #python-3.x #многопоточность #блокировки
Вопрос:
У меня есть исполняемый файл, который я использовал с различными начальными условиями. Это может выполняться сотни раз в зависимости от диапазона входных данных, которые я предоставляю. Ускорение этого процесса является первоочередной задачей, и поэтому я попытался использовать Thread и список блокировок.
Причиной списка блокировок является ограничение общей нагрузки на мой 6-ядерный процессор. Итак, я выбрал 3 блокировки для этого поста, но планирую использовать 5.
Я показываю три разные попытки, каждая из которых завершается неудачей по-разному.
- Диапазон входных данных никогда не увеличивается, т. Е. перед завершением программы используется только первая комбинация. (цикл над lock_list и, если lock.locked(): break)
- Каждый ввод выполняется n_locks раз. (цикл над lock_list)
- На самом деле не выполняется одновременно. (прерывание после каждой блокировки в lock_list)
Я показываю не фактические вызовы программы, а только способы, которыми я пытался реализовать Thread.
import threading
import time
import random
# Random seed for reproducibility
random.seed(123)
# Limit the number of active threads using locks
n_locks = 3
lock_list = list()
# Create a list that holds the desired number of locks
for i in range(n_locks):
lock_list.append(threading.Lock())
# Some dummy data for use in the function to be threaded
aa = [1, 2, 3, 4, 5, 6, 7, 8]
bb = [3, 4, 3, 4, 3, 4, 3, 4]
# The function to be used, where execution time may vary
def multiply(a, b):
print(a, b, a * b)
time.sleep(random.random() * 0.5)
# Show the inputs and outputs without threading
print('Unthreaded output...')
for d1, d2 in zip(aa, bb):
multiply(d1, d2)
# The same function, but using 'with lock:'
def multiply_threaded(l, a, b):
with l:
print(a, b, a * b)
time.sleep(random.random() * 1.0)
# Here's where I'm having a problem...
print('nThreaded Ouptut, 1st Try')
for d1, d2 in zip(aa, bb):
for lk in lock_list:
if lk.locked():
break
else:
threading.Thread(target=multiply_threaded, args=(lk, d1, d2)).start()
time.sleep(1.5)
print('The data set is never advanced...')
# Sleep to wait for the 2nd attempt...
# 2nd Try
print('nThreaded Ouptut, 2nd Try')
for d1, d2 in zip(aa, bb):
for lk in lock_list:
threading.Thread(target=multiply_threaded, args=(lk, d1, d2)).start()
time.sleep(5.5)
print('The data set is used 3 times...')
# 3rd Try
print('nThreaded Ouptut, 3rd Try')
for d1, d2 in zip(aa, bb):
for lk in lock_list:
threading.Thread(target=multiply_threaded, args=(lk, d1, d2)).start()
break
time.sleep(5.5)
print("Doesn't appear to be executed concurrently...")
Ниже приведен вывод:
Unthreaded output...
1 3 3
2 4 8
3 3 9
4 4 16
5 3 15
6 4 24
7 3 21
8 4 32
Threaded Ouptut, 1st Try
1 3 3
1 3 3
1 3 3
The data set is never advanced...
Threaded Ouptut, 2nd Try
1 3 3
1 3 3
1 3 3
2 4 8
2 4 8
2 4 8
3 3 9
4 4 16
3 3 9
5 3 15
4 4 16
3 3 9
5 3 15
4 4 16
5 3 15
6 4 24
6 4 24
6 4 24
7 3 21
7 3 21
8 4 32
8 4 32
7 3 21
8 4 32
The data set is used 3 times...
Threaded Ouptut, 3rd Try
1 3 3
2 4 8
3 3 9
4 4 16
5 3 15
6 4 24
7 3 21
8 4 32
Doesn't appear to be executed concurrently...
Process finished with exit code 0
То, что я ожидаю увидеть, похоже на вывод без обработки потоков и попытку # 3, за исключением того, что порядок не обязательно должен соответствовать порядку ввода, поскольку функция sleep использовалась для имитации загрузки исполняемого файла.
Спасибо, что нашли время для чтения!
РЕДАКТИРОВАТЬ: я использую os.system («C:my_exe.exe > C:my_output.txt ) в реальном потоке. Я не могу получить доступ к exe или вспомогательным файлам, когда они используются, поэтому я сделал копии, чтобы каждый поток мог использовать по одному.d
Комментарии:
1. Похоже, вам действительно нужен либо семафор , пул потоков (см.
multiprocessing.dummy
илиconcurrent.futures
), либо решение на основе процесса. Список блокировок не звучит как правильный путь.2. @user2357112, спасибо за информацию. Я проверю их. Пул потоков звучит многообещающе.