Прежде всего, tr проанализировать это, используя profiler. Профилирование должно ВСЕГДА быть первым шагом при попытке повысить производительность. Мы все можем догадываться о том, что приводит к снижению производительности, но единственный способ быть уверенным и сосредоточиться на правильной части - проверить отчет профилировщика.
Я не запускал профилировщик вашего кода, так как я не хочу генерировать тестовые данные для этого; но у меня есть некоторые идеи о том, какая работа выполняется напрасно. В вашей функции mean(sum(pr<=x))./sum(p<=x)
, вы повторно суммируете более p<=x
. Всего один звонок включает в себя N
сравнения и N-1
суммирования. Итак, для обоих, у вас есть поведение, которое квадратично в N
, когда вычисляются все значения N
значений p
.
Если вы выполните отсортированную версию p
, вам нужно меньше вычислений и сравнений, так как вы можете отслеживать текущую сумму (то есть поведение, которое является линейным в N
). Я предполагаю, что аналогичный метод может быть применен к другой части расчета.
редактировать: Реализация моей идеи, выраженная выше:
function pfdr = fdr(p,pr)
[N, M] = size(pr);
[p, idxP] = sort(p);
[pr] = sort(pr(:));
pfdr = NaN(N,1);
parfor iP = 1:N
x = p(iP);
m = sum(pr<=x)/M;
pfdr(iP) = m/iP;
end
pfdr(idxP) = pfdr;
Если у вас есть доступ к параллельной вычислительной инструментарии, цикл parfor
позволит вам получить некоторое представление. Я использовал две основные идеи: mean(sum(pr<=x))
фактически равен sum(pr(:)<=x)/M
.С другой стороны, поскольку p
сортируется, это позволяет просто взять индекс как количество элементов (в предположении, что каждый элемент уникален, иначе вам придется работать с unique
, чтобы выполнить полный тщательный анализ).
Как вы уже должны хорошо знать, запустив профайлер самостоятельно, линия m = sum(pr<=x)/M;
является основным ресурсом hog. Это можно решить аналогично p
, используя отсортированную природу pr
.
Я проверил свой код (как для идентичных результатов, так и для потребления времени) против вашего. Для N=20e3; M=100
я получаю около 63 секунд для запуска вашего кода и 43 секунды для запуска моего на моем основном компьютере (MATLAB 2011a на 64-битной Arch Linux, 8 GiB RAM, Core i7 860). При меньших значениях M
коэффициент усиления больше. Но этот выигрыш частично объясняется распараллеливанием.
edit2: По-видимому, я пришел к очень похожим результатам, как Андрей, мой результат был бы очень схожим, если бы я придерживался того же подхода.
Однако я понял, что есть некоторые встроенные функции, которые делают больше или меньше того, что вам нужно, то есть очень похоже на определение эмпирической функции кумулятивной плотности. И это можно сделать с помощью построения гистограммы:
function pfdr = fdr(p,pr)
[N, M] = size(pr);
[p, idxP] = sort(p);
count = histc(pr(:), [0; p]);
count = cumsum(count(1:N));
pfdr = count./(1:N).';
pfdr(idxP) = pfdr/M;
Для того же M
и N
, как указано выше, этот код занимает 228 миллисекунд на моем компьютере. Для параметров Андрея требуется 104 миллисекунды, поэтому на моем компьютере это происходит немного медленнее, но я думаю, что этот код гораздо читабельнее, чем запутанный для циклов (как это было в обоих наших примерах).
Прошу прощения за то, что вас задержал срок. Ваш код отличный и самый быстрый среди всех предлагаемых. Лучшим трюком является 'pr (:)'. Не делая этого, у меня болит голова. Разумеется, деление на М в конце. Очень хорошо. Это на самом деле второй пример, когда я обнаружил, что циклы могут быть быстрее, чем векторизованный код. Я собираюсь принять ваш ответ с наградой. Спасибо огромное !!! – yuk
@yuk, последняя часть вашего комментария была совершенно неожиданной :). О щедрости - приятный сюрприз, я был уверен, что вы выберете Эгона. –
После дополнительных тестов я обнаружил ошибку в вашем коде. Похоже, что наибольшее значение 'pr' меньше, чем наибольшее значение' p'. Затем в 'while pr (place) <= x'' place' становится' end + 1', и оператор возвращает индекс из связанной ошибки. Я добавил 'sz = N * M;' перед for-loop, тогда 'while place <= sz && pr (place) <= x'. Код становится немного медленнее, но все же самый быстрый по сравнению с другими. Любое лучшее решение? Пожалуйста, уточните ответ для дальнейших читателей. Благодарю. – yuk