Многопроцессорность такая медленная - PullRequest
0 голосов
/ 05 января 2019

У меня есть функция, которая делает следующее:

  • Возьмите файл в качестве ввода и выполните базовую очистку.
  • Извлеките необходимые элементы из файла, а затем запишите их в кадр данных pandas.
  • Фрейм данных окончательно преобразуется в csv и записывается в папку.

Это пример кода:

def extract_function(filename):  
   with open(filename,'r') as f:  
       input_data=f.readlines()  
   try:
     // some basic searching pattern matching extracting  
     // dataframe creation with 10 columns and then extracted values are filled in
        empty dataframe
     // finally df.to_csv()

if __name__ == '__main__':
   pool_size = multiprocessing.cpu_count()
   filenames=os.listdir("/home/Desktop/input")
   pool=multiprocessing.Pool(pool_size)
   pool.map(extract_function,filenames)
   pool.close()
   pool.join()

Общее количество файлов в папке input : 4000. Я использовал многопроцессорность, так как запуск программы в обычном режиме с for loop занимал некоторое время. Ниже приведены времена выполнения обоих подходов:

Обычная обработка ЦП = 139,22 секунды
Многопроцессорная обработка = 18,72 секунды

Моя системная спецификация:

Intel i5 7-го поколения, оперативная память 12 ГБ, жесткий диск 1 ТБ, Ubuntu 16.04

При запуске программы для 4000 файлов все ядра полностью используются (в среднем около 90% каждого ядра). Поэтому я решил увеличить размер файла и повторить процесс. На этот раз номер входного файла был увеличен с 4000 до 1,20,000. Но на этот раз при запуске кода загрузка процессора была нестабильной при запуске, и через некоторое время загрузка снизилась (в среднем около 10% на ядро). Использование оперативной памяти также является низким усреднением при максимуме 4 ГБ (оставаясь свободным 8 ГБ). С 4000 файлами в качестве входных данных запись файла в CSV была быстрой, как в одно мгновение, так как я мог видеть скачок или около 1000 файлов или более в одно мгновение. Но с 1,20000 файлов в качестве входных данных, запись файлов замедлилась примерно до 300 файлов, и это замедление идет линейно, и через некоторое время запись файлов на мгновение стала около 50-70. Все это время большинство баранов свободны. Я перезапустил машину и попробовал то же самое, чтобы очистить любой нежелательный процесс зомби, но все равно, результат тот же.

В чем причина этого? Как мне добиться такой же многопроцессорности для больших файлов?

Примечание:
* Средний размер каждого файла около 300 КБ.
Каждый записываемый файл будет иметь размер около 200 байт.
* Общее количество файлов 4080. Следовательно, общий размер будет ~ 1,2 ГБ.
* Эти же 4080 файлов использовались для создания копий, чтобы получить 1,20000 файлов.
* Эта программа является экспериментом для проверки многопроцессорности на наличие большого количества файлов.

Обновление 1

Я пробовал тот же код на гораздо более мощной машине.

Intel i7 8-го поколения 8700, 1 ТБ SSHD и 60 ГБ оперативной памяти.

. Запись файла была намного быстрее, чем на обычном жестком диске. Программа заняла:

  • Для 4000 файлов - 3,7 с
  • Для 1,20000 файлов - 2 минуты

В какой-то момент эксперимента я получил самое быстрое время завершения, которое составляет 84 с. В тот момент он давал мне постоянный результат, пытаясь два раза подряд. Подумав, что это может быть из-за того, что я правильно установил число потоков в размере пула, я перезапустил и попытался снова. Но на этот раз это было намного медленнее. Чтобы дать представление, во время обычных прогонов около 3000-4000 файлов будут записываться в секунду или две, но на этот раз он записывал менее 600 файлов в секунду. В этом случае также оперативная память не использовалась вообще. Процессор, несмотря на то, что используется многопроцессорный модуль, загрузка всех ядер составляет в среднем около 3-7%.

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Как и предполагали @RolandSmith & @selbie, я избежал непрерывной записи ввода-вывода в файлы CSV, заменив ее фреймами данных и добавив к ней. Это, я думаю, очистило несоответствия. Я проверил «пера» и «паракет» высокопроизводительных модулей ввода-вывода, как предложено @CoMartel, но я думаю, что это для сжатия больших файлов в меньшую структуру фрейма данных. Варианты добавления не были там для этого.

Замечания:

  • Программа работает медленно при первом запуске . последовательных запусков будет быстрее . Такое поведение было последовательным.
  • Я проверил некоторые завершающие процессы Python после завершения программы, но не смог найти ни одного. Таким образом, в CPU / RAM имеется какое-то кеширование, которое ускоряет выполнение программы при последующих запусках

Программа для 4000 входных файлов заняла 72 сек для при первом запуске , а затем в среднем 14-15 сек для всех последовательных прогонов после этого.

  • Перезапуск системы очищает этот кеш и заставляет программу работать медленнее при первом запуске.

  • Среднее время пробега составляет 72 сек. Но для уничтожения программы сразу после ее запуска и запуска потребовалось 40 сек для первого пробного прогона после завершения. В среднем 14 секунд после всех последовательных запусков.

  • Во время нового запуска все использование ядра будет около 10-13% . Но после всех последовательных запусков загрузка ядра будет 100% .

Проверено с 1 200 000 файлов, оно следует той же схеме. Итак, на данный момент несоответствие решено. Поэтому, если такой код необходимо использовать в качестве сервера, необходимо выполнить пробный прогон для кэширования ЦП / ОЗУ, прежде чем он сможет начать принимать запросы API для более быстрых результатов.

0 голосов
/ 05 января 2019

Чтение с диска и запись на диск медленны по сравнению с запуском кода и данных из ОЗУ Это крайне медленнее по сравнению с запуском кода и данных из внутреннего кэша в CPU.

В попытке сделать это быстрее используются несколько кэшей.

  1. Жесткий диск обычно имеет встроенный кеш. В 2012 году я провел тестирование по этому вопросу. При отключенном кеше записи жесткого диска скорость записи снизилась с 72 МБ / с до 12 МБ / с.
  2. В настоящее время большинство операционных систем используют незанятую память в качестве дискового кэша.
  3. Процессор также имеет несколько уровней встроенных кэшей.

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

Так что я предполагаю, что когда вы пропустите определенное количество файлов, вы исчерпаете один или несколько кэшей, и узким местом становится дисковый ввод-вывод.

Чтобы проверить, вам нужно добавить код к extract_function, чтобы измерить 3 вещи:

  • Сколько времени занимает чтение данных с диска.
  • Сколько времени занимает выполнение расчетов.
  • Сколько времени занимает написание CSV.

Пусть extract_function вернет кортеж из этих трех чисел и проанализирует их. Вместо map я бы посоветовал использовать imap_unordered, чтобы вы могли начать оценивать числа, как только они станут доступны.

Если дисковый ввод-вывод оказался проблемой, рассмотрите возможность использования SSD.

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