Стратегии для работы с большими объемами данных изображений - PullRequest
8 голосов
/ 02 февраля 2012

Технологический стек: C # / .NET 4 / WinForms

Фон:

Проект, над которым я работаю, представляет собой приложение для визуализации серии стеков изображений.В частности, каждый стек изображений выровнен по сетке, показывает одно и то же изображение в любой момент времени, и функции обработки применяются к изображениям, видимым в данный момент.Сами стеки изображений составляют 150-300 МБ, а каждое изображение имеет размер 512 КБ-1 МБ.Типичный набор данных будет состоять из ~ 100 стеков изображений.

Вопрос:

Чтобы попытаться использовать этот объем данных, я использую несколько методов:

  • файлы с отображением в память: стеки изображений загружаются с диска при запуске приложения
  • компиляция под x64 с разрешенным небезопасным кодом: очевидно, мне нужно 64-битное адресное пространство для файлов такого размера.Я перемещаю текущее отображаемое изображение из файла отображения памяти в метод, который генерирует растровое изображение через Marshal.Copy с небезопасными указателями.
  • System.Threading.Tasks: я использую параллельные циклы для обработки, где это возможно
  • System.Drawing.BufferedGraphicsContext: Каждый стек изображений имеет одно активное изображение, которое перед передачей передается в BufferedGraphicsContext.в PictureBox для отображения пользователю.
  • Высококачественные системные требования: четырехъядерный процессор или лучше, твердотельный накопитель, 12 ГБ памяти и т. д.

Но даже с использованием всего вышеперечисленногоОтзывчивость оставляет желать лучшего.При использовании SysInternals Process Explorer загрузка ЦП является низкой (<25%), а использование памяти возрастает до предела, прежде чем происходит сборка мусора. </p>

Профилирование показывает, что большая часть времени выполнения тратится на извлечение данных из отображенной памятифайлы.Я полагаю, что он ждет, пока ОС вернет запрошенную память обратно в активную память?

Что еще я могу сделать для повышения производительности?

Примечание:

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

Обновление 1:

  • Для памяти, мой блок разработки имеет только 6 ГБ(в результате я пытаюсь загрузить меньше файлов), но система развертывания будет иметь 24 ГБ.
  • Я изучаю возможности оптимизации SSE с помощью Intel Performance Primitives и ускорения GPU с помощью CUDA.
  • Причина, по которой я пытаюсь загрузить все данные в память, заключается в том, что важным шагом визуализации является циклический переход между стеками изображений с частотой 15–60 Гц, и я боялсяshing.

Ответы [ 5 ]

5 голосов
/ 02 февраля 2012

Прежде всего, я думаю, что использование небезопасного кода и отображенных в память файлов не очень полезно. Вам нужно прочитать около 20 ГБ данных с диска. Чтение с диска займет гораздо больше времени, чем одна дополнительная копия в памяти, если вы просто используете потоки - вы оптимизировали не в том месте.

Я думаю, вы должны смотреть на это под другим углом. Вы показываете стопки изображений размером 20 ГБ на дисплее, который может отображать менее 10 МБ данных. Вам не нужно читать 20 ГБ данных, чтобы показать все стопки изображений и обеспечить отзывчивый пользовательский интерфейс при обработке этих изображений. Вам просто нужно загрузить верхнее изображение из каждого стека - это будет намного намного быстрее.

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

2 голосов
/ 02 февраля 2012

Вы можете предварительно сгенерировать изображения большого пальца для каждого изображения и загружать их только на Grid, когда все изображения доступны.В тот момент, когда пользователь применяет эффект / преобразование к изображению, вы можете загрузить только этого изображения.И даже во время загрузки только этого изображения вы можете разделить его на отрезки секторов загрузки и загрузить их асинхронным способом.Если вы посмотрите на Google Street View , как он загружается, после увеличения вы обнаружите, что никогда все изображение (даже если оно было запрошено вами) немедленно загружено, но оно загруженопо секторам.

Другая очень интересная технология, я думаю, Deep Zoom может быть, если не ответом на ваши проблемы, но по крайней мере может дать хороший намек.

Еще один пример Deep Zoom от Скотта Хансельмана

Удачи.

0 голосов
/ 02 февраля 2012

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

Если вы используете WPF, вы можете попробовать использовать DecodePixelWidth и DecodePixelHeight. Может быть, в winforms есть эквивалент

0 голосов
/ 02 февраля 2012

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

0 голосов
/ 02 февраля 2012

Как бы странно это не звучало, вы должны пытаться прикасаться (т. Е. Читать один байт при каждом кратном 4 КБ от начала каждого файла) всем данным в отображенных в память файлах при запуске приложения.Поскольку у вас достаточно ОЗУ, проблема, вероятно, не в том, что ОС выгружает ваши образы из памяти, а в том, что они изначально не распределяют их по страницам. Файлы, отображаемые в память, загружаются лениво, поэтому ОС не будет обращаться к диску, пока вы на самом деле не попытаетесьполучить доступ к данным в памяти сопоставленных файлов.В результате прикосновение к памяти при загрузке приложения вызовет чтение диска, а не время, когда пользователь просматривает стеки изображений.

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