Можно ли получить скорость при параллельной загрузке нескольких файлов с диска?

Я работаю над проектом (написанным на python 2.7), в котором я обрабатываю несколько 1000 изображений, каждое размером около 2,7 МБ. В настоящее время рабочий процесс выглядит следующим образом:

  • 1 процесс последовательно загружает образы с диска в multiprocessing.Manager().Queue()
  • Процессы N потребляют изображения из очереди для предварительной обработки и сохраняют результаты во второй очереди.
  • 1 процесс берет изображения из второй очереди и сохраняет их на диск (файлы меньшего размера, не проблема)

Пока что это работает достаточно хорошо, и я могу создать достаточно процессов предварительной обработки, так что загрузка с диска становится узким местом.

Для развлечения и обучения я экспериментировал с использованием двух процессов, каждый из которых загружал половину файлов с диска и помещал их в одну очередь. Я хотел посмотреть, даст ли это мне еще более быстрое время загрузки с диска. Однако из-за моей настройки (жесткие диски с ZFS и различными уровнями кэширования) результаты этой «оптимизации» неубедительны и могут сильно различаться даже между двумя одинаковыми запусками. Цифры Что-то вроде предполагают, что параллельная загрузка происходит намного быстрее, но из-за всего кеширования я потерял доверие к таймингу (значения от 55 до 7 и все промежуточные значения были ...).
Кроме того, я пока тестирую систему Linux, но производственная машина работает под управлением Windows с SSD. Итак, какие бы результаты я ни получил при тестировании, они могут быть специфичными для ОС и неприменимы к окончательному варианту использования.

Мой вопрос: есть ли какая-то согласованная выгода от параллельной загрузки нескольких файлов? Или достаточно, чтобы один процесс загружал все файлы последовательно, поскольку он уже будет читать настолько быстро, насколько позволяет жесткий диск? Я не обязательно ищу ответы, относящиеся к python, но к файловому вводу-выводу в целом. Есть ли какие-нибудь важные различия между Linux и Windows?


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

Поскольку загрузка файла, скорее всего, будет связана с вводом-выводом, выполнение ее в двух процессах может быть медленнее из-за дополнительных накладных расходов, которые она требует.

martineau 01.05.2018 22:12

@martineau Не на SSD. Одновременное ожидание нескольких операций чтения важно для получения от них высокой производительности.

David Schwartz 01.05.2018 22:15

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

Jean-François Fabre 01.05.2018 22:17

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

martineau 01.05.2018 22:17

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

Klaus D. 01.05.2018 22:18

@DavidSchwartz: да, это была одна из моих идей. Однако я не был уверен, насколько "ожидающими" нескольких параллельных чтений будут.

Slizzered 01.05.2018 22:21

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

Slizzered 01.05.2018 22:22

Хорошо, поскольку обработка данных во время загрузки - это то, что замедляет этот шаг, на самом деле он должен быть привязан к вычислениям, а не к вводу-выводу - в этом случае многопоточность, вероятно, не поможет, потому что Python на самом деле не работает больше чем один поток за раз из-за GIL (Global Interpreter Lock), который предотвращает это, кроме как во время ввода-вывода и вызовов функций в некоторых модулях расширения на основе C.

martineau 01.05.2018 22:32

@martineau Нет, это определенно связано с вводом-выводом. Кеширование, о котором я говорил, - это кеширование файловой системы. Кроме того, я занимаюсь не многопоточностью, а многопроцессорностью. Насколько мне известно, разница здесь как раз в том, что многопроцессорность не страдает от проблем, связанных с GIL.

Slizzered 01.05.2018 22:36

К сожалению, это слишком широко, я бы не стал здесь подходить. Однако есть несколько хороших вопросов, которые вы могли бы извлечь. В любом случае, один профессиональный совет: вы можете протестировать производительность многопоточности по сравнению с производительностью многопроцессорности в python 2.7 с помощью модуля multiprocessing.dummy. Просто поменяйте их местами, поскольку они имеют общий интерфейс, и посмотрите, интересует ли вас GIL для начала: docs.python.org/2/library/…

BlackVegetable 01.05.2018 22:39

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

martineau 01.05.2018 22:47
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
11
155
0

Другие вопросы по теме