Глобальная блокировка интерпретатора Python или GIL позволяет только одному потоку удерживать управление интерпретатором Python. Поскольку ваша функция calculateScore
может быть привязана к процессору и требует, чтобы интерпретатор выполнял свой байтовый код, вы можете немного выиграть от использования потоковой передачи. С другой стороны, если бы он выполнял в основном операции ввода-вывода, он бы отказался от GIL большую часть своего времени выполнения, позволяя запускать другие потоки. Но, похоже, здесь дело обстоит не так. Вероятно, вам следует использовать ProcessPoolExecutor
из concurrent.futures
(попробуйте оба способа и посмотрите):
def main():
with ProcessPoolExecutor(max_workers=None) as executor:
the_futures = {}
for i in range(len(fullAnalysis)):
text = fullAnalysis['QueryText'][i]
arg = 'most_similar'+ ' ' + text
future = executor.submit(calculateScore, arg)
the_futures[future] = i # map future to request
for future in as_completed(the_futures): # results as they become available not necessarily the order of submission
i = the_futures[future] # the original index
result = future.result() # the result
Если вы опустите параметр max_workers
(или укажите значение None
) из конструктор ProcessPoolExecutor
, по умолчанию будет количество процессоров, установленных на вашем компьютере (неплохое значение по умолчанию). Нет смысла указывать значение, превышающее количество имеющихся у вас процессоров.
Если вам не нужно ie возвращать будущее к исходному запросу, тогда the_futures
может быть просто списком к которому Но проще всего даже не беспокоиться об использовании метода as_completed
:
def main():
with ProcessPoolExecutor(max_workers=5) as executor:
the_futures = []
for i in range(len(fullAnalysis)):
text = fullAnalysis['QueryText'][i]
arg = 'most_similar'+ ' ' + text
future = executor.submit(calculateScore, arg)
the_futures.append(future)
# wait for the completion of all the results and return them all:
results = [f.result() for f in the_futures()] # results in creation order
return results
Следует отметить, что код, запускающий функции ProcessPoolExecutor
, должен находиться в блоке, управляемом if __name__ = '__main__':
. Если это не так, вы попадете в рекурсивный l oop, где каждый подпроцесс будет запускать ProcessPoolExecutor
. Но, похоже, здесь так и есть. Возможно, вы все время хотели использовать ProcessPoolExecutor
?
Также:
Я не знаю, что это за строка ...
model = gensim.models.Word2Vec.load('w2v_model_bigdata')
... в функция calculateStore
делает. Это может быть один оператор с привязкой к вводу-выводу. Но, похоже, это то, что не меняется от звонка к звонку. Если это так и model
не изменяется в функции, не следует ли вынести этот оператор из функции и вычислить только один раз? Тогда эта функция явно будет работать быстрее (и будет явно связана с процессором).
Также:
Блок исключений ...
except KeyError as ke:
#print(str(ke) + "\n")
inp = input()
... вызывает недоумение . Вы вводите значение, которое никогда не будет использоваться, прямо перед возвратом. Если это нужно для приостановки выполнения, сообщение об ошибке не выводится.