#python #python-3.x #multiprocessing
#python #python-3.x #многопроцессорная обработка
Вопрос:
У меня есть простой код, который загружает список паролей в словарь и генерирует из них хэши в новый список:
def hash_one():
hash_to_string = {}
with open("wordlists/pass.txt", "r", encoding="ISO-8859-1") as file:
for x in file:
x = x.strip()
result = hashlib.sha1(hashlib.sha1(x.encode()).digest()).hexdigest()
f_result = (result)
hash_to_string[hash] = (f_result)
with open("hashed.txt", "a") as final:
final.write(f_result "n")
hash_one()
Интересно, как я могу использовать PoolProcessExecutor()
для ускорения процесса? Теперь он читает построчно. Я пытался провести несколько тестов, но не могу заставить его работать должным образом. Я хотел бы использовать 16-ядерный процессор, который я использую.
Комментарии:
1. одновременное чтение / запись из файлов — это кошмар. Можете ли вы просто сохранить весь файл в памяти? Или, возможно, разделить файл?
2. нет необходимости, чтение / запись происходят в разных файлах. И запись — это простое добавление после основного вычисления (хеширования). Можно просто написать функцию для всего, что делается в цикле, и довольно эффективно передавать ее в пул рабочих.
3. Вы также можете увеличить скорость, не открывая выходной файл каждый раз в цикле. Есть ли причина не оставлять его открытым или сохранять результаты до конца и записывать их один раз?
4. @juanpa.arrivillaga невозможно сохранить файл в памяти, содержащий более 15 миллионов строк
5. Вы хотите ускорить чтение строк или генерацию хэшей?
Ответ №1:
Вы можете распараллелить хеширование, но на самом деле не чтение файлов. Для этого вы можете попробовать разделить исходные файлы на 16 частей и запустить свой исходный непараллельный код (запустив 16 интерпретаторов Python).
import hashlib
import multiprocessing
from concurrent.futures import ProcessPoolExecutor
def do_hash(x):
return hashlib.sha1(hashlib.sha1(x.encode()).digest()).hexdigest()
def hash_each_in_list(l):
return [do_hash(x) for x in l]
def hash_each_in_list_parallel(l):
n = multiprocessing.cpu_count()
parts = [l[(i*len(l))//n : ((i 1)*len(l))//n] for i in range(n)]
with ProcessPoolExecutor() as executor:
return sum(list(executor.map(hash_each_in_list, parts)), [])
l = hash_each_in_list_parallel(open('so_2020-12-08_hashes.txt').read().splitlines())
password
123456
monkey
['2470c0c06dee42fd1618bb99005adca2ec9d1e19',
'6bb4837eb74329105ee4568dda7dc67ed2ca2ad9',
'a5892368ae83685440a1e27d012306b073bdf5b7']
Непараллеленный вызов:
l = hash_each_in_list(open('so_2020-12-08_hashes.txt').read().splitlines()))
Результаты теста на фиктивном файле с 10 миллионами строк, 6-ядерный процессор Ryzen 5 3600:
- непараллеливание: 9,9 с
- распараллеливание: 6,3 с
- без сшивания списков в конце, используя
sum(parts, [])
это 5.1s
- без сшивания списков в конце, используя
Я предполагаю, что копирование памяти здесь является узким местом, в то время как вычисление has на процессоре происходит довольно быстро, поэтому здесь нет большого ускорения. (Моя загрузка процессора не превысила 40%)