Векторизация для meshgrid в Matlab (или Octave)



Векторизованный код в Matlab работает намного быстрее, чем цикл for (см. параллельные вычисления в Октаве на одной машине-пакет и Пример для конкретных результатов в Октаве)



С учетом сказанного, есть ли способ векторизации кода, показанного далее в Matlab или Octave?



x = -2:0.01:2;
y = -2:0.01:2;
[xx,yy] = meshgrid(x,y);
z = sin(xx.^2-yy.^2);
801   3  

3 ответов:

Как указывает @Jonas, в MATLAB доступно несколько вариантов, и то, что работает лучше всего, зависит от нескольких факторов, таких как:

  • насколько велика ваша проблема
  • сколько машин у вас есть в наличии
  • у вас есть графический процессор
  • делает ли MATLAB уже многопоточные операции

Многие элементарные операции теперь многопоточны в MATLAB - в этом случае, как правило, мало смысла использовать PARFOR (если у вас нет нескольких машин и MATLAB Доступны лицензии серверов распределенных вычислений).

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

Использование GPU может превзойти многопоточную производительность одной машины, если ваша проблема имеет подходящий размер и тип для вычислений на GPU. Векторизованный код, как правило, наиболее естественно подходит для распараллеливания через GPU. Например, вы можете написать свой код, используя gpuArrays из Parallel Computing Toolbox, например и пусть все работает на ГПУ.

x = parallel.gpu.GPUArray.colon(-2,0.01,2);
y = x;
[xx,yy] = meshgrid(x,y); % xx and yy are on the GPU
z = arrayfun( @(u, v) sin(u.*u-v.*v), xx, yy );

Я преобразовал последнюю строку в вызов arrayfun, так как это более эффективно при использовании gpuArrays.

В Matlab единственный способ получить встроенные векторизованные функции для многопоточности-это дождаться, пока MathWorksреализует их как таковые.

В качестве альтернативы можно записать векторизованные вычисления в виде цикла и запустить их параллельно с помощью parfor.

Наконец, ряд функцийс поддержкой GPU , поэтому с доступом к инструменту параллельной обработки вы можете распараллелить эти операции, включая вычитание и поэлементную мощность.

Векторизация для meshgrid и ndgrid

Если вы все еще заинтересованы в поиске векторизованной реализации, чтобы сделать код на основе meshgrid в задаче быстрее, позвольте мне предложить векторизованный метод с bsxfun и его портированной версией GPU. Я твердо убежден, что люди должны рассматривать vectorization with GPUs как перспективный вариант ускорения MATLAB кодов. Коды, которые используют meshgrid или ndgrid и выходы которых должны работать с некоторой элементарной операцией, создают идеальную основу для использования bsxfun в этот код. Кроме того, использование GPU с bsxfun, которое позволяет ему работать над элементами независимо с сотнями и тысячами доступных ядер CUDA, делает его просто идеальным для реализации GPU.

Для вашей конкретной задачи входы были -

x = -2:0.01:2;
y = -2:0.01:2;

Далее, у вас было -

[xx,yy] = meshgrid(x,y);
z = sin(xx.^2-yy.^2);

С bsxfun это становится однострочным -

z = sin(bsxfun(@minus,x.^2,y.^2.'));

Бенчмаркинг

Советы по бенчмаркингу GPU были взяты из Measure and Improve GPU Производительность .

%// Warm up GPU call with insignificant small scalar inputs
temp1 = sin_sqdiff_vect2(0,0);

N_arr = [50 100 200 500 1000 2000 3000]; %// array elements for N (datasize)
timeall = zeros(3,numel(N_arr));

for k = 1:numel(N_arr)
    N = N_arr(k);
    x = linspace(-20,20,N);
    y = linspace(-20,20,N);

    f = @() sin_sqdiff_org(x,y);%// Original CPU code
    timeall(1,k) = timeit(f);
    clear f

    f = @() sin_sqdiff_vect1(x,y);%// Vectorized CPU code
    timeall(2,k) = timeit(f);
    clear f

    f = @() sin_sqdiff_vect2(x,y);%// Vectorized GPU(GTX 750Ti) code
    timeall(3,k) = gputimeit(f);
    clear f
end

%// Display benchmark results
figure,hold on, grid on
plot(N_arr,timeall(1,:),'-b.')
plot(N_arr,timeall(2,:),'-ro')
plot(N_arr,timeall(3,:),'-kx')
legend('Original CPU','Vectorized CPU','Vectorized GPU (GTX 750 Ti)')
xlabel('Datasize (N) ->'),ylabel('Time(sec) ->')

Ассоциированные функции

%// Original code
function z = sin_sqdiff_org(x,y)
[xx,yy] = meshgrid(x,y);
z = sin(xx.^2-yy.^2);
return;

%// Vectorized CPU code
function z = sin_sqdiff_vect1(x,y)
z = sin(bsxfun(@minus,x.^2,y.^2.')); %//'
return;

%// Vectorized GPU code
function z = sin_sqdiff_vect2(x,y)
gx = gpuArray(x);
gy = gpuArray(y);
gz = sin(bsxfun(@minus,gx.^2,gy.^2.')); %//'
z =  gather(gz);
return;

Результаты

Введите описание изображения здесь

Выводы

Как показывают результаты, векторизованный метод с графическим процессором показывает хорошее улучшение производительности, которое составляет около 4.3x против векторизованного кода процессора и 6x против исходного кода. Пожалуйста, имейте в виду, что GPU должен преодолеть минимальные накладные расходы, которые требуются при его настройке, поэтому, по крайней мере, вход приличного размера необходим, чтобы увидеть улучшение. Надеюсь, люди будут исследовать больше vectorization with GPUs, так как это не может быть подчеркнуто достаточно!

Comments

    Ничего не найдено.