Возможно ли ускорить ввод-вывод Python? - PullRequest
12 голосов
/ 11 мая 2009

Рассмотрим эту программу на Python:

import sys

lc = 0
for line in open(sys.argv[1]):
    lc = lc + 1

print lc, sys.argv[1]

Запустив его на моем текстовом файле 6 ГБ, он завершается за ~ 2 минуты.

Вопрос: можно ли идти быстрее?

Обратите внимание, что такое же время требуется для:

wc -l myfile.txt

Итак, я подозреваю, что ответ на мой вопрос - просто «нет».

Обратите внимание, что моя настоящая программа делает что-то более интересное, чем просто подсчет строк, поэтому, пожалуйста, дайте общий ответ, не трюки подсчета строк (например, хранение метаданных счетчика строк в файле)

PS: я отметил этот вопрос как "linux", потому что меня интересуют только ответы, относящиеся к linux. Не стесняйтесь давать ответы, не зависящие от ОС, или даже от других ОС, если они у вас есть.

См. Также следующий вопрос

Ответы [ 8 ]

12 голосов
/ 11 мая 2009

Бросьте оборудование в проблему.

Как указала gs, узким местом является скорость передачи данных на жестком диске. Так что нет, вы не можете использовать лучший алгоритм для улучшения своего времени, но вы можете купить более быстрый жесткий диск.

Редактировать: Еще один хороший момент по GS; Вы также можете использовать конфигурацию RAID для повышения скорости. Это можно сделать с помощью аппаратного обеспечения или программного обеспечения (например, OS X , Linux , Windows Server и т. Д.).


Управляющее уравнение

(Amount to transfer) / (transfer rate) = (time to transfer)

(6000 MB) / (60 MB/s) = 100 seconds

(6000 MB) / (125 MB/s) = 48 seconds


Аппаратные решения

ioDrive Duo , предположительно, является самым быстрым решением для корпоративной среды, и «будет доступно в апреле 2009 года».

Или вы можете проверить жесткий диск WD Velociraptor (10000 об / мин).

Кроме того, я слышу, что Seagate Cheetah - хороший вариант (15000 оборотов в минуту с устойчивой скоростью передачи 125 МБ / с).

8 голосов
/ 12 мая 2009

Хитрость заключается не в том, чтобы заставить электроны двигаться быстрее (это трудно сделать), а в том, чтобы выполнять больше работы за единицу времени.

Во-первых, убедитесь, что чтение файла 6 ГБ связано с вводом / выводом, а не с ЦП.

Если это связано с вводом / выводом, рассмотрите шаблон проектирования "Fan-Out".

  • Родительский процесс порождает группу детей.

  • Родитель читает файл 6 Гб и передает строки дочерним элементам, записывая их в каналы STDIN. Время чтения 6 ГБ останется постоянным. Работа со строками должна включать как можно меньше родительской обработки. Следует использовать очень простые фильтры или счетчики.

    Канал - это канал связи в памяти. Это общий буфер с читателем и писателем.

  • Каждый ребенок читает строку из STDIN и выполняет соответствующую работу. Каждый ребенок, вероятно, должен написать простой файл на диске с окончательными (обобщенными, уменьшенными) результатами. Позже результаты в этих файлах могут быть объединены.

5 голосов
/ 11 мая 2009

обычный "нет".

Вы достигли максимальной скорости диска.

Я имею в виду, вы можете mmap файл или прочитать его в двоичных блоках, и использовать .count('\n') или что-то еще. Но это вряд ли даст значительные улучшения.

4 голосов
/ 11 мая 2009

Вы не можете получить скорость выше максимальной скорости чтения с диска.

Для достижения максимальной скорости диска вы можете воспользоваться следующими двумя советами:

  1. Считайте файл с большим буфером. Это может быть написано «вручную» или просто с помощью io.BufferedReader (доступно в python2.6 +).
  2. Выполнять подсчет новой строки параллельно в другом потоке.
4 голосов
/ 11 мая 2009

Если вы предполагаете, что диск может читать 60 МБ / с, вам потребуется 6000/60 = 100 секунд, что составляет 1 минуту 40 секунд. Я не думаю, что вы можете получить что-то быстрее, потому что диск является узким местом.

1 голос
/ 14 мая 2009

2 минуты звучит о праве прочитать весь файл 6 ГБ. Существует не так много, вы можете сделать с алгоритмом или ОС, чтобы ускорить процесс. Я думаю, у вас есть два варианта:

  1. Бросьте деньги на проблему и получите лучшее оборудование. Вероятно, лучший вариант, если этот проект для вашей работы.

  2. Не читайте весь файл. Я не знаю, что вы пытаетесь сделать с данными, поэтому, возможно, у вас нет другого выбора, кроме как прочитать все это. С другой стороны, если вы сканируете весь файл для какой-то конкретной вещи, то, возможно, было бы полезно поместить туда некоторые метаданные в начале.

1 голос
/ 11 мая 2009

как говорили другие - "нет"

Почти все ваше время тратится на ожидание ввода-вывода. Если вам нужно выполнить это несколько раз, и у вас есть машина с тоннами оперативной памяти, вы можете сохранить файл в памяти. Если ваша машина имеет 16 ГБ оперативной памяти, вы можете использовать 8 ГБ в / dev / shm для игры.

Другой вариант: Если у вас несколько машин, эту проблему тривиально распараллелить. Распределите его по нескольким машинам, каждый из них считает свои новые строки и добавляет результаты.

0 голосов
/ 11 мая 2009

Обратите внимание, что Python I / O реализован в C, поэтому не так уж много удачи в его дальнейшей оптимизации

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...