Я создаю свою первую крупномасштабную программу MATLAB, и мне удалось написать оригинальный векторный код для всего, пока я не попытался создать изображение, представляющее плотность вектора в стереографической проекции. После пары неудачных попыток я пошел на сайт обмена файлами Mathworks и нашел программу с открытым исходным кодом, которая соответствует моим потребностям Malcolm Mclean. С тестовой матрицей его функция производит что-то вроде этого:
И хотя это почти то, что я хотел, его код основывается на тройном вложенном for-loop. На моей рабочей станции тестовая матрица данных размером 25000x2 заняла 65 секунд в этом разделе кода. Это неприемлемо, так как я буду масштабироваться до матриц данных размером 500000x2 в моем проекте.
До сих пор я мог векторизовать самый внутренний цикл (который был самым длинным/худшим), но я хотел бы продолжить и полностью избавиться от циклов, если это возможно. Вот оригинальный код Malcolm, который мне нужно оцифровать:
dmap = zeros(height, width); % height, width: scalar with default value = 32
for ii = 0: height - 1 % 32 iterations of this loop
yi = limits(3) + ii * deltay + deltay/2; % limits(3) & deltay: scalars
for jj = 0 : width - 1 % 32 iterations of this loop
xi = limits(1) + jj * deltax + deltax/2; % limits(1) & deltax: scalars
dd = 0;
for kk = 1: length(x) % up to 500,000 iterations in this loop
dist2 = (x(kk) - xi)^2 + (y(kk) - yi)^2;
dd = dd + 1 / ( dist2 + fudge); % fudge is a scalar
end
dmap(ii+1,jj+1) = dd;
end
end
И вот это касается изменений, которые я уже внес в самый внутренний цикл (который был самым большим утечкой эффективности). Это сокращает время с 65 секунд до 12 секунд на моей машине для той же тестовой матрицы, которая лучше, но все же намного медленнее, чем хотелось бы.
dmap = zeros(height, width);
for ii = 0: height - 1
yi = limits(3) + ii * deltay + deltay/2;
for jj = 0 : width - 1
xi = limits(1) + jj * deltax + deltax/2;
dist2 = (x - xi) .^ 2 + (y - yi) .^ 2;
dmap(ii + 1, jj + 1) = sum(1 ./ (dist2 + fudge));
end
end
So my main question, are there any further changes I can make to optimize this code? Or even an alternative method to approach the problem? I've considered using C++ or F# instead of MATLAB for this section of the program, and I may do so if I cannot get to a reasonable efficiency level with the MATLAB code.
Также обратите внимание, что на данный момент у меня нет ЛЮБЫХ дополнительных панелей инструментов, если бы я это сделал, тогда я знаю, что это было бы тривиально (например, используя hist3 из инструментария статистики).