Векторизация для 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);
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