Как можно векторизовать эти несколько циклов в Matlab?

Я пытался найти способ запустить этот скрипт, но обработка занимает много времени, поэтому я решил попытаться «векторизовать» их, но безуспешно.

B = sparse(NxNy,NxNy)

Ny=246;
Nx=190;

for n1y = 1:Ny
 for n1x = 1:Nx;
  n1 = (n1y-1)*Nx+n1x;
  for n2y = 1:Ny
   for n2x = 1:Nx;

       n2 = (n2y-1)*Nx+n2x;
       dx12 = xax(n1x) - xax(n2x);  
       dy12 = xay(n1y) - xay(n2y);
       r12 = sqrt(dx12^2+dy12^2);
       B(n1,n2) = 0.8 * exp((-1/2)*(r12/300));

   end      
  end
 end
end

Я пытался векторизовать n1y, n1x, n2y и 2nx, но, поскольку Matlab работает с векторами, векторы разных размеров не могут быть выполнены (вычислить n1 и n2), поэтому я остановился.

размер (хах) = 190

размер (xay) = 246


person Igor Frassoni    schedule 16.01.2014    source источник
comment
Укажите размеры для xax, xay и B. Вы инициализировали B = нулями (b1, b2) перед циклом?   -  person divanov    schedule 16.01.2014
comment
Извините, забыл, xax (1190) и xay (1246) я инициализировал B функцией sparse(): B = sparse(NxNy,NxNy)   -  person Igor Frassoni    schedule 16.01.2014
comment
Также поставьте точку с запятой после (n2y-1)*Nx+n2x - вывод на консоль значительно замедляет выполнение.   -  person divanov    schedule 16.01.2014
comment
Хорошо, я изменился. Я все еще не разместил его, потому что я тестировал.   -  person Igor Frassoni    schedule 16.01.2014


Ответы (1)


Мне удалось сократить время внутреннего цикла с 0,027 секунды до 0,00046 секунды, просто изменив цикл на матричную операцию.

Кроме того, есть улучшение на 5%, если вычисление расстояния выведено из цикла.

А уменьшение второго внутреннего цикла изменяет их время с 0,11 секунды до 0,0065 секунды.

close all; clear all;

Nx=190;
Ny=246;

xax = unidrnd(10, [1,Nx]);
xay = unidrnd(10, [1,Ny]);
B = sparse(Nx * Ny, Nx * Ny);

dx2 = repmat(xax, length(xax), 1);
dy2 = repmat(xay, length(xay), 1);

dx2 = (dx2 - dx2').^2 / 90000;
dy2 = (dy2 - dy2').^2 / 90000;

n1x = 1:Nx;
n2x = 1:Nx;
for n1y = 1:Ny
  Y1 = (n1y-1)*Nx;
  for n2y = 1:Ny
    tic
    Y2 = (n2y-1)*Nx;
    DY = dy2(n1y, n2y);
    n1 = Y1 + n1x;
    n2 = Y2 + n2x;
    r12 = sqrt(dx2 + DY);
    B(n1,n2) = 0.8 * exp((-1/2)*(r12));
    toc
  end
end
person divanov    schedule 16.01.2014
comment
Это невероятно! Это здорово экономит время. Есть ли у вас другие идеи по сокращению времени выполнения? - person Igor Frassoni; 16.01.2014
comment
Взяв как можно больше за пределы петель. - person divanov; 16.01.2014
comment
Хорошо, спасибо за ваше время, ваши идеи были действительно полезны. - person Igor Frassoni; 16.01.2014
comment
Мне удалось вывести второй цикл, и теперь он в ~1107 раз быстрее по сравнению с исходным алгоритмом. - person divanov; 16.01.2014