Эффективный разреженный доступ к большому отображенному в памяти файлу - PullRequest
2 голосов
/ 17 февраля 2012

У нас есть данные изображения в больших (например, 700 МБ) файлах. Файлы отображены в памяти в Windows 7 64-bit.

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

Чтобы получить наилучшую возможную производительность, мы надеемся, что сможем дать подсказку системе ВМ для выборки следующей строки изображения (возможно, вызвавшей ошибку страницы), пока мы обрабатываем данные в текущей. Это распараллелит нашу обработку и ошибки страницы. Кажется, нет очевидного способа сделать это в Windows!

Итак, вопросы:

  • Есть ли в Windows 7 какой-либо эквивалент madvise( MADV_WILLNEED )?

  • Есть ли способ асинхронного касания страницы, запуска страницы ошибка, не дожидаясь появления страницы?

Правильное долгосрочное решение - хранить наши данные другим способом (например, в тайлах), однако сейчас мы не можем этого сделать. На данный момент нам необходимо сохранить подход с отображением в памяти.

Ответы [ 2 ]

1 голос
/ 06 марта 2014

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

У нас была проблема водно приложение для «больших данных», где мы лучше, чем менеджер виртуальной памяти, добавляем, какие страницы должны быть выгружены из редких «огромных файлов».Что мы сделали, так это то, что у нас был выделенный поток («inmemadvisor») для получения «нужных» запросов, каждый из которых имел приоритет.Этот поток поддерживает приоритетный список запросов и отправляет «подсказки» чтения из памяти в пул потоков, где наибольшее количество потоков обрабатывает запросы с высоким приоритетом, а наименьшая часть пула обрабатывает наименьший приоритет (вы, вероятно, поняли это).

Затем у нас есть параметры для управления количеством потоков в пуле и некоторые другие изящные детали.

Плюсы этой реализации:

  • мы в 10 раз превосходим пейджинг виртуальной машины по умолчаниюмодель (в Windoze Server 2008/2012)
  • , пока пейджинг становится «мягким», и мы можем забыть данные, которые нам больше не нужны (без срочной необходимости вставлять страницы с серьезной ошибкой), производительностьлучше, чем хорошо
  • мы можем использовать всю доступную свободную физическую оперативную память для ускорения вычислений
  • каждый добавляемый вами новый МБ памяти может повысить производительность

Минусы:

  • если у вас не хватит ОЗУ (локальность нарушена), производительность будет свинья ... ну, это будет то же самоебез этой реализации
  • это требует некоторого тщательного проектирования и хорошей реализации, чтобы оправдать ее выполнение
  • в некоторых приложениях вам может потребоваться добавить дополнительную логику мониторинга и управления для управления "inmemadvisor", чтобыхороший гражданин

Итак, вкратце: это то, чего лучше не делать, но, с другой стороны, это то, что делает программирование положительным испытанием ;-) Кстати: наша реализацияПревосходит Linux madvice () по производительности с нашим приложением, но не настолько универсален, как это.

Cheers, // Jari

1 голос
/ 19 февраля 2012

Я не думаю, что вы можете намекнуть на систему VM, но вы можете предварительно извлечь данные, просто загрузив данные следующей строки во время обработки предыдущей.Вы можете сделать это параллельно с обработкой.Вы, вероятно, должны получить больше, чем на 1 вперед, так как обработка, скорее всего, намного быстрее, чем чтение из файла.

Это на самом деле очень хорошо вписывается в шаблон производителя-потребителя.Запустите программу чтения изображений и обработчик данных в отдельных потоках и используйте своего рода коллекцию блокировок (например, C # BlockingCollection) с ограничением емкости для передачи данных из считывателя в процессор.

...