Я работаю над проектом (написанным на python 2.7
), в котором я обрабатываю несколько 1000 изображений, каждое размером около 2,7 МБ. В настоящее время рабочий процесс выглядит следующим образом:
multiprocessing.Manager().Queue()
N
потребляют изображения из очереди для предварительной обработки и сохраняют результаты во второй очереди.Пока что это работает достаточно хорошо, и я могу создать достаточно процессов предварительной обработки, так что загрузка с диска становится узким местом.
Для развлечения и обучения я экспериментировал с использованием двух процессов, каждый из которых загружал половину файлов с диска и помещал их в одну очередь. Я хотел посмотреть, даст ли это мне еще более быстрое время загрузки с диска.
Однако из-за моей настройки (жесткие диски с ZFS и различными уровнями кэширования) результаты этой «оптимизации» неубедительны и могут сильно различаться даже между двумя одинаковыми запусками. Цифры Что-то вроде предполагают, что параллельная загрузка происходит намного быстрее, но из-за всего кеширования я потерял доверие к таймингу (значения от 55 до 7 и все промежуточные значения были ...).
Кроме того, я пока тестирую систему Linux, но производственная машина работает под управлением Windows с SSD. Итак, какие бы результаты я ни получил при тестировании, они могут быть специфичными для ОС и неприменимы к окончательному варианту использования.
Мой вопрос: есть ли какая-то согласованная выгода от параллельной загрузки нескольких файлов? Или достаточно, чтобы один процесс загружал все файлы последовательно, поскольку он уже будет читать настолько быстро, насколько позволяет жесткий диск? Я не обязательно ищу ответы, относящиеся к python, но к файловому вводу-выводу в целом. Есть ли какие-нибудь важные различия между Linux и Windows?
Отказ от ответственности:
Я знаю, что это можно решить путем чрезмерного тестирования производительности на целевой машине. Однако комплексный тест потребовал бы большого количества переписывания кода на этом этапе и большего времени доступа (и, возможно, перезагрузок для очистки кешей файловой системы) на целевой машине, чем у меня сейчас.
@martineau Не на SSD. Одновременное ожидание нескольких операций чтения важно для получения от них высокой производительности.
вы можете протестировать это при запуске своей программы, просто чтобы решить, делать это параллельно или последовательно. У многих программ есть программы запуска, чтобы узнать, какой алгоритм лучше всего зависит от текущего оборудования.
Хорошо, если вы используете SSD, тогда эта часть не связана с вводом-выводом ... но почему вы тогда пытаетесь ускорить эту часть? Вы профилировали свой код, чтобы увидеть, на что он на самом деле тратит большую часть времени?
Это вряд ли зависит от вашей настройки, связано только с дистанционным программированием и тоже слишком широко. Не лучшая тема для ТАК.
@DavidSchwartz: да, это была одна из моих идей. Однако я не был уверен, насколько "ожидающими" нескольких параллельных чтений будут.
@martineau из моего профилирования, ясно, что загрузка файлов с диска является узким местом. Однако мне трудно определить, выгодна ли загрузка файлов с несколькими потоками, поскольку время выполнения может сильно различаться из-за кеширования, поэтому я надеялся на некоторые передовые методы или рекомендации.
Хорошо, поскольку обработка данных во время загрузки - это то, что замедляет этот шаг, на самом деле он должен быть привязан к вычислениям, а не к вводу-выводу - в этом случае многопоточность, вероятно, не поможет, потому что Python на самом деле не работает больше чем один поток за раз из-за GIL (Global Interpreter Lock), который предотвращает это, кроме как во время ввода-вывода и вызовов функций в некоторых модулях расширения на основе C.
@martineau Нет, это определенно связано с вводом-выводом. Кеширование, о котором я говорил, - это кеширование файловой системы. Кроме того, я занимаюсь не многопоточностью, а многопроцессорностью. Насколько мне известно, разница здесь как раз в том, что многопроцессорность не страдает от проблем, связанных с GIL.
К сожалению, это слишком широко, я бы не стал здесь подходить. Однако есть несколько хороших вопросов, которые вы могли бы извлечь. В любом случае, один профессиональный совет: вы можете протестировать производительность многопоточности по сравнению с производительностью многопроцессорности в python 2.7 с помощью модуля multiprocessing.dummy
. Просто поменяйте их местами, поскольку они имеют общий интерфейс, и посмотрите, интересует ли вас GIL для начала: docs.python.org/2/library/…
Передача больших объемов данных между отдельными процессами, как это может показаться здесь необходимым, также приведет к огромным накладным расходам и, опять же, приведет к более медленному, а не ускоренному времени.
Поскольку загрузка файла, скорее всего, будет связана с вводом-выводом, выполнение ее в двух процессах может быть медленнее из-за дополнительных накладных расходов, которые она требует.