Mail.ruПочтаМой МирОдноклассникиВКонтактеИгрыЗнакомстваНовостиКалендарьОблакоЗаметкиВсе проекты

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

SYFAREN m Ученик (174), открыт 3 дня назад
Привет всем! Занимаюсь обработкой огромного текстового файла (несколько гигабайт) на 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()



Буду очень благодарен за помощь!
2 ответа
Вася Б Мастер (1536) 3 дня назад
Выбери другой язык, например С++ или другой комп, пошустрей
Я вот мучаюсь над этим же вопросом, но на языке PHP.
В итоге раздробил базы. Хотя открытие закрытие файлов никоим образом не способствует ускорению. Все же меньший объем обрабатывается быстрее.
D P Мудрец (17888) 2 дня назад
Питон достаточно медленный сам по себе, поэтому выбор языка изначально неудачный.
Задача про "огромный текстовый файл на несколько гигабайт" - это типичная задача про выделение информации из лога. В подобных файлах строки имеют разный размер, поэтому идея о том, что можно просто разделить файл на куски весьма убогая. У меня есть наработки в этом направлении, но, естественно, не на языке Питон :)
Общая идея такая:
Первый поток - Читатель. Задача: считывание больших блоков из файла. Каждый блок считывается в свой кусок выделенной памяти. После считывания блок передается в следующий поток - парсер строк, а Читатель переходит к считыванию следующего блока.
Второй поток - Парсер строк. Получает блок памяти из потока Читателя и разбивает его на строки с учетом сохраненного "хвоста" (неполной завершающей строки) от предыдущего блока. Выделенные строки передаются в виде связанного списка для последующего разбора в следующий поток.
В целом должен получиться конвейер, дающий ускорение за счет параллельного считывания с диска и разбора считанных данных.
Похожие вопросы