 |
|
 |
Быстрое сжатие изображений по алгоритму JPEG на CUDA
Задача максимально быстрого сжатия изображений возникла в контексте приложений для скоростных видеокамер, выпускаемых нашей компанией. Все наши скоростные видеокамеры работают по принципу онлайн передачи всего регистрируемого потока несжатых данных от камеры в кольцевой буфер оперативной памяти компьютера. Таким образом, в компьютер поступает очень большой поток данных, которые нужно быстро обработать и записать. Обычно такие потоки данных записывают либо в оперативную память компьютера, либо на RAID-массив или SSD, а обработка всего потока данных в онлайне возможна только внутри камеры на ПЛИС (FPGA). К сожалению, софт для CPU с обработкой таких потоков данных не справляется в принципе, поэтому для решения задач этого класса мы использовали видеокарты NVIDIA с технологией CUDA.
В системах скоростной съёмки обычно используются монохромные видеокамеры, поскольку их чувствительность значительно выше, чем у цветных, поэтому ниже мы рассмотрим задачу онлайн компрессии видеопотока именно от монохромной камеры. Наша цель состоит в том, чтобы успеть всё сжать в онлайне, а полученный выходной поток записать на жёсткий диск компьютера. Мы выбрали алгоритм компрессии JPEG с потерями, потому что он может обеспечить быстроту и минимальные искажения при значительном коэффициенте сжатия, а также может быть эффективно распараллелен. Вопрос быстрого декодирования для задач скоростной съёмки не критичен, но тем не менее, декодирование изображений в формате JPEG тоже было реализовано на видеокарте.
Общая схема работы кодера JPEG на CUDA
- Загрузка приложения, инициализация и нумерация устройств, проверка их возможностей.
- Выделение памяти, создание групп потоков, синхронизация с пользовательским приложением на CPU.
- Получение от драйвера фреймграббера или от пользовательского приложения адреса или номера для последнего полученного изображения, находящегося в оперативной памяти компьютера.
- Загрузка (копирование) кадра или серии последовательных 8-битных кадров из оперативной памяти CPU в память GPU.
- Численные расчёты: Level shift, DCT, Quantization, Zig-Zag, AC/DC, DPCM, RLE, Huffman для каждого блока 8х8. Для кодирования используются статические таблицы Хаффмана. Все кадры кодируются по отдельности, корреляция кадров не учитывается.
- Создание выходной строки байт для каждого сжатого блока 8х8, упорядоченная запись таких строк, запись выходного массива в отдельный буфер оперативной памяти.
Конфигурация компьютеров для тестирования
- Настольный компьютер ASUS P6T Deluxe V2 LGA1366, X58, Core i7 920, 2,67 ГГц, DDR-III 6 ГБайт
- Видеокарты для вычислений GeForce GT 240 (CC=1.2, 96 ядер) и GeForce GTX 580 (CC=2.0, 512 ядер)
- Ноутбук ASUS N55S, Core i5 2430M, DDR III 6 ГБайт, видеокарта GeForce GT 555M (СС = 2.1, 144 ядра)
- Операционная система Windows-7, 64-bit, CUDA 4.1, драйвер 296.10
Чем ограничена производительность алгоритма
Производительность алгоритмов такого типа непросто оценить заранее. В них важную роль играют как сложность и количество вычислений, так и задержки, связанные с обращениями к памяти. Если в программе много обращений к памяти (в данном случае используются разные виды памяти, в том числе и относительно медленная глобальная память GPU), скорость выполнения программы может определяться именно пропускной способностью памяти, а вовсе не сложностью вычислений. В данном случае оба этих фактора вносят существенный вклад в суммарное время выполнения, а при использовании разных видеокарт это соотношение бывает разным.
Оценка латентности отдельных стадий обработки данных алгоритма сжатия JPEG с потерями
Для скорости сжатия одного 8-битного изображения с разрешением 7216 х 5408 (сжатие по алгоритму Baseline JPEG с потерями, коэффициент сжатия = 13, сжимаются отдельные кадры независимо друг от друга, кадр находится в оперативной памяти компьютера, видеокарта модели GeForce GTX 580, измерение времени проводится встроенным профайлером CUDA_PROFILE_LOG_VERSION 2.0) были получены следующие результаты для времени выполнения отдельных стадий обработки данных:
- HostIO (загрузка данных в оперативную память компьютера) - этой задержки нет, поскольку данные уже лежат в оперативной памяти
- Host-to-Device (время копирования данных в память GPU) - 6500 мкс
- Level shift, DCT, Quantization, Zig-Zag - 1260 мкс
- RLE+DPCM - 1570 мкс
- Huffman - 590 мкс
- Device-to-Host (запись выходной строки из видеокарты в оперативную память компьютера) - 520 мкс
- Разное - 710 мкс
- ИТОГО: 11150 мкс
Основной результат: 11150 микросекунд необходимо видеокарте GeForce GTX 580 для сжатия примерно в 13 раз 8-битного изображения с разрешением 7216 х 5408 по алгоритму Baseline JPEG с учётом загрузки и выгрузки данных. Таким образом, получена производительность сжатия порядка 3,5 ГБайт/с для компрессии в джипег на видеокарте NVIDIA.
При сжатии в джипег одной из самых медленных операцией является загрузка данных в видеокарту. В этом случае производительность вычислений (без учёта загрузки и выгрузки данных) может превышать 10 ГБайт/с. В настоящее время наше программное обеспечение может работать с 8-битными изображениями, разрешение которых не более 12000 х 12000.
К сожалению, в настоящее время у нас нет аппаратного решения, которое могло бы генерировать такой поток данных. Наша самая быстрая видеокамера может дать до 700 МБайт в секунду. Тем не менее, мы работаем над аппаратным решением, которое даст поток видео данных в диапазоне 1-2 ГБайт в секунду.
Уже есть предварительные результаты и для декодирования 8-битных изображений на видеокарте GeForce GTX 580. Получена производительность до 3,5 ГБайт в секунду с учётом загрузки и выгрузки данных для аналогичных условий. Для степеней сжатия ниже 50% скорость декодирования превышает скорость кодирования. Обязательным условием быстрого декодирования на видеокарте является наличие рестарт-маркеров в сжатом изображении. Наш кодер джипега эти маркеры ставит. Одним из очень интересных приложений для декодирования является пересылка сжатых данных в видеокарту с последующей декомпрессией и выводом картинки на монитор. В этом случае время пересылки данных в видеокарту невелико, так как данные сжаты, декодирование выполняется очень быстро, а необходимости обратной пересылки данных нет, поскольку они будут выведены на монитор.
Результаты тестирования алгоритма сжатия JPEG с потерями для 8-битных изображений 7216 х 5408
Мы получили следующие результаты для средней скорости сжатия на разных видеокартах (время загрузки изображений и их выгрузки после сжатия включено в представленные результаты):
- GeForce GT 240 (96 ядер) - 820 МБайт в секунду
- GeForce GT 555M (144 ядер, мобильный вариант) - 1420 МБайт в секунду
- GeForce GTX 580 (512 ядер) - 3,5 ГБайт в секунду
Таким образом, показана принципиальная возможность онлайн сжатия, причём для довольно широкого класса графических карт, в том числе бюджетных и мобильных. Такое решение позволит значительно увеличить длительность скоростной съёмки и даст возможность записывать сжатый поток данных на жёсткий диск компьютера даже без использования RAID или SSD.
Приложения для систем онлайн-сжатия в формате JPEG
Данное решение может использоваться не только в скоростной видеосъёмке. Существует немало других задач, связанных с необходимостью быстрого сжатия больших объёмов данных:
- Системы машинного зрения
- Системы получения, обработки и хранения медицинских изображений
- Охранные системы
- Промышленные системы
- Научные исследования
- Облачные вычисления на GPU (Cloud Services for GPU Computing)
В настоящее время реализован алгоритм сжатия с потерями только для 8-битных монохромных изображений. Если к нему добавить возможность восстановления цвета и сжатия цветных изображений, то количество возможных приложений значительно увеличится.
Сравнение с самыми быстрыми аппаратными кодерами на FPGA
Интересно отметить, что производительность системы сжатия в JPEG с потерями на базе видеокарты GeForce GTX 580 оставила позади лучшие на сегодняшний день системы аппаратного сжатия, построенные на ПЛИС (FPGA). Одни из самых быстрых систем на ПЛИС предлагают следующие компании:
- Cast Inc. (JPEG-E Baseline JPEG Compression Core) - функция аппаратного сжатия в джипег для FPGA, производительность до 750 МБайт/с.
- Alma-Tech (SVE-JPEG-E, SpeedView Enabled JPEG Encoder Megafunction) - функция аппаратного сжатия по Baseline JPEG для FPGA Altera/Xilinx, производительность до 500 МБайт/с.
- Visengi JPEG Encoder (JPEG / MJPEG Hardware Compressor IP Core) - функция аппаратного кодирования в джипег для FPGA Virtex-5, производительность до 405 МБайт/с.
- Barco BA116 JPEG Encoder (High speed baseline DCT-based JPEG color encoder) - функция аппаратного кодирования в JPEG для FPGA, производительность до 140 МБайт/с.
Эти высокопроизводительные решения написаны на Verilog/VHDL и являются оптимальными для компактных (встраиваемых) систем с минимальными требованиями по питанию и габаритам.
Сравнивая наше решение с аппаратными кодерами jpeg на ПЛИС, стоит отметить, что кроме более высокой производительности и масштабируемости полученного нами решения, по сравнению с Verilog/VHDL, код на Си для CUDA намного более понятный и приспособленный для модификации и создания на его базе новых, более сложных систем обработки и сжатия изображений.
Как достичь лучших результатов
Существует ряд методов, с помощью которых мы расчитываем в дальнейшем получить увеличение производительности подобных систем:
- Оптимизация кажой стадии алгоритма сжатия, схем распараллеливания и реализации.
- Использование новых решений NVIDIA в последних моделях видеокарт: возможности архитектуры Fermi и др.
- Использование более мощных видеокарт Quadro и Tesla.
- Распараллеливание алгоритма между разными видеокартами, увеличение количества видеокарт для организации параллельных вычислений.
|