Многопоточность снижает производительность задачи сопоставления строк - Python
У меня есть два списка - один из 100 000 комментариев ("ответы") и один из 10000 комментариев ("письма"). 10000 букв - это подмножество 100000 ответов, но измененные непредсказуемым образом. Мне нужно выяснить, какие из них соответствуют, и решил использовать SequenceMatcher из встроенной библиотеки difflib.
Это отлично справляется с работой, и ей удается найти похожие строки, но на данный момент они невероятно интенсивны. Он должен сравнивать каждый ответ на каждое письмо, что приводит к миллиарду сравнений.
Я пробовал многопоточность, скажем, с 16 потоками (в системе Ryzen с 8 физическими ядрами), но производительность в каждом матче снижается в 16 раз, а общая производительность сопоставима.
Для одного потока требуется две минуты, чтобы найти соответствующий "ответ" на каждую букву. Когда это нарезается, одно совпадение может занять полчаса. Загрузка ЦП не улучшается вообще. Вот часть моего кода, ограничивающая производительность:
import pandas as pd
import numpy as np
import time
import threading
import queue
def how_similar(some_string, phrase):
return SequenceMatcher(None, some_string, phrase).ratio()
def queue_letters():
global letters_queue
letters_queue = queue.Queue()
for i, j in letters.iterrows():
letters_queue.put([i, j])
return
# First lock accesses the queue. Second writes to dataframe
lock_1 = threading.Lock()
lock_2 = threading.Lock()
def cross_check(number_of_threads, this_thread_number):
cpu = "CPU " + str(this_thread_number) + ": "
while True:
start = time.time()
lock_1.acquire()
if not letters_queue.empty():
i, j = letters_queue.get()
lock_1.release()
current_para = j["First Paragraph"]
current_link = j["link-address"]
current_pub_date = j["published-date"]
print(str(cpu) + "About to test similarity...")
# Expensive, time limiting operation:
similarity_vec = np.vectorize(how_similar)(responses["first-paragraph"] , current_para)
print(str(cpu) + "Just finished checking similarity")
matched_response = similarity_vec.argmax()
print(str(cpu) + " About to write the match to dataframe")
# Writes the match to the responses datafram
lock_2.acquire()
responses["Found a match"][matched_response] = current_link
responses["Match ratio"][matched_response] = similarity_vec.max()
responses["Match published"][matched_response] = current_pub_date
lock_2.release()
print(str(cpu) + "Just matched the following two phrases (letter, then response) with ratio "
+ str(similarity_vec.max()) + ": \n\n"
+ str(current_para) + "\n\n" + str(responses["first-paragraph"][matched_response]))
end = time.time()
print(str(cpu) + "This match took " + str(end - start) + "\n")
else:
lock_1.release()
break
return
# Multi threaded cross checker
number_of_threads = 8
threads = []
queue_letters()
for i in range(number_of_threads):
thread = threading.Thread(target=cross_check, args=(number_of_threads, i))
threads.append(thread)
thread.start()
Я думал о блокировках, но это не должно быть проблемой, потому что код ограничения времени не находится в блокировке. Любая помощь приветствуется.