Этот пример показывает, как интегрировать код CUDA®, сгенерированный для нейронной сети для глубокого обучения в Simulink®. В то время как GPU Coder™ не поддержан для блоков Simulink, можно все еще использовать вычислительную мощность графических процессоров в Simulink путем генерации динамически подключаемой библиотеки (dll) с GPU Coder и затем интеграции его в Simulink как Блок s-function при помощи Legacy Code Tool. Обнаружение маршрута с GPU Coder используется в качестве примера, чтобы продемонстрировать эту концепцию. Исходный пример использовал файл C++ с функциями OpenCV, чтобы считать кадры, чертить маршруты и наложить информацию о частоте кадров о видеовыходе. Однако этот пример использует блоки Simulink от Computer Vision Toolbox™, чтобы выполнить те же операции.
CUDA включил NVIDIA®, графический процессор с вычисляет возможность 3.2 или выше.
NVIDIA инструментарий CUDA и драйвер.
Библиотека NVIDIA cuDNN (v7).
Переменные окружения для компиляторов и библиотек. Для получения информации о поддерживаемых версиях компиляторов и библиотек, смотрите Сторонние продукты. Для подготовки переменных окружения смотрите Переменные окружения.
Simulink для создания модели.
Computer Vision Toolbox™ для видео средства чтения, средства просмотра и функциональности маркировки маршрута используется в примере.
Deep Learning Toolbox™ для использования объекта SeriesNetwork.
Следующая строка кода создает папку в вашей текущей рабочей папке (pwd) и копирует все соответствующие файлы в эту папку. Если вы не хотите выполнять эту операцию или если вы не можете сгенерировать файлы в этой папке, изменить вашу текущую рабочую папку.
gpucoderdemo_setup('gpucoderdemo_lane_detection_simulink');
Используйте coder.checkGpuInstall, функционируют и проверяют, что компиляторы и библиотеки, необходимые для выполнения этого примера, настраиваются правильно.
envCfg = coder.gpuEnvConfig('host'); envCfg.DeepLibTarget = 'cudnn'; envCfg.DeepCodegen = 1; envCfg.Quiet = 1; coder.checkGpuInstall(envCfg);
Следующая схема иллюстрирует общую процедуру для использования Legacy Code Tool
, чтобы интегрировать код CUDA, сгенерированный для нейронной сети для глубокого обучения в Simulink.
[laneNet, coeffMeans, coeffStds] = getLaneDetectionNetwork();
Архитектура предварительно обученного SeriesNetwork
подобна AlexNet
, за исключением того, что последние несколько слоев заменяются меньшим полносвязным слоем и регрессией выходной слой. Эта сеть берет вход изображений и выходные параметры два контура маршрута, которые соответствуют левым и правым маршрутам автомобиля, оборудованного датчиком. Каждый контур маршрута может быть представлен параболическим уравнением. Здесь, боковое смещение и продольное расстояние от автомобиля. Сетевые выходные параметры эти три параметра и описание параболического уравнения для левых и правых контуров маршрута.
Этот пример использует ту же detect_lane.m функцию точки входа в качестве исходного примера. Функция detect_lane
вычисляет и координаты, соответствующие положениям маршрута от, и параметры. Функция detect_lane
также выполняет вычисления, которые сопоставляют и координаты, чтобы отобразить координаты.
Переменные coeffStds
и coeffMeans
содержат среднее значение и значения станд. от обучившего сеть. Эти значения требуются во время симуляции. Чтобы запустить функцию detect_lane
на графическом процессоре от Simulink, сгенерируйте разделяемую библиотеку при помощи GPU Coder. Входные параметры к функции detect_lane
являются кадром видео, средним значением и значениями станд. Переданное использование значений опции -args
отражает размер этих входных параметров. Скопируйте сгенерированную библиотеку в папку верхнего уровня.
coeffStds = [0.002995595096857,0.076600147330248,0.631288082601997,0.002600128777275,0.073641936476251,0.984567040148445]; coeffMeans = [-1.939450143265110e-04,1.557727430093527e-04,1.473991581706893,-1.909623131136531e-04,0.004474616468621,-1.378729416735388]; 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').
Предупреждение выдано относительно необъединенного доступа к переменной входных данных. Это вызвано тем, что команда codegen
генерирует главный столбцом код. В целях этого примера может быть проигнорировано это предупреждение.
Пример обнаружения маршрута зависит от времени выполнения 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'); libs = {'detect_lane.so','libcudart.so','libcublas.so','libcudnn.so'}; end headerPath = {srcPath;cudnnIncPath;cudaIncPath}; libPath = {srcPath;cudnnLibPath;cudaLibPath}; % 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/devel/sbs/37/vravicha.lcmFirst/matlab/toolbox/gpucoder/gpucoderdemos/gpucoderdemo_lane_detection_simulink2/codegen/dll/detect_lane', '-I/mathworks/hub/3rdparty/R2019a/3840803/glnxa64/cuDNN/cuda/include', '-I/usr/local/cuda/include', '-I/mathworks/devel/sbs/37/vravicha.lcmFirst/matlab/toolbox/gpucoder/gpucoderdemos/gpucoderdemo_lane_detection_simulink2', '/mathworks/devel/sbs/37/vravicha.lcmFirst/matlab/toolbox/gpucoder/gpucoderdemos/gpucoderdemo_lane_detection_simulink2/codegen/dll/detect_lane/detect_lane.so', '/usr/local/cuda/lib64/libcudart.so', '/usr/local/cuda/lib64/libcublas.so', '/mathworks/hub/3rdparty/R2019a/3840803/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);
Весь пред - и операции последующей обработки, сделанные в файле main_lanenet.cpp
исходного примера, должен быть перемещен в Simulink. Входная подсистема Обработки видеоданных удаляет нормализацию, выполняемую мультимедийным блоком читателя, и изменяет размер входного кадра видео к входному размеру слоя сети обнаружения маршрута, 227x227x3
. Это затем преобразовывает 3D кадр видео в одномерный вектор, требуемый библиотекой detect_lane
. Включенная подсистема Точек Маршрута выполняет обработку левых и правых точек маршрута, чтобы сделать его подходящим для блока Draw Lanes. Модель Simulink использует видеодисплей, чтобы показать обнаружение маршрута на демонстрационном видео.
open_system('main_lanenet'); set_param('main_lanenet', 'SimulationCommand', 'update');
Запустите симуляцию, чтобы видеть обнаружение маршрута на демонстрационном видео.
sim('main_lanenet', 'timeout', 30);
Очистите ресурсы памяти, удалите файлы и возвратитесь к исходной папке.
close_system('main_lanenet'); clear mex cleanup