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