Top.Mail.Ru
Ответы

Подсчет слов в огромном файле с помощью многопоточности и очередей (multiprocessing)

Привет всем! Занимаюсь обработкой огромного текстового файла (несколько гигабайт) на Python. Нужно посчитать, сколько раз встречается каждое слово. Проблема в том, что если просто идти построчно, это занимает очень много времени.

Думаю, можно ускорить всё с помощью многопоточности и очередей. Вот моя идея:

1. Разбить файл на несколько частей.
2. Запустить несколько потоков, каждый обрабатывает свою часть и считает слова. Результаты (слово: количество) каждый поток отправляет в очередь.
3. Главный поток собирает результаты из очереди и объединяет их в один словарь.

Написал код, но он работает как-то странно - то неправильный результат выдаёт, то вообще зависает. Не могу понять, где ошибка и как правильно использовать multiprocessing.Queue и multiprocessing.Process. Хочется, чтобы и память не жрало, и работало быстро.

Вот что у меня пока есть:


import multiprocessing
import os

def process_chunk(filename, start_byte, end_byte, queue):
# ... (тут код обработки куска файла) ...

def main():
filename = "huge_file.txt"
filesize = os.path.getsize(filename)
num_processes = multiprocessing.cpu_count()
chunk_size = filesize // num_processes

queue = multiprocessing.Queue()
processes = []

for i in range(num_processes):
start_byte = i * chunk_size
end_byte = (i + 1) * chunk_size
if i == num_processes - 1:
end_byte = filesize # Последний кусок может быть неполным

process = multiprocessing.Process(target=process_chunk, args=(filename, start_byte, end_byte, queue))
processes.append(process)
process.start()

# ... (тут код, который собирает результаты из очереди) ...

for process in processes:
process.join()

if __name__ == "__main__":
main()



Буду очень благодарен за помощь!

По дате
По рейтингу
Аватар пользователя
Новичок
10мес

Питон достаточно медленный сам по себе, поэтому выбор языка изначально неудачный.
Задача про "огромный текстовый файл на несколько гигабайт" - это типичная задача про выделение информации из лога. В подобных файлах строки имеют разный размер, поэтому идея о том, что можно просто разделить файл на куски весьма убогая. У меня есть наработки в этом направлении, но, естественно, не на языке Питон :)
Общая идея такая:
Первый поток - Читатель. Задача: считывание больших блоков из файла. Каждый блок считывается в свой кусок выделенной памяти. После считывания блок передается в следующий поток - парсер строк, а Читатель переходит к считыванию следующего блока.
Второй поток - Парсер строк. Получает блок памяти из потока Читателя и разбивает его на строки с учетом сохраненного "хвоста" (неполной завершающей строки) от предыдущего блока. Выделенные строки передаются в виде связанного списка для последующего разбора в следующий поток.
В целом должен получиться конвейер, дающий ускорение за счет параллельного считывания с диска и разбора считанных данных.

Аватар пользователя
Знаток
10мес

Выбери другой язык, например С++ или другой комп, пошустрей
Я вот мучаюсь над этим же вопросом, но на языке PHP.
В итоге раздробил базы. Хотя открытие закрытие файлов никоим образом не способствует ускорению. Все же меньший объем обрабатывается быстрее.