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

Предпосылки

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

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

  • Переменные окружения для компиляторов и библиотек. Для получения дополнительной информации смотрите Переменные окружения.

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

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

Создайте новую папку и скопируйте соответствующие файлы

Следующая строка кода создает папку в вашей текущей рабочей папке (pwd) и копирует все соответствующие файлы в эту папку. Если вы не хотите выполнять эту операцию или если вы не можете сгенерировать файлы в этой папке, изменить вашу текущую рабочую папку.

gpucoderdemo_setup('gpucoderdemo_in_simulink');

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

Используйте 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 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

Сгенерируйте DLL для функции

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

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

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

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

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

type SobelAPI

%   Copyright 2017 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

% LocalWords:  sobel

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

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

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

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

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

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

Очистка

Удалите файлы и возвратитесь к исходной папке

Команда выполнения: Очистка

close_system('gpucoder_sobelEdge');
cleanup