Использование DSP-сопроцессора DM8168 с помощью фреймворка C6Accel



    В этой статье мы познакомимся с отладочной платой DM816x/C6A816x/AM389x и фреймворком C6Accel (он же C6EZAccel), а также рассмотрим инструкции по наладке системы для выполнения встроенных тестовых приложений.

    Всё началось с интересной идеи использовать алгоритмы нынче очень популярной библиотеки компьютерного зрения OpenCV на микропроцессоре. Однако, изучив немного тему, идея уточнилась. Почему бы не реализовать алгоритмы не просто на ядре ARM, а на специализированном ядре для цифровой обработки сигналов DSP? Тем самым разгрузим ядро ARМ, ускорим выполнение алгоритмов, и, глядишь, самое громоздкое приложение заработает в реальном времени.

    Итак, что же использовать для решения задачи? Оказалось вариантов немного…

    Рассмотрим всё логично и последовательно. Начнём с того, что позволяет работать с DSP процессором – это фреймворк C6Accel. Хорошо, он поддерживает OpenCV (причем 2.x) только в последней версии – 2.01.00.11. В свою очередь, этот фреймворк написан под микропроцессоры C6A81xx/DM81xx. По названию статьи вы уже догадались, что попался нам под руку DM8168, для работы с которым требуется программный интерфейс TI EZSDK (последняя версия – 5.05.02.00).

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

    1. Описание отладочной платы DM816x/C6A816x/AM389x





    Вычислительный модуль DM816x/C6A816x/AM389x, разработанный компанией Texas Instruments совместно с Spectrum Digital, позволяет производить разработку на DM816x DaVinci MPU (DM8168, DM8167, DM8166, DM8165), на C6A816x C6-Integra DSP+ARM процессорах (C6A8168, C6A8167) и на AM389x Sitara ARM MPUs (AM3894, AM3892).

    Это чудо техники предназначено для широкого спектра решений, таких как видеорегистраторы (DVRs) для наблюдения, системы организации видеоконференций, системы телевизионного вещания, медиасерверы, одноплатные компьютеры, вычислительные шлюзовые машины, маршрутизаторы, серверы, промышленная автоматика, интерфейсы «пользователь-машина» (HMIs), терминалы пунктов обслуживания для сбора данных, машинное зрение, приложения для тестирования, измерения, слежения, контроля и др.



    Теперь посмотрим на сам объект. Он состоит из двух блоков печатных плат:
    • вычислительный модуль 8168 (сверху);
    • дочерняя плата расширения входов-выходов (снизу).

    Ввиду большого количества компонентов обратим своё внимание только на особо важные.



    На рисунке выше изображён вычислительный модуль 8168 со следующими обозначенными компонентами:
    1. и 2. — это переключатели №3 (SW3) и №4 (SW4) соответственно.



    Стандартно загрузка платы происходит с флеш-памяти NAND (однако существует много других режимов, например, загрузка с SD-карты), поэтому переключатели №3 и №4 были установлены в нужное положение: SW3[9:0]=”0000010010” и SW4[1:0]=”10” [NAND/SPI].

    3. Последовательный порт (COM-порт).
    4. Порт HDMI.
    5. Порт Ethernet.
    6. Порт USB.
    7. Компонентный видеоразъем.
    8. Слот для SD-карты.
    9. Гнездо питания.
    10. Переключатель питания.
    11. Микропроцессор DM8168 (эмулирует AM3894 и C6A816).

    Функциональная диаграмма:



    Характерные особенности:
        •  VLIW-процессор C674x DSP (до 1 ГГц, тип команд – с фиксированной и плавающей точкой).
        •  RISC-процессор ARM Cortex-A8 (до 1,2 ГГц).
        •  Укоритель 3D-графики SGX530.
        •  Подсистема обработки видео высокой чёткости (HDVPSS).
        •  3 программируемых сопроцессора обработки видео высокой чёткости (HDVICP2), отвечающих за захват, кодирование, декодирование и анализ нескольких видеопотоков, а также поддерживающих стандарты H.264, MPEG4,H263, VC1/RTV, AVS, RV10, ON2, JPEG, MPEG2, DIVX.
        •  Широкий набор периферийных модулей:
           — 2 канала Gigabit Ethernet;
           — 2 канала PCI Express;
           — 2 канала SATA с интегрированным физическим уровнем;
           — 2 канала USB 2.0 с интегрированным физическим уровнем;
           — интерфейсы DDR3, MMC/SD, HDMI и DVI.

    Для дальнейшей работы мы подключались к компонентам 3, 5, 9 и настраивали переключатели 1, 2, 10.

    2. Описание фреймворка C6Accel


    C6Accel – абсолютно бесплатный инструмент разработки ПО от Texas Instruments (TI). Он предназначен для упрощения разработки кода DSP на двухъядерных гетерогенных процессорах SoC от TI, а именно для устройств ARM+DSP, которые запускают Linux на ARM и содержат процессор DSP из семейства C6000.

    2.1. Из чего состоит C6Accel?

    C6EZAccel состоит из алгоритмов цифровой обработки сигналов, которые придерживаются интерфейса алгоритмов под названием XDAIS (eXpressDsp Algorithm Interoperability Standard). TI также предоставляет фреймворк под названием Codec Engine, который позволяет эффективно выполнять алгоритмы, написанные с использованием интерфейса XDAIS. TI поставляет все свои кодеки в рамках ПО для SoC и рекомендует использование Codec Engine. C6EZAccel также состоит из библиотеки на стороне ARM, являющейся надстройкой над Codec Engine, который предоставляет APIs (интерфейсы программирования приложений). А они, в свою очередь, позволяют коду приложения на стороне ARM вызывать выполнение алгоритмов XDAIS на DSP. Эта библиотека содержит в себе управление кешем, преобразование адресов, передачу параметров и обработку ошибок из приложения, работающего на ARM.

    2.2. Как работает C6Accel?

    Код ARM-приложения (или промежуточное ПО, которое его использует) вызывает C6Accel. Он использует оболочку библиотеки APIs и/или Codec Engine, совместимый c iUniversal APIs, которые, как и VISA APIs, используются для вызова Audio/Video/Speech-кодеков. Потом эти APIs просматривают интерфейс Codec Engine и вызывают алгоритм C6Accel на DSP, который идентифицирует вызов функции и задействует соответствующую функциональность на DSP, используя параметры, переданные из приложения.



    3. Использование EZSDK и C6Accel


    Достаточно теории, приступим к практике. EZSDK 5.05.02.00 поддерживается только в Ubuntu 10.04 LTS 32-bit или Ubuntu 11.10 32-bit. Поэтому тем, у кого не установлена одна из этих ОС (конечно же, мы работали под более новой версией), придётся использовать виртуальную машину, например, VirtualBox. Инструкции по её установке и настройке имеются здесь.

    Далее используются следующие обозначения:
    • host $ – команда для выполнения на хосте;
    • target # – команда для выполнения на целевой ОС.

    3.1. Установка и сборка EZSDK

    Перед началом работы с EZSDK следует скачать и установить компилятор С CodeSourcery Toolchain 2009q-203. Просто распакуйте архив в домашнюю директорию.

    Скачайте EZSDK 5.05.02.00 и выполните:
    host $ sudo ./ezsdk_dm816x-evm_5_05_02_00_setuplinux
    

    Запустится установщик. Укажите расположение CodeSourcery Toolchain, т. е. /home/%username%/arm-2009q1/bin, и путь для установки EZSDK – /home/%username%/ezsdk.

    Разработчики данного ПО позаботились о нас и сделали интерактивный скрипт (одна из причин строгой привязки к версии OC):
    host $ export EZSDK="${HOME}/ezsdk"
    host $ sudo ${EZSDK}/setup.sh
    

    Скрипт установит необходимые пакеты и попросит уточнить:
    • путь установки целевой файловой системы – /home/%username%/targetfs;
    • путь корневой директории tftp – /tftpboot;
    • путь последовательного порта – /dev/ttyUSB0 (для подключения по USB-порту) или /dev/ttyS0 (для подключения по COM-порту);
    • ip-адрес хост-машины – у каждого свой (например, у нас 10.54.4.44);
    • расположение ядра Linux – 1-е из предложенного списка, т. е. TFTP;
    • расположение корневой файловой системы – 1-е из предложенного списка, т. е. NFS;
    • имя образа ядра, загружаемого из TFTP – uImage-dm816x-evm.bin;
    • создавать ли скрипт для minicom – согласитесь;
    • запускать ли сейчас созданный скрипт – откажитесь.

    Cкорректируем этот скрипт: откроем его в текстовом редакторе и заменим текст «mem=364M@0x80000000 mem=320M@0x9FC00000» на «mem=364M», так как в дальнейшем невозможно будет загрузить необходимые модули ядра.

    Далее, для выполнения каких-либо операций на плате нужно запустить minicom с настройками, указанными в скрипте, командой
    host $ minicom -S setup_uimage-tftp_fs-nfs.minicom
    

    Далее нужно перезапустить плату.

    Теперь при сборке EZSDK возникает проблема из-за отсутствия некоторого компонента. Можно починить, распаковав архив 8272.pcie.tar.gz в директорию /home/%username%/ezsdk/example-applications.

    Наконец соберём EZSDK командами
    host $ cd ${HOME}/ezsdk
    host $ sudo make all
    host $ sudo make install
    

    3.2. Установка и сборка С6Accel

    Скачайте C6Accel 2.01.00.11 и выполните:
    host $ sudo ./c6accel_2_01_00_11_Linux-x86_Setup.bin
    

    Укажите путь установки /home/%username%/c6accel.

    Операционная система реального времени SYS/BIOS является составной частью EZSDK, однако версии позже 6.32.02.09 не поддерживают Real Time Data eXchange (RTDX), который необходим при сборке С6Accel. Поэтому установим SYS/BIOS 6.32.02.09 специально для С6Accel:
    host $ sudo ./bios_setuplinux_6_32_02_39.bin
    

    Укажите путь установки /home/%username%/c6accel/bios_6_32_02_39.

    Исправим пути в файле Rules.make в /home/%username%/c6accel на следующие:
    DVSDK_INSTALL_DIR=$(HOME)/ezsdk
    TARGETFS_INSTALL_DIR = $(HOME)/targetfs
    C6ACCEL_INSTALL_DIR=$(HOME)/c6accel
    BIOS_INSTALL_DIR = $(HOME)/c6accel/bios_6_32_02_39
    DSPDEVKIT_INSTALL_DIR= $(DVSDK_INSTALL_DIR)/dsp-devkit
    LINUXDEVKIT_INSTALL_DIR = $(DVSDK_INSTALL_DIR)/linux-devkit
    PLATFORM = dm816x-evm
    

    И, в конце концов, соберём С6Accel командами:
    host $ cd ${HOME}/c6accel
    host $ sudo make all
    host $ sudo make install
    

    3.3. Выполнение теста DSP

    Приятно, что C6Accel содержит в себе пример для тестирования выполнения кода на DSP-процессоре. Выполним скрипт загрузки модулей cmem и dsplink (это библиотеки связки ARM и DSP, с помощью которых грузится CodecEngine) и запустим тестирующие приложение.
    target # cd /opt/c6accel_app/c6accel_dsplib_testapp
    target # ./loadmodules_ti8168_c6accel.sh
    target # ./c6accel_dsplib_testapp
    

    Ура! По сообщениям в консоли видно, что всё в порядке и ничего не сломано
    ******************************************************************************
    Sample application for testing kernels in C6Accel started.
    ******************************************************************************
    CERuntime complete
    C6Accel handle created

    Test for Vision/Analytics functions in C6Accel:



    Testing the function: VLIB_histogram_1D_дU8…
    VLIB_histogram_1D_U8 passed the test!


    Testing the function: VLIB_histogram_1D_U16…
    VLIB_histogram_1D_U16 passed the test!


    Testing the function: VLIB_histogram_nD_U16…
    VLIB_histogram_nD_U16 passed the test!


    Testing the function: VLIB_weightedHistogram_1D_U8…
    VLIB_weightedHistogram_1D_U8 passed the test!


    Testing the function: VLIB_weightedHistogram_nD_U16…
    VLIB_weightedHistogram_nD_U16 failed the test!
    VLIB_unpackMask32 passed the test!
    VLIB_packMask32 passed the test!
    VLIB_subtractBackGroundS16 passed the test!
    VLIB_subtractBackGroundS32 passed the test!


    Testing the function: VLIB_extractLumaFromUYUV…
    C6accel test for VLIB_extractLumaFromUYUV passed the test!


    Testing the function: VLIB_convertUYVYsemipl_to_YUVpl…
    VLIB_convertUYVYsemipl_to_YUVpl passed the test!


    Testing the function: VLIB_convertUYVYpl_to_YUVint…
    VLIB_convertUYVYpl_to_YUVint passed the test!


    Testing the function: VLIB_convertUYVYint_to_YUVpl…
    VLIB_convertUYVYint_to_YUVpl passed the test!


    Testing the function: VLIB_convertUYVYint_to_RGBpl…
    VLIB_convertUYVYint_to_RGBpl passed the test!


    Testing the function: VLIB_ConvertUYVYint_to_YUV420pl…
    VLIB_ConvertUYVYint_to_YUV420pl passed the test!


    Testing the function: VLIB_convertUYVYint_to_LABpl…
    VLIB_convertUYVYint_to_LABpl passed the test!


    Testing the function: VLIB_convertUYVYint_to_HSLpl…
    VLIB_convertUYVYint_to_HSLpl passed the test!


    Testing the function: VLIB_convertUYVYint_to_LABpl_LUT…


    Completed initialization.
    VLIB_convertUYVYint_to_LABpl2 passed the test!
    Testing VLIB_harrisScore_7x7…
    VLIB_harrisScore_7x7 passed the test!


    Initializing Legendre Polynomial

    Computing Legendre Moments


    Testing the function: VLIB_legendreMoments…
    VLIB_legendreMoments passed the test!


    Testing the function: VLIB_normalFlow_16…
    VLIB_normalFlow_16 passed the test!


    Testing the function: VLIB_kalmanFilter_4x6 functions…
    VLIB_kalmanFilter_ VLIB_recursiveFilterHoriz1stOrderS16…
    VLIB_recursiveFilterHoriz1stOrderS16 passed the test!

    Testing VLIB_recursiveFilterVert1stOrядра.der…
    VLIB_recursiveFilterVert1stOrder passed the test!

    Testing VLIB_recursiveFilterVert1stOrderS16…
    VLIB_recursiveFilterVert1stOrderS16 passed the test!


    Testing the function: VLIB_bhattacharyaDistance_U32…
    VLIB_bhattacharyaDistance_U32 passed the test!


    Testing the function: VLIB_L1DistanceS16…
    VLIB_L1DistanceS16 functions passed the test
    VLIB_dilate_bin_mask passed the test!
    VLIB_dilate_bin_square passed the test!
    VLIB_dilate_bin_cross passed the test!
    VLIB_erode_bin_mask passed the test!
    VLIB_erode_bin_square passed the test!
    VLIB_erode_bin_cross passed the test!
    Testing VLIB_trackFeaturesLucasKanade_7x7…
    VLIB_trackFeaturesLucasKanade_7x7 passed the test!
    VLIB Canny functions Test results:
    IMG_conv_7x7: passed the test!
    VLIB_xyGradient: passed the test!
    VLIB_nonMaximumSuppressionCanny: passed the test!
    VLIB_doublethresholding: passed the test!
    VLIB_edgeRelaxation: passed the test!

    Calling Chained Canny API:
    Chained Canny edge detection function failed the test!


    Testing the function: VLIB_integralImage8…
    VLIB_integralImage8 passed the test!


    Testing the function: VLIB_integralImage16…
    VLIB_integralImage16 passed the test!


    Testing the function: VLIB_imagePyramid8…
    VLIB_imagePyramid8 passed the test!


    Testing the function: VLIB_imagePyramid16…
    VLIB_imagePyramid16 passed the test!


    Testing the function: VLIB_gauss5x5PyramidKernel_8…
    VLIB_gauss5x5PyramidKernel_8 passed the test!


    Testing the function: VLIB_gauss5x5PyramidKernel_16…
    VLIB_gauss5x5PyramidKernel_16 passed the test!


    Testing the function: VLIB_gradientH5x5PyramidKernel_8…
    VLIB_gradientH5x5PyramidKernel_8 passed the test!


    Testing the function: VLIB_gradientV5x5PyramidKernel_8…
    VLIB_gradientV5x5PyramidKernel_8 passed the test!

    VLIB_initMeanWithLumaS16 passed the test!
    VLIB_updateEWRMeanS16 passed the test!
    VLIB_initMeanWithLumaS32 passed the test!
    VLIB_updateEWRMeanS32 passed the test!
    VLIB_initVarWithConstS32 passed the test!
    VLIB_updateEWRVarianceS32 passed the test!
    VLIB_initVarWithConstS16 passed the test!
    VLIB_updateEWRVarianceS16 passed the test!
    VLIB_updateUWRMeanS16 passed the test!
    VLIB_updateUWRVarianceS16 passed the test!

    Test for Image processing functions in C6Accel:

    Tests for Histogram functions successful
    Test for Median Filtering functions successful
    Tests for Convolution functions successful
    Tests for Correlation functions successful
    Tests for Sobel Filter successful
    Test for Image multiplication functions successful
    Tests for Image addition functions successful
    Tests for Image substraction functions successful
    Tests for Color Space Conversion functions successful
    C6accel_IMG_ycbcr422pl_to_ycbcr422sp() successful
    C6accel_IMG_ycbcr422sp_to_ycbcr422ile() successful
    C6accel_IMG_ycbcr422sp_to_ycbcr420pl successful

    Test for Fixed point Signal processing functions in C6Accel

    Tests for FFT functions successful
    Tests for Invers FFT functions successful
    Test for Auto Correlation function successful
    Tests for DoT Product functions successful
    Tests for Matrix multiplication successful
    Tests for FIR Filtering functions successful
    Test for IIR Filter successful

    Test for Fixed point Math functions in C6Accel

    Test for Arithmetic RTS functions successful
    Tests for Conversion RTS functions successful
    Tests for IQmath Conversion functions successful
    Tests for Mathematical IQmath functions successful
    Tests for Arithmetic IQmath functions successful
    Tests for Trignometric IQmath functions successful

    Test for Floating point Math Functions in C6Accel

    Test for Arithmetic RTS functions successful
    Tests for Conversion RTS functions successful
    Tests for Floating point RTS single precision functions successful
    Tests for Floating point RTS double precision functions successful

    Test for Floating point Signal processing Functions in C6accel

    Test for Floating point DSP FFT function successful
    Test for Floating point DSP vector multiplication successful
    Test for Floating point DSP vector reciprocal function successful
    Test for Floating point DSP vector reciprocal function successful
    Test for Floating point DSP vector weighted sum function successful
    Test for Floating point DSP vector dot product function executed successful
    Tests for Floating point DSP matrix functions successful
    Tests for Floating point DSP Matrix Multiplication functions successful
    Test for Floating point DSP matrix transpose function successful
    Tests for Floating point DSP autocorrelation functions successful
    Tests for Floating point DSP convolution functions successful
    Test for Floating point DSP FIR filter successful
    Test for Floating point DSP Inverse FFT function successful
    Test for Floating point DSP BIQUAD Filter successful
    Test for Floating point to Double precision successful
    Test for Complex to real and imaginary passed successfully
    -> Asynchronous Calls
    Tests for FFT functions successful
    Tests for Sobel Filter successful
    Test for Arithmetic RTS functions successful
    ******************************************************************************
    All tests done.
    ******************************************************************************


    4. Тест сравнения работы функций OpenCV на ARM и DSP


    OpenCV (Open Source Computer Vision Library) – библиотека алгоритмов компьютерного зрения, обработки изображений и численных алгоритмов общего назначения с открытым исходным ко-дом. Библиотека написана на C и C++, однако поддерживается Java, Python и др. Работает под Linux, Windows и Mac OS X.

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

    Так как библиотека OpenCV является переносимым ПО, её можно скомпилировать в большинстве систем, в которых предусмотрен компилятор C/C++. OpenCV успешно используется на ARM, MIPS, Xscale и других процессорах.

    Стоит заметить, что в C6Accel 2.01.00.11 имеются не все функции OpenCV, а лишь 50.

    4.1. Установка и сборка OpenCV

    Следуйте инструкциям для сборки OpenCV 2.2.0 под ARM-платформу. При их выполнении помните, что CodeSourcery Toolchain уже установлен.

    Скопируем разделяемые библиотеки OpenCV в целевую файловую систему.
    host $ cp ${HOME}/build/lib/* ${HOME}/targetfs/usr/lib
    

    4.2. Сборка и выполнение теста

    Первая проблема, с которой пришлось столкнуться, – это ошибка при загрузке изображений. Почему-то не нравятся картинки с расширением png, ошибка локализована в функции cvCreateImage. Ладно, изменим на другое расширение, например, bmp. Это можно сделать так:
    host $ cd ${HOME}/c6accel/soc/app/c6accel_opencv_testapp/opencv_images
    host $ for fname in *.png; do convert "$fname" "$fname.bmp"; done
    

    И конечно, не забудем изменить расширения в исходном коде. В файлах appMain.c и c6accel_opencv_testfxns.c расположенных в директории /home/%username%/c6accel/soc/app/c6accel_opencv_testapp заменим все вхождения строки «.png» на «.png.bmp», для этой цели удобен текстовый редактор gedit с комбинацией клавиш Ctrl+H.

    Второй проблемой оказались ошибка при выполнении функции C6Accel_test_Matchshapes и отказ работы функции cvFindCornerSubPix (в связи с известным багом http://code.opencv.org/issues/963).

    В файле appMain.c закомментируем строку с функцией C6Accel_test_Matchshapes. А в файле c6accel_opencv_testfxns.c закомментируем текст со строки
    //cvFindCorner SubPix issue to be resolved 
    
    и включительно до строки
    printf("Called ARM FindCornerSubPix function (time: %f ms)\n", t_algo / 1000.0 / n);
    

    Напоследок соберём и запустим тестовое приложение.
    host $ cd ${HOME}/c6accel
    host $ sudo make opencv_app
    host $ sudo make opencv_app_install
    target # cd /opt/c6accel_app/c6accel_opencv_testapp
    target # ./loadmodules_ti8168_c6accel.sh
    target # ./c6accel_opencv_testapp
    

    Ура! После долгих мучений всё заработало.

    Результат работы приложения подытожен в таблице

    Функция OpenCV 


    Среднее время
    выполнения
    на ARM, мс


    Среднее время
    выполнения
    на DSP, мс


    Отметка о
    выборе
    DSP


    Разница между результатами выполнения
    на ARM и DSP (расстояние в пространстве
    L2, если не указано иное)


    cvCanny


    43.218000


    42.804000


    +


    0.000000


    get Affine transform matrix


    0.557000


    0.411000


    +


    0.000000


    Affine transform


    46.325000


    36.554000


    +


    7926.342031


    2D Rotation Matrix


    0.314000


    0.378000


    -


    0.000000


    Rotation using Affine


    55.380000


    40.985000


    +


    774.451419


    cvIntegral


    6.537000


    8.232000


    -


    0.000000


    cvMinMaxLoc


    3.083000


    1.660000


    +


    Результаты совпадают


    cvNorm


    1.881000


    1.336000


    +


    0.000000


    AddS


    9.573000


    12.434000


    -


    0.000000


    AbsDiff


    9.036000


    14.349000


    -


    0.000000


    AbsDiffS


    10.555000


    12.670000


    -


    0.000000


    Add


    8.931000


    15.852000


    -


    0.000000


    cvDilate


    3.182000


    1.282000


    +


    0.000000


    cvErode


    3.093000


    1.281000


    +


    0.000000


    cvLaplace


    180.171000


    11.968000


    +


    0.000000


    cvPyrDown


    4.265000


    4.917000


    -


    0.000000


    cvFilter2D


    519.593000


    21.259000


    +


    3651.030129


    cvFindContours


    11.915000


    17.753000


    -


    Результаты совпадают


    EqualizeHist


    5.809000


    8.921000


    -


    0.000000


    SetZero


    0.634000


    3.871000


    -


    132898.252336


    Rectangle


    5.847000


    1.307000


    +


    Circle


    3.652000


    3.323000


    +


    Flip


    12.372000


    12.071000


    +


    0.000000


    Copy


    2.479000


    6.072000


    -


    Sobel


    5.463000


    7.197000


    -


    0.000000


    ConvertScale


    5.139000


    6.044000


    -


    Adaptive threshold


    89.986000


    33.231000


    +


    0.000000


    cvMulSpectrums


    91.865000


    15.221000


    +


    0.086427


    cvDFT


    597.131000


    99.666000


    +


    cvNormalize


    57.318000


    13.576000


    +


    cvSmooth


    109.345000


    57.467000


    +


    1771.619316


    HoughLines2D


    2314.028000


    634.262000


    +


    46306.904723


    cvCornerHarris


    653.550000


    168.213000


    +


    0.136828


    cvCornerEigenValsAndVecs


    3430.892000


    870.525000


    +


    350.751214


    cvCornerMinEigenVal


    1384.182000


    1.155000


    +



    cvMulSpectrums


    91.711000


    15.323000


    +


    0.086427


    cvDFT


    597.707000


    99.412000


    +


    cvNormalize


    58.782000


    13.751000


    +


    GoodFeaturesToTrack


    1259.277000


    279.508000


    +



    FindCornerSubPix



    449.029000


     


    cvMatchTemplate


    1576.569000


    221.753000


    +


    3.741657


    cvThreshold


    2.182000


    4.442000


    -


    0.000000


    cvBoundingRect


    0.036000


    0.302000


    -


    Разница между полученными площадями – 0.000000


    cvDrawContour


    0.030000


    0.989000


    -


    cvContourArea


    0.049000


    0.231000


    -


    Plotting



    183.243000


     


    CvtColor


    16.283000


    13.804000


    +


    0.000000


    Resize


    18.357000


    17.617000


    +


    cvCalcOpticalFlowPyrLK


    2472.993000


    146.874000


    +


    Оба результата состоят из 445 особенностей


    HaarDetectObjects


    2522.499000


    460.350000


    +


    Оба результата состоят из 5-ти элементов.


    ARM:


      0:   46,   48 (42x42)


      1:  174,   48 (37x37)


      2:  240,   51 (38x38)


      3:  110,   48 (40x40)


      4:   92,   37 (131x131)


    DSP:


      0:   47,   49 (40x40)


      1:  175,   49 (35x35)


      2:  240,   52 (37x37)


      3:   17,  198 (34x34)


      4:  110,   48 (38x38)




    По результатам можно сделать выводы:
    • У некоторых функций имеется разница между результатами выполнения. Архитектура сигнальных процессоров, по сравнению с микропроцессорами общего применения, имеет некоторые особенности, связанные со стремлением максимально ускорить выполнение типовых задач ЦОС. DSP ориентированы, в первую очередь, на многократное выполнение умножения с расчётом «на лету» адресов перемножаемых элементов массивов. Алгоритм, реализованный на различных базовых операциях, может давать различные результаты.
    • Не все функции работают быстрее на DSP, чем на ARM. Можно заметить закономерность: это функции базовых операции над матрицами или функции, которые в основном из них состоят. Такие «плохие» функции можно выполнять на ARM, в то время как другие пере-нести на DSP. В случае перегрузки процессора ARM использование некоторых «плохих» функций на DSP может быть терпимым.
    • При использовании «хороших» функции на DSP можно достичь улучшения в разы и даже более чем на порядок. Это, как правило, наиболее трудоёмкие функции.

    Таким образом, балансируя между быстродействием, загрузкой процессоров и результатами выполнения можно существенно оптимизировать работу приложения.

    Полезные ссылки:
    1. Плата DM816x/C6A816x/AM389x
    2. Загрузка DM816x
    3. Руководство пользователя EZSDK
    4. Фреймворк C6Accel
    5. Хорошая книга по OpenCV + частичный перевод на русский
    6. Статья о применении OpenCV на процессорах ARM и DSP
    Promwad
    Контрактная разработка и производство электроники

    Comments 10

      +1
      Меня недавно попросили помочь с разработкой модуля компьютерного зрения для коптера и спросили про DSP (т.к. на нем реализовывали поиск ключевых точек на изображении и добивались 30FPS).
      Я никогда не имел с ним дело, но как я понял после поверхностного изучения, чтобы заставить его работать с OpenCV нужна промежуточноя библиотека, реализация которой зависит от самого процесора. Плюс DSP работает только с целыми числами, отсюда не все алгоритмы можно портировать на него (ваша таблица это подтвердает). То есть есть большая зависимость от конкретного железа.
      Поэтому я сделал на плате Jetson, где, кстати полноценный gpu и официальная поддержка OpenCV.
      Дествительно ли c DSP много подобных сложностей или я преувеличил?
        0
        Спасибо за вопрос, victor1234.

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

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

        Наша таблица не подтверждает, что не все алгоритмы OpenCV можно портировать, она лишь говорит о том, что разработчики С6Accel портировали не все. :)
          0
          С таблицей я передернул, конечно.
          0
          Говорю, как человек, который имел дело с DSP. Почти все алгоритмы можно портировать на DSP. Некоторые кладутся на инструкции лучше, некоторые хуже.
          Некоторые алгоритмы вообще за вменяемое время невозможно заставить работать из-за их особенностей. В таких случаях часть логики делают в виде электронной схемы на железе.

          А арифметику с плавающей точкой на DSP заменяют арифметикой с фиксированной точкой — en.wikipedia.org/wiki/Fixed-point_arithmetic
          С разбегу в арифметику с фиксированной точкой конечно же не въедешь. И за месяц экспертом по портированию алгоритмов на DSP тоже не стать.
            0
            Скажите, если стоит задача компьютерного зрения, где важен вес, размер, да и стоимость. На сколько рационально и реально пытаться портировать OpenCV на DSP?

            Какие приблизительно процессоры подойдут, на сколько код будет портируем между ними и на какое время расчитывать, учитывая, что с OpenCV я работаю достаточно долго и внутреннее устройство ее представляю, а с DSP не работал никогда?

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

              Обычно оптимизация звукового какого-то кодека занимает от 2 до 6-х человеко-месяцев. При этом подрузамевается, что человек или группа людей уже имеет опыт такой деятельности. Но это мы выжимали из DSP все соки. Абсолютно все соки.

              Основная часть оптимизаций идет за счет VLIW архитектуры. Компиляторы конечно умные, но не настолько, чтобы распараллелить алгоритм на несколько одновременных частей. Для большего понимания, на отладочной платы из статьи стоит DSP C674x. Открываем доку на эту DSP: www.ti.com/lit/ug/sprufe8b/sprufe8b.pdf

              В разделе «1.2. DSP Features and Options» видим основные характеристики:
              — 64 general-purpose 32-bit registers
              — Eight functional units:
              — — Two multipliers
              — — Six ALUs
              — Executes up to eight instructions per cycle

              Т.е. за такт можно исполнить 2 умножения и по одной какой-то инструкции из каждого ALU. Всего — 8 инструкций за такт. Но не все комбинации процессорных команд возможны. В той же доке такие ограничения описаны например в «3.8 Resource Constraints».

              И так у каждого DSP проца: своя дока, свои инструкции, свое количество регистров, свои ограничения на набор инструкций в одном пакете. Я к тому, что один раз заоптимизированный алгоритм, при переходе на другой DSP проц, приходится оптимизировать почти заново.

              По итогу, жесткие оптимизации + куча человеко-времени и алгоритм начинает работать за приемлемое количество тактов процессора и становится пригоден для использования в realtime.
          0
          Мне удалось немного поработать с чем-то похожим (TI DM36x), конкретней со связкой ARM(linux) + DSP. Ощущения остались двоякие, с одной стороны эта был первый опыт с подобными SoC, с другой нагромождение API и витиеватая система сборки с java кодом потребовала немало усилий чтобы перейти к задаче от борьбы с тулчейном и «API». К тому же очень болезненна прошла смена версии ядра на отличную от SDK.
          Приходилось ли Вам выходить за рамки этих готовых интерфейсов и зачем? Как отлаживали DSP код кроме dbgprintf (всякие CE_DEBUG=..)?
            0
            nickpetrovsky, спасибо, что поделились впечатлениями о работе с ARM(linux) + DSP.

            Для автора статьи это был первый опыт с SoC такого рода. Выходить за рамки готового пока не приходилось, но предвидится задача преобразования теста функций OpenCV на ARM и DSP в программу для конкретных вычислений. Насчет отладки можно лишь сказать про существование Code Composer Studio(CCS).
              0
              Ещё отметим, что на TI DM36x доступен не DSP, а HDVICP и MPEG/JPEG co-processor.
                +1
                Согласен. Для dm365 была задача интеграции кодека в CE. SoС c DSP был OMAP3530.

            Only users with full accounts can post comments. Log in, please.