Этот пример демонстрирует, как создать автономный исполняемый файл CUDA®, который усиливает библиотеку CUDA Solver (cuSOLVER). Пример использует приложение аппроксимирования кривыми, которое подражает автоматическому отслеживанию маршрута на дороге, чтобы проиллюстрировать несколько тем, включая:
Подбор кривой полиному произвольного порядка к зашумленным данным с помощью матричной QR-факторизации.
Используя кодер. Класс LAPACKCallback, чтобы предоставить информацию о библиотеке LAPACK для генератора кода при генерации независимых исполняемых файлов.
CUDA включил NVIDIA®, графический процессор с вычисляет возможность 3.2 или выше.
NVIDIA инструментарий CUDA.
Библиотека LAPACK, которая оптимизирована для вашей среды выполнения. Для получения дополнительной информации см. реализации поставщиков LAPACK.
Переменные окружения для компиляторов и библиотек. Для получения информации о поддерживаемых версиях компиляторов и библиотек, смотрите Сторонние продукты. Для подготовки переменных окружения смотрите Переменные окружения.
Следующая строка кода создает папку в вашей текущей рабочей папке (pwd) и копирует все соответствующие файлы в эту папку. Если вы не хотите выполнять эту операцию или если вы не можете сгенерировать файлы в этой папке, изменить вашу текущую рабочую папку.
gpucoderdemo_setup('gpucoderdemo_qr_decomposition');
Используйте coder.checkGpuInstall, функционируют и проверяют, что компиляторы и библиотеки, необходимые для выполнения этого примера, настраиваются правильно.
envCfg = coder.gpuEnvConfig('host');
envCfg.BasicCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);
В приложениях аппроксимирования кривыми цель состоит в том, чтобы оценить коэффициенты полинома младшего разряда. Полином затем используется в качестве модели для наблюдаемых зашумленных данных, которые в этом примере представляют контур маршрута дороги перед транспортным средством. Например, если квадратичный полином должен использоваться, существует три коэффициента (a, b и c), чтобы оценить:
Полином, который подходит лучше всего, задан как тот, который минимизирует сумму квадратичных невязок между собой и зашумленными данными. Для того, чтобы решить эту задачу наименьших квадратов, сверхрешительная линейная система получена и решена. Явная обратная матрица на самом деле не требуется, чтобы решать систему.
В этом примере неизвестные являются коэффициентами каждого термина в полиноме. Поскольку полином, который мы будем использовать в качестве модели всегда, начинает с нашего текущего положения на дороге, постоянный термин в полиноме принят, чтобы быть нулем, и мы должны только оценить коэффициенты для линейных и условий высшего порядка. Мы настроим матричное уравнение Ax=y, таким образом что
y содержит датчик выходные параметры.
x содержит полиномиальные коэффициенты, которые мы должны получить.
A является постоянной матрицей, связанной с порядком полинома и местоположениями датчиков.
Мы решим уравнение с помощью QR-факторизации можно следующим образом:
и
где pinv () представляет псевдоинверсию. Учитывая матрицу А, следующий код может использоваться, чтобы реализовать решение этого матричного уравнения. Факторинг A позволяет для более легкого решения системы.
[Q, R] = 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] = 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
Матрица А Вандермонда может быть сформирована с помощью следующего кода:
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
Матрица А Вандермонда и датчик выходная матрица 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®.
Для автономных целей необходимо задать пользовательский кодер. Класс LAPACKCallback, который задает LAPACK и cuSOLVER библиотеки наряду с заголовочными файлами, чтобы использовать для вызовов линейной алгебры в сгенерированном коде. В этом примере 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 CUDA libraries if ispc cudaPath = getenv('CUDA_PATH'); libPath = 'lib\x64'; libName = ['cusolver' libExt]; else [~,cudaPath] = system('which nvcc'); cudaPath = fileparts(cudaPath); while (cudaPath(end)=='/') cudaPath = cudaPath(1:end-1); end lastIdx = find(cudaPath=='/',1,'last'); cudaPath = cudaPath(1:(lastIdx-1)); libPath = 'lib64'; libName = ['libcusolver' libExt]; end % Add include path and cusolver library for linking buildInfo.addIncludePaths(fullfile(cudaPath,'include')); libPath = fullfile(cudaPath, libPath); addLinkObjects(buildInfo, libName, libPath, '', true, true); % Specify path to LAPACK library if ispc lapackLocation = fullfile('C:','win64','LAPACK'); libName = ['liblapacke' libExt]; buildInfo.addIncludePaths(fullfile(lapackLocation,'include')); libPath = fullfile(lapackLocation, 'lib'); else lapackLocation = fullfile(filesep,'usr','lib','lapack'); libName = ['liblapack' libExt]; buildInfo.addIncludePaths(fullfile('usr','include')); libPath = fullfile(lapackLocation); end % Add include path and LAPACK library for linking addLinkObjects(buildInfo, 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, и функция построения графика используется, чтобы визуализировать данные о датчике и кривую по экспериментальным точкам.
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 vehicle'); legend('Sensor data','Curve fit'); title('Estimate of lane boundary looking ahead of vehicle');
Удалите сгенерированные файлы и возвратитесь к исходной папке.
cleanup