В этом примере показано, как интегрировать код CUDA®, сгенерированный для нейронной сети для глубокого обучения в Simulink®. Графический процессор coder™ не поддерживает генерацию кода для блоков Simulink, но можно все еще использовать вычислительную мощность графических процессоров в Simulink путем генерации динамически подключаемой библиотеки (dll) с GPU Coder и затем интеграции его в Simulink как Блок s-function при помощи Legacy Code Tool. Для получения дополнительной информации смотрите legacy_code. Чтобы проиллюстрировать эту концепцию, пример использует Обнаружение Маршрута, Оптимизированное с GPU Coder. Исходный пример использовал файл C++ с функциями OpenCV, чтобы считать системы координат, чертить маршруты и наложить информацию о частоте кадров о видеовыходе. Этот пример использует блоки Simulink от Системы Компьютерного зрения Toolbox™, чтобы выполнить те же операции.

Предпосылки

  • CUDA включил NVIDIA®, графический процессор с вычисляет возможность 3.2 или выше.

  • NVIDIA инструментарий CUDA и драйвер.

  • Библиотека NVIDIA cuDNN.

  • Переменные окружения для компиляторов и библиотек. Для получения информации о поддерживаемых версиях компиляторов и библиотек, смотрите Сторонние продукты. Для подготовки переменных окружения смотрите Подготовку Необходимых как условие продуктов.

  • Интерфейс GPU Coder™ для Библиотек Глубокого обучения поддерживает пакет. Чтобы установить этот пакет поддержки, используйте Add-On Explorer.

Проверьте среду графического процессора

Используйте coder.checkGpuInstall функция, чтобы проверить, что компиляторы и библиотеки, необходимые для выполнения этого примера, настраиваются правильно.

envCfg = coder.gpuEnvConfig('host');
envCfg.DeepLibTarget = 'cudnn';
envCfg.DeepCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);

Рабочий процесс

Эта схема иллюстрирует общую процедуру для использования Legacy Code Tool интегрировать код CUDA, сгенерированный для нейронной сети для глубокого обучения в Simulink.

Получите предварительно обученный SeriesNetwork

[laneNet,coeffMeans,coeffStds] = getLaneDetectionNetwork();

Архитектура предварительно обученного SeriesNetwork похоже на AlexNet за исключением того, что последние несколько слоев заменяются меньшим, полносвязным слоем и регрессией выходной слой. Эта сеть берет вход изображений и выходные параметры два контура маршрута, которые соответствуют левым и правым маршрутам автомобиля, оборудованного датчиком. Каждый контур маршрута представлен параболическим уравнением. Здесь, боковое смещение и продольное расстояние от транспортного средства. Сетевые выходные параметры эти три параметра, и которые описывают параболическое уравнение для левых и правых контуров маршрута. Переменные coeffStds и coeffMeans содержите среднее значение и значения станд. от обучившего сеть. Эти значения требуются в процессе моделирования.

Основная функция точки входа

Этот пример использует detect_lane.m функцию точки входа. detect_lane функция вычисляет и координаты, соответствующие положениям маршрута от, и параметры. detect_lane функция также выполняет расчеты, которые сопоставляют и координаты, чтобы отобразить координаты.

Сгенерируйте динамически подключаемую библиотеку (DLL) для функции

Запускать detect_lane функция на графическом процессоре от Simulink, сгенерируйте разделяемую библиотеку при помощи GPU Coder. Входные параметры к detect_lane функция является видеокадром, средним значением и значениями станд. Значения передаются при помощи -args опция отражает размер этих входных параметров. Скопируйте сгенерированную библиотеку в папку верхнего уровня.

Isize = single(zeros(227,227));

cfg = coder.gpuConfig('dll');
cfg.TargetLang = 'C++';
cfg.GenerateReport = true;
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
codegen -args {ones(227,227,3,'single'),ones(1,6,'double'),ones(1,6,'double')} -config cfg detect_lane

if ispc
    copyfile(fullfile(pwd, 'codegen','dll', 'detect_lane','detect_lane.dll'), pwd);
else
    copyfile(fullfile(pwd, 'codegen','dll', 'detect_lane','detect_lane.so'), pwd);
end
Code generation successful: To view the report, open('codegen/dll/detect_lane/html/report.mldatx').

Сгенерируйте и скомпилируйте S-функцию

Пример обнаружения маршрута зависит от времени выполнения CUDA NVIDIA, cuBLAS, и cuDNN библиотеки. Legacy Code Tool структура данных задает:

  • Имя для S-функции

  • Спецификации для существующей функции C++

  • Вся библиотека и заголовочные файлы требуются для компиляции и путей к файлам

  • Опции для сгенерированной S-функции

После определения структуры используйте функцию legacy_code для:

  • Инициализируйте Legacy Code Tool структура данных для функции C++

  • Сгенерируйте S-функцию для использования в процессе моделирования

  • Скомпилируйте и соедините сгенерированную S-функцию в динамически загружаемый исполняемый файл (MEX)

  • Сгенерируйте Блок s-function маскированный для вызова сгенерированной S-функции

srcPath = fullfile(pwd, 'codegen', 'dll', 'detect_lane');

if ispc
    cuPath = getenv('CUDA_PATH');
    cudaLibPath = fullfile(cuPath,'lib','x64');
    cudaIncPath = fullfile(cuPath,'include');

    cudnnPath = getenv('NVIDIA_CUDNN');
    cudnnIncPath = fullfile(cudnnPath,'include');
    cudnnLibPath = fullfile(cudnnPath,'lib','x64');

    libs = {'detect_lane.lib','cudart.lib','cublas.lib','cudnn.lib'};

else
    [~,nvccPath] = system('which nvcc');
    nvccPath = regexp(nvccPath, '[\f\n\r]', 'split');
    cuPath = erase(nvccPath{1},'/bin/nvcc');
    cudaLibPath = fullfile(cuPath,'lib64');
    cudaIncPath = fullfile(cuPath,'include');

    cudnnPath = getenv('NVIDIA_CUDNN');
    cudnnIncPath = fullfile(cudnnPath,'include');
    cudnnLibPath = fullfile(cudnnPath,'lib64');

    [~,cmdout] = system('ldconfig -p | grep "libcublas.so "');
    pathStrIdx =  strfind(cmdout,'/usr/');
    cublasLibPath = fileparts(cmdout(33:end));
    cublasIncPath = '/usr/include';

    libs = {'detect_lane.so','libcudart.so','libcublas.so','libcudnn.so'};
end

headerPath = {srcPath;cudnnIncPath;cudaIncPath;cublasIncPath};
libPath = {srcPath;cudnnLibPath;cudaLibPath;cublasLibPath};

% Define the Legacy Code Tool data structure
def = legacy_code('initialize');
def.SFunctionName = 'lane_detect_sfun';
def.OutputFcnSpec = 'void detect_lane(single u1[154587],double u2[6],double u3[6],uint8 y1[1],single y2[56],single y3[56])';
def.IncPaths = headerPath;
def.HeaderFiles = {'detect_lane.h'};
def.LibPaths = libPath;
def.HostLibFiles = libs;
def.Options.useTlcWithAccel = false;
def.Options.language = 'C++';

legacy_code('sfcn_cmex_generate', def);
legacy_code('compile', def);
### Start Compiling lane_detect_sfun
    mex('lane_detect_sfun.cpp', '-I/mathworks/home/lnarasim/Documents/MATLAB/Examples/deeplearning_shared-ex59437955/codegen/dll/detect_lane', '-I/mathworks/hub/3rdparty/R2019b/4462385/glnxa64/cuDNN/cuda/include', '-I/usr/local/cuda/include', '-I/usr/include', '-I/mathworks/home/lnarasim/Documents/MATLAB/Examples/deeplearning_shared-ex59437955', '/mathworks/home/lnarasim/Documents/MATLAB/Examples/deeplearning_shared-ex59437955/codegen/dll/detect_lane/detect_lane.so', '/usr/local/cuda/lib64/libcudart.so', '/usr/lib/x86_64-linux-gnu/libcublas.so', '/mathworks/hub/3rdparty/R2019b/4462385/glnxa64/cuDNN/cuda/lib64/libcudnn.so')
Building with 'g++'.
MEX completed successfully.
### Finish Compiling lane_detect_sfun
### Exit

OutputFcnSpec аргумент задает функцию что S-вызовы-функции на каждом временном шаге. detect_lane.h заголовочный файл в codegen папке предоставляет функциональную информацию о спецификации. Сопоставьте detect_lane аргументы функции к Блоку s-function Simulink при помощи исключительно пронумерованного u лексема для входных портов и y лексема для выходных портов. Типы данных генерации кода, заданные в tmwtypes.h, должны также быть сопоставлены с типами данных, которые поддерживает Simulink. Для получения дополнительной информации смотрите Объявление Спецификаций Функции Legacy Code Tool. Поскольку этот пример уже содержит полную модель Simulink, генерация Блока s-function не выполняется. Чтобы сгенерировать Блок s-function, используйте:

legacy_code('slblock_generate', def);

Создайте модель Simulink для обнаружения маршрута

Переместитесь весь пред - и операции последующей обработки в main_lanenet.cpp файл исходного примера в Simulink. Входная подсистема Обработки видеоданных удаляет нормализацию, выполняемую мультимедийным блоком читателя, и изменяет размер входного видеокадра к входному размеру слоя сети обнаружения маршрута, 227 227 3. Подсистема затем преобразует 3D видеокадр в одномерный вектор, требуемый detect_lane библиотека. Точки Маршрута позволили процессам подсистемы левых и правых точек маршрута сделать их подходящими для блока Draw Lanes. Модель Simulink использует видеодисплей, чтобы показать обнаружение маршрута на демонстрационном видео.

open_system('main_lanenet');
set_param('main_lanenet', 'SimulationCommand', 'update');

Запустите модель Simulink (обнаружение маршрута)

Чтобы видеть обнаружение маршрута на демонстрационном видео, запустите симуляцию.

sim('main_lanenet', 'timeout', 30);

Очистка

Закройте модель Simulink.

close_system('main_lanenet');