Я сделал пару уточнений (в том числе вдохновленный Aero Engy в другом ответе), который привел к некоторым улучшениям.Чтобы проверить их, я создал случайную матрицу из миллиона строк и 100 столбцов для запуска улучшенных функций:
>> x = randn(1000000,100);
Сначала я запустил мой неизмененный код со следующими результатами:
Обратите внимание, что из 40 секунд около 14 из них тратятся на вычисление квантилей - я не могу ожидать, чтобы улучшить эту часть процедуры (я предполагаю, что Mathworks уже оптимизировал ее,хотя я предполагаю, что для предположения получается ...)
Затем я изменил подпрограмму следующим образом, что должно быть быстрее и иметь преимущество в том, что меньше строк!
function [Y q] = levels(X,nLevels)
p = linspace(0, 1.0, nLevels+1);
q = quantile(X,p);
if isvector(q), q = transpose(q); end
Y = ones(size(X));
for i = 2:nLevels
Y = Y + bsxfun(@ge,X,q(i,:));
end
Результаты профилирования с этим кодом:
Так что это на 15 секунд быстрее, что представляет собой 150% -ное ускорение части моего кода, а не MathWorks.
Наконец, следуя совету Андрея (снова в другом ответе), я изменил код, чтобы использовать второй вывод функции histc
, которая назначает записи для корзин.Он не обрабатывает столбцы независимо, поэтому мне пришлось циклически перебирать столбцы, но, похоже, он работает очень хорошо.Вот код:
function [Y q] = levels(X,nLevels)
p = linspace(0,1,nLevels+1);
q = quantile(X,p);
if isvector(q), q = transpose(q); end
q(end,:) = 2 * q(end,:);
Y = zeros(size(X));
for k = 1:size(X,2)
[junk Y(:,k)] = histc(X(:,k),q(:,k));
end
И результаты профилирования:
Теперь мы тратим всего 4,3 секунды в кодах вне функции quantile
, котораяпримерно на 500% быстрее, чем я писал изначально.Я потратил немного времени на написание этого ответа, потому что я думаю, что он превратился в хороший пример того, как вы можете использовать профилировщик MATLAB и StackExchange в комбинации, чтобы получить гораздо лучшую производительность из вашего кода.
Ядоволен этим результатом, хотя, конечно, я продолжу рад слышать другие ответы.На этом этапе основное увеличение производительности произойдет за счет увеличения производительности части кода, которая в данный момент вызывает quantile
.Я не вижу, как это сделать немедленно, но, может быть, кто-то еще здесь может.Еще раз спасибо!