Подтвердить что ты не робот

Самый быстрый PNG-декодер для .NET.

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

Сейчас наше решение загружает PNG файлы (около 1 МБ каждый) из HD и отправляет их на видеокарту, поэтому композиция выполняется на графическом процессоре. Сначала мы попытались загрузить наши изображения, используя PNG-декодер, открытый API XNA. Мы видели, что производительность не слишком хорошая.

Чтобы понять, загружалась ли проблема с HD или декодирования PNG, мы изменили это, загрузив файл в поток памяти, а затем отправив этот поток памяти в декодер .NET PNG. Разница в производительности с использованием XNA или с использованием класса System.Windows.Media.Imaging.PngBitmapDecoder незначительна. Мы грубо получаем одинаковые уровни производительности.

Наши тесты показывают следующие результаты:

  • Загрузка изображений с диска: 37.76ms 1%
  • Декодирование PNG: 2816.97мс 77%
  • Загрузка изображений на видеооборудование: 196.67ms 5%
  • Состав: 87.80ms 2%
  • Получить результат композиции из видеооборудования: 166.21ms 5%
  • Кодировать в PNG: 318.13ms 9%
  • Сохранение на диск: 3.96ms 0%
  • Очистка: 53.00ms 1%

Всего: 3680.50ms 100%

Из этих результатов видно, что самые медленные части при декодировании PNG.

Итак, нам интересно, не будет ли декодер PNG, который мы могли бы использовать, что позволило бы сократить время декодирования PNG. Мы также рассматривали сохранение несжатых изображений на жестком диске, но тогда каждое изображение будет размером 10 МБ, а не 1 МБ, и поскольку на жестком диске хранится несколько десятков тысяч этих изображений, их невозможно сохранить без сжатия.

EDIT: дополнительная информация:

  • Тест сравнивает загрузку 20 изображений PNG и их компоновку. Это примерно соответствует запросам, которые мы получим в производственной среде.
  • Каждое изображение, используемое в композиции, имеет размер 1600x1600.
  • В решении будет задействовано до 10 серверов с балансировкой нагрузки, подобных тем, которые мы обсуждаем здесь. Таким образом, дополнительные усилия по разработке программного обеспечения могут стоить экономии на стоимости оборудования.
  • Кэширование декодированных исходных изображений - это то, что мы рассматриваем, но каждая композиция, скорее всего, будет выполнена с совершенно разными исходными изображениями, поэтому кэш-промахи будут высокими и производительность будет низкой.
  • Тесты были сделаны с дрянной видеокартой, поэтому мы можем ожидать, что декодирование PNG станет еще более узким местом производительности с использованием достойной видеокарты.
4b9b3361

Ответ 1

Есть еще один вариант. Иными словами, вы пишете собственный графический редактор PNG. Вы можете использовать OpenCL для выполнения этой операции достаточно эффективно (и выполнить свою композицию с помощью OpenGL, которая может совместно использовать ресурсы с OpenCL). Также возможно чередование передачи и декодирования для максимальной пропускной способности. Если это маршрут, который вы можете/хотите продолжить, я могу предоставить дополнительную информацию.

Вот некоторые ресурсы, связанные с DEFLATE (и INFLATE) на основе GPU.

Надеюсь, это поможет!

Ответ 2

Вы пробовали следующие 2 вещи.

1)
Multi thread it, есть несколько способов сделать это, но один из них будет методом "все в одном". В основном полностью создайте количество потоков X для полного выполнения.

2)
Возможно, подумайте о том, что XX-поток выполняет всю работу процессора, а затем передает его в поток GPU.

Ваш вопрос очень хорошо сформулирован для того, чтобы быть новым пользователем, но может быть полезной информация о сенарио? Мы говорим о пакетной работе или фотографиях службы в режиме реального времени? Изменились ли снимки 10k?

Аппаратные ресурсы
Вы также должны учитывать, какие аппаратные ресурсы у вас есть на вашем диспуте. Обычным является то, что две самые дешевые вещи - это мощность процессора и дисковое пространство, поэтому, если у вас есть только 10 тыс. Картинок, которые редко меняются, преобразование их в формат, который быстрее обрабатывается, может быть способом.
Многопоточные мелочи
Еще одна вещь, которую следует учитывать при выполнении многопоточности, заключается в том, что ее нормальная интеллектуальность позволяет создавать потоки в приоритете BellowNormal. Поэтому вы не делаете всю систему "задержкой". Вам нужно немного поэкспериментировать с количеством потоков для использования, если вам повезет, вы можете приблизиться к 100% -ному увеличению скорости cORE, но это зависит от аппаратного обеспечения и кода вашего запуска.

Я нормально использую Environment.ProcessorCount, чтобы получить текущий подсчет процессора и работать оттуда:)

Ответ 3

У вас есть несколько параметров

  • Повысить производительность процесса декодирования

    Вы можете реализовать еще один более быстрый png-декодер (libpng - это стандартная библиотека, которая может быть быстрее) Вы можете переключиться на другой формат изображения, который использует более простое/более быстрое декодируемое сжатие

  • Распараллеливать

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

  • Храните файлы несжатыми, но на устройстве, которое сжимает

    Например, сжатая папка или даже sandforce ssd. Это будет по-прежнему сжиматься, но по-разному и нагружать другое программное обеспечение декомпрессией. Я не уверен, что это действительно поможет, и попробовал бы это только в крайнем случае.

Ответ 4

Я написал чистый С# PNG-кодер/декодер (PngCs), вам может понадобиться его посмотреть. Но я очень сомневаюсь, что у нее будет более высокая скорость [*], она не очень оптимизирована, скорее пытается минимизировать использование памяти для работы с огромными изображениями (она последовательно кодирует/декодирует, строит за строкой). Но, возможно, он служит вам в качестве шаблона, чтобы подключить некоторые улучшения сжатия/декомпрессии. Как я вижу, узким местом скорости является zlib (inflater/deflater), который (в отличие от Java) не реализован изначально на С# - я использовал библиотеку SharpZipLib с чистым управляемым кодом С#; это не может быть очень эффективным.

Я немного удивлен, однако, что в ваших тестах декодирование было намного медленнее, чем кодирование. Мне это кажется странным, потому что в большинстве алгоритмов сжатия (возможно, во всех и, конечно же, в zlib) кодирование намного более интенсивно, чем декодирование. Вы уверены, что? (Например, этот speedtest, который считывает и записывает изображения 5000x5000 RGB8 (не очень сжимаемые, около 20 МБ на диске), дает мне около 4,5 секунд для записи и 1,5 секунды для чтения). Возможно, есть и другие факторы, помимо чистого PNG-декодирования?

[*] Обновление: новые версии (начиная с версии 1.1.14), которые имеют несколько оптимизаций; если вы можете использовать .Net 4.5, особенно, он должен обеспечить лучшую скорость декодирования.