Интеграция GPU Coder™ в Simulink®

В этом примере показано, как интегрировать GPU Coder™ в Simulink®. GPU Coder не поддержан для блоков Simulink, но можно все еще усилить графические процессоры в Simulink путем генерации динамически подключаемой библиотеки (dll) использование GPU Coder и затем интеграция его в блок Simulink при помощи coder.ExternalDependency API. Обнаружение ребра Sobel используется в качестве примера, чтобы продемонстрировать эту концепцию.

Предпосылки

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

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

  • Simulink, чтобы создать модель в Simulink.

  • Computer Vision Toolbox™, чтобы использовать видео средство чтения и средство просмотра, используемое в примере.

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

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

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

envCfg = coder.gpuEnvConfig('host');
envCfg.BasicCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);

Функция точки входа обнаружения ребра Sobel

Функция sobelEdge.m берет изображение (представленный как одна матрица) и возвращает изображение с обнаруженными ребрами.

type sobelEdge
function [ magnitude ] = sobelEdge( Image )
%#codegen

%   Copyright 2017-2019 The MathWorks, Inc.


maskX = single([-1 0 1 ; -2 0 2; -1 0 1]);
maskY = single([-1 -2 -1 ; 0 0 0 ; 1 2 1]);

coder.gpu.kernelfun();



resX = conv2(Image, maskX, 'same');
resY = conv2(Image, maskY, 'same');

magnitude = sqrt(resX.^2 + resY.^2);
thresh = magnitude < 0.4;
magnitude(thresh) = 0;

end

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

Чтобы запустить эту функцию на графическом процессоре от Simulink, сгенерируйте разделяемую библиотеку при помощи GPU Coder. Вызовите сгенерированный код (библиотека) от Simulink при помощи coder.ExternalDependency API. Скопируйте сгенерированную библиотеку в папку верхнего уровня.

Isize = single(zeros(240, 320));
cfg = coder.gpuConfig('dll');
codegen -args {Isize} -config cfg sobelEdge
if ispc
    copyfile(fullfile(pwd, 'codegen','dll', 'sobelEdge','sobelEdge.dll'), pwd);
else
    copyfile(fullfile(pwd, 'codegen','dll', 'sobelEdge','sobelEdge.so'), pwd);
end

Прежде, чем сгенерировать код CUDA, сначала протестируйте MEX-функцию в MATLAB®, чтобы гарантировать, что это функционально эквивалентно оригинальному коду MATLAB и что никакие ошибки времени выполнения не происходят.

Задайте кодер. ExternalDependency API, чтобы Вызвать Generated Code

SobelAPI.m является классом, который задает API, чтобы вызвать сгенерированную динамическую библиотеку. Большая часть этой функции является стандартным шаблоном. Метод интереса является SobelAPI.sobelEdge, который называется, чтобы выполнить динамическую библиотеку. Эта функция вызывает sobelEdge динамическую библиотеку через coder.ceval вызвать.

type SobelAPI

%   Copyright 2017-2019 The MathWorks, Inc.

classdef SobelAPI < coder.ExternalDependency
    %#codegen
    
    methods (Static)
        
        function bName = getDescriptiveName(~)
            bName = 'SobelAPI';
        end
        
        function tf = isSupportedContext(ctx)
            if  ctx.isMatlabHostTarget()
                tf = true;
            else
                error('Sobel library not available for this target');
            end
        end
        
        function updateBuildInfo(buildInfo, ctx)
            [~, linkLibExt, execLibExt, ~] = ctx.getStdLibInfo();
            
            % Header files.
            hdrFilePath = fullfile(pwd, 'codegen', 'dll', 'sobelEdge');
            buildInfo.addIncludePaths(hdrFilePath);
            
            % Link files.
            linkFiles = strcat('sobelEdge', linkLibExt);
            linkPath = hdrFilePath;
            linkPriority = '';
            linkPrecompiled = true;
            linkLinkOnly = true;
            group = '';
            buildInfo.addLinkObjects(linkFiles, linkPath, ...
                linkPriority, linkPrecompiled, linkLinkOnly, group);
            
            % Non-build files.
            nbFiles = 'sobelEdge';
            nbFiles = strcat(nbFiles, execLibExt);
            buildInfo.addNonBuildFiles(nbFiles,'','');
        end
        
        %API for library function 'sobelEdge'.
        function c = sobelEdge(I)
            % Running in generated code, call library function.
            coder.cinclude('sobelEdge.h');
            
            c = coder.nullcopy(I);
            coder.ceval('sobelEdge', coder.rref(I), coder.wref(c));
        end
    end
end

Создайте модель Simulink, которая интегрирует API к DLL

В Simulink создайте блок MATLAB function, который вызывает SobelAPI.sobelEdge. Этот шаг эквивалентен подписанию сгенерированного кода DLL GPU Coder. Когда блок MATLAB function выполняется, эта динамическая библиотека работает на графическом процессоре вашей хост-машины. И так же для генерации кода от Simulink, код CUDA вызывается. Модель Simulink использует видео средство чтения и видеодисплей, чтобы показать эффект алгоритма.

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

Запустите модель Simulink (фильтр Sobel)

Запустите симуляцию, чтобы видеть эффект алгоритма Sobel.

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