Улучшайте Производительность Поэлементного MATLAB® Functions на графическом процессоре с помощью ARRAYFUN

В этом примере показано, как arrayfun может использоваться, чтобы запустить функцию MATLAB® исходно на графическом процессоре. Когда функция MATLAB содержит много поэлементных операций, arrayfun может обеспечить улучшенную производительность когда по сравнению с простым выполнением функции MATLAB непосредственно на графическом процессоре с gpuArray входными данными. Функция MATLAB может быть в ее собственном файле или может быть вложенной или анонимной функцией. Это должно содержать только скалярные операции и арифметику.

Мы помещаем пример в функцию, чтобы позволить вложенные функции:

function paralleldemo_gpu_arrayfun

Использование правила Горнера, чтобы вычислить экспоненциалы

Правило Горнера позволяет эффективную оценку расширений степенного ряда. Мы будем использовать его, чтобы вычислить первые 10 сроков расширения степенного ряда для показательной функции exp. Мы можем реализовать это как функцию MATLAB.

function y = horner(x)
%HORNER - series expansion for exp(x) using Horner's rule
y = 1 + x.*(1 + x.*((1 + x.*((1 + ...
        x.*((1 + x.*((1 + x.*((1 + x.*((1 + ...
        x.*((1 + x./9)./8))./7))./6))./5))./4))./3))./2));
end

Подготовка horner для графического процессора

Чтобы запустить эту функцию на графическом процессоре с минимальными изменениями кода, мы могли передать gpuArray возразите, как введено против horner функция. Начиная с horner содержит только отдельные поэлементные операции, мы не можем понять очень хорошую производительность на графическом процессоре при выполнении каждой операции по одному. Однако мы можем улучшать производительность путем выполнения всех поэлементных операций в horner функционируйте когда-то использование arrayfun.

Запускать эту функцию на графическом процессоре с помощью arrayfun, мы используем указатель на horner функция. horner автоматически адаптируется к различному размеру и входным параметрам типа. Мы можем сравнить результаты, вычисленные на графическом процессоре с помощью обоих gpuArray объекты и arrayfun со стандартным выполнением центрального процессора MATLAB просто путем выполнения функции непосредственно.

hornerFcn = @horner;

Создайте входные данные

Мы создаем некоторые входные параметры различных типов и размеров, и используем gpuArray отправить их в графический процессор.

data1  = rand( 2000, 'single' );
data2  = rand( 1000, 'double' );
gdata1 = gpuArray( data1 );
gdata2 = gpuArray( data2 );

Оцените horner на графическом процессоре

Оценивать horner функция на графическом процессоре, у нас есть два варианта. С минимальными изменениями кода мы можем выполнить исходную функцию на графическом процессоре путем обеспечения gpuArray возразите, как введено. Однако, чтобы улучшать производительность на графическом процессоре вызывают arrayfun, использование того же соглашения о вызовах как исходная функция MATLAB.

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

gresult1 = arrayfun( hornerFcn, gdata1 );
gresult2 = arrayfun( hornerFcn, gdata2 );

comparesingle = max( max( abs( gresult1 - horner( data1 ) ) ) );
comparedouble = max( max( abs( gresult2 - horner( data2 ) ) ) );
fprintf( 'Maximum discrepancy for single precision: %g\n', comparesingle );
fprintf( 'Maximum discrepancy for double precision: %g\n', comparedouble );
Maximum discrepancy for single precision: 2.38419e-07
Maximum discrepancy for double precision: 0

Сравнение производительности между графическим процессором и центральным процессором

Мы можем сравнить производительность версий графического процессора к нативной версии ЦП MATLAB. Графические процессоры текущего поколения имеют намного лучшую производительность в одинарной точности, таким образом, мы сравниваем это.

% CPU execution
tic
hornerFcn( data1 );
tcpu = toc;

% GPU execution using only gpuArray objects
tgpuObject = gputimeit(@() hornerFcn(gdata1));

% GPU execution using gpuArray objects with arrayfun
tgpuArrayfun = gputimeit(@() arrayfun(hornerFcn, gdata1));


fprintf( 'Speed-up achieved using gpuArray objects only: %g\n',...
    tcpu / tgpuObject );
fprintf( 'Speed-up achieved using gpuArray objects with arrayfun: %g\n',...
    tcpu / tgpuArrayfun );
Speed-up achieved using gpuArray objects only: 24.6764
Speed-up achieved using gpuArray objects with arrayfun: 98.3555
end