exponenta event banner

QR-декомпозиция на NVIDIA GPU с использованием библиотек cuSOLVER

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

  • Подгонка полинома произвольного порядка к шумным данным с помощью факторизации QR матрицы.

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

Предпосылки

Проверка среды графического процессора

Чтобы убедиться, что компиляторы и библиотеки, необходимые для выполнения этого примера, настроены правильно, используйте 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;

Используйте функцию linsolureQR для решения уравнения с помощью 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');

См. также

Функции

Объекты

Связанные темы