Разложение QR на NVIDIA графический процессор Используя cuSOLVER Библиотеки

В этом примере показано, как создать автономный исполняемый файл CUDA®, который усиливает библиотеку CUDA Solver (cuSOLVER). Пример использует приложение аппроксимирования кривыми, которое подражает автоматическому отслеживанию маршрута на дороге, чтобы проиллюстрировать:

  • Подбор кривой полиному произвольного порядка к зашумленным данным при помощи матричной QR-факторизации.

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

Предпосылки

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

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

  • Библиотека LAPACK, которая оптимизирована для вашей среды выполнения. Для получения дополнительной информации см. реализации поставщиков LAPACK. Этот пример использует mwlapack библиотеки, которые MATLAB® обеспечивает в matlabroot/extern/lib.

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

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

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

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

Решите линейную систему при помощи матричной факторизации

В приложениях аппроксимирования кривыми цель состоит в том, чтобы оценить коэффициенты полинома младшего разряда. Полином затем используется в качестве модели для наблюдаемых зашумленных данных, которые в этом примере представляют контур маршрута дороги перед транспортным средством. Например, при использовании квадратичного полинома, существует три коэффициента ($a$$b$и$c$), чтобы оценить:

$$ax^2 + bx + c$$

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

В этом примере неизвестные являются коэффициентами каждого термина в полиноме. Поскольку полином, который вы используете в качестве модели всегда, начинает с текущего положения на дороге, постоянный термин в полиноме принят, чтобы быть нулем. Оцените коэффициенты для линейных и условий высшего порядка. Настройте матричное уравнение Ax=y, таким образом что:

  • $y$ содержит датчик выходные параметры.

  • $x$ содержит полиномиальные коэффициенты, которые мы должны получить.

  • $A$ постоянная матрица, связанная с порядком полинома и местоположениями датчиков.

Решите уравнение с помощью QR-факторизации$A$:

$$Ax = QRx=y$$

и

$$x = pinv(A) * y = R^{-1}Q^T*y$$

где pinv () представляет псевдоинверсию. Учитывая матрицу$A$, можно использовать следующий код, чтобы реализовать решение этого матричного уравнения. Факторинг$A$ допускает более легкое решение системы.

[Q,R,P] = qr(A);
z = Q' * y;
x = R \ z;
yhat = A * x;

Используйте функцию linsolveQR, чтобы решить уравнение с помощью QR-факторизации$A$.

type linsolveQR.m
function [yhat,x] = linsolveQR(A,y)
%#codegen

%   Copyright 2019 The MathWorks, Inc.

[Q,R,P] = qr(A);
z = Q' * y;
x = R \ z;
yhat = A * x;

end

Модель сигнала для дороги

Чтобы протестировать алгоритм, постоянно изгибающаяся дорожная модель используется, то есть, синусоида, которая загрязнена аддитивным шумом. Путем варьирования частоты синусоиды в модели можно подчеркнуть алгоритм различными суммами. Этот код симулирует шумный датчик выходные параметры с помощью нашей дорожной модели:

Duration = 2;                                                       % Distance that we look ahead
N = 25;                                                             % Total number of sensors providing estimates of road boundary
Ts = Duration / N;                                                  % Sample interval
FracPeriod = 0.5;                                                   % Fraction of period of sinusoid to match
y = sin(2*pi* (0:N-1)' * (FracPeriod/N)) + sqrt(0.3) * randn(N,1);  % y will contain the simulated sensor outputs

Используйте этот код, чтобы сформировать матрицу Вандермонда$A$:

Npoly = 3;                  % Order of polynomial to use in fitting
v = (0:Ts:((N-1)*Ts))';
A = zeros(length(v), Npoly);
for i = Npoly : -1 : 1
    A(:,i) = v.^i;
end

Матрица Вандермонда$A$ и датчик выходная матрица$y$ передаются как входные параметры linsolveQR функция точки входа. Эти входные параметры записаны в разделенные от запятой файлы и читаются из рукописного основного qrmain.cu.

 writematrix(reshape(A, 1, 75), 'inputA.csv');
 writematrix(reshape(y, 1, 25), 'inputY.csv');

Пользовательский класс коллбэка для автономной генерации кода

qr функция только частично поддерживается в cuSOLVER библиотека. В таких случаях GPU Coder™ использует LAPACK библиотека для определенных вызовов функции линейной алгебры. LAPACK внешняя библиотека программного обеспечения в числовой линейной алгебре. Для целей MEX генератор кода использует LAPACK библиотека включена в MATLAB.

Для автономных целей необходимо задать пользовательский coder.LAPACKCallback класс, который задает библиотеки LAPACK наряду с заголовочными файлами, чтобы использовать в вызовах линейной алгебры в сгенерированном коде. В этом примере lapackCallback класс коллбэка задает пути к этим библиотекам в updateBuildInfo метод. Необходимо изменить этот файл с именами библиотеки и путями для пользовательской установки LAPACK на компьютере.

type lapackCallback.m

classdef lapackCallback < coder.LAPACKCallback
%

%   Copyright 2019 The MathWorks, Inc.

    methods (Static)
        function hn = getHeaderFilename()
            hn = 'lapacke.h';
        end

        function updateBuildInfo(buildInfo, buildctx)
            [~, libExt] = buildctx.getStdLibInfo();          
          
            % Specify path to LAPACK library
            if ispc
                lapackLocation = [matlabroot,'\extern'];
                libName = ['libmwlapack' libExt];
                buildInfo.addIncludePaths([lapackLocation,'\include']);            
                libPath = [lapackLocation,'\lib\win64\microsoft\'];
            else
                lapackLocation = [matlabroot];
                libName = ['libmwlapack' libExt];
                buildInfo.addIncludePaths([lapackLocation,'/extern/include']);            
                libPath = [lapackLocation,'/bin/glnxa64'];
            end
            
            % Add include path and LAPACK library for linking
            buildInfo.addLinkObjects(libName, libPath, 1000, true, true);

            buildInfo.addDefines('HAVE_LAPACK_CONFIG_H');
            buildInfo.addDefines('LAPACK_COMPLEX_STRUCTURE');
        end
    end
end

Автономная генерация кода

Сгенерируйте независимый исполняемый файл определением CustomLAPACKCallback свойство в объекте настройки кода и использовании рукописного основного qrmain.cu.

cfg = coder.gpuConfig('exe');
cfg.GpuConfig.EnableCUSOLVER = 1;
cfg.CustomLAPACKCallback = 'lapackCallback';
cfg.CustomSource = 'qrmain.cu';
cfg.CustomInclude = '.';
codegen -config cfg -args {A,y} linsolveQR -report
Code generation successful: To view the report, open('codegen/exe/linsolveQR/html/report.mldatx').

Автономное выполнение кода

Когда вы выполняете сгенерированный независимый исполняемый файл, выходные параметры$yhat$ и$x$ вычислены и записаны в разделенные от запятой файлы. Считайте эти выходные параметры назад в MATLAB и используйте plot функция, чтобы визуализировать данные о датчике и кривую по экспериментальным точкам.

if ispc
    system('linsolveQR.exe');
else
    system('./linsolveQR');
end
yhat = reshape(readmatrix('outputYhat.csv'), 25, 1);
x = reshape(readmatrix('outputX.csv'), 3, 1);
figure
plot(v, y, 'k.', v, yhat, 'r')
axis([0 N*Ts -3 3]);
grid;
xlabel('Distance Ahead of the Vehicle');
legend('Sensor data','Curve fit');
title('Estimate the Lane Boundary Ahead of the Vehicle');