Ответ 1
Я запускал оба примера на машине с 24 ГБ ОЗУ с profile('-memory','on');
. Эта опция профилировщика отображает выделенную и освобожденную память в каждой строке кода. Предполагается, что это не брутто, а чистые суммы. Я проверил с простой функцией, которая имеет net 0 бесплатно и alloc, и она сообщила о брутто-суммах. Однако представляется вероятным, что встроенные команды без кода .m для их резервного копирования не предоставляют мелкозернистую отчетность памяти профилировщику.
Я провел пару тестов для следующего кода:
% truncTest.m
N = 628000000;
M = 364000000;
clear Z
Z = zeros(N,1,'single');
Z(M:end) = [];
Z(1) % just because
clear Z
Z = zeros(N,1,'single');
Z = Z(1:M);
Z(1)
Для того, что они стоят, результаты профилирования памяти для этих N
и M
:
Ну, обе линии выглядят одинаково с точки зрения выделенной и освобожденной памяти. Может быть, это не вся правда.
Итак, из любопытства я уменьшил M
до 200
(всего 200!) без изменения N
, сделал profile clear
и повторил. Профилирование:
Интересно, что Z=Z(1:M);
сейчас практически мгновенно, а Z(M:end)=[];
- немного быстрее. Оба освобождают около 2,4 ГБ памяти, как и ожидалось.
Наконец, если мы идем в другом направлении и установите M=600000000;
:
Теперь даже Z=Z(1:M);
работает медленно, но примерно дважды с точностью Z(M:end)=[];
.
Это говорит о том, что
-
Z=Z(1:M);
просто захватывает указанные элементы, сохраняет их в новом буфере или временной переменной, освобождает старый буфер и назначает новый/временный массивZ
. Я смог сделать мою более слабую машину размером 4 ГБ с 2,45 секунды до того, чтобы пробить файл страницы в течение 5 минут, просто увеличивM
и оставивN
один. Определенно предпочитайте этот вариант для небольшогоM/N
, возможно, во всех случаях. -
Z(M:end)=[];
всегда перезаписывает буфер, а время выполнения увеличивается с помощьюM
. На самом деле всегда медленнее и, кажется, увеличивается экспоненциально, в отличие отZ=Z(1:M);
. - Профилирование памяти не дает мелкой информации об этих встроенных операциях и не должно быть неверно истолковано как предоставление полной памяти, освобожденной и распределенной по исполнению команд, а скорее изменение сети.
ОБНОВЛЕНИЕ 1. Просто для удовольствия я приурочил тесты к диапазону значений M
:
Очевидно, более информативный, чем профилирование. Оба метода не являются no-ops, но Z=Z(1:M);
является самым быстрым, но он может использовать почти вдвое больше памяти Z
для M/N
около 1.
ОБНОВЛЕНИЕ 2:
Относительно неизвестный feature
, называемый mtic
(и mtoc
), был доступен в 32-битной Windows до R2008b. Я все еще устанавливаю его на одной машине, поэтому я решил посмотреть, дает ли это более глубокое понимание, понимая, что (а) многое изменилось с тех пор и (б) это совершенно другой менеджер памяти, используемый в 32-битном MATLAB. Тем не менее, я уменьшил размер теста до N=128000000; M=101000000;
и посмотрел. Во-первых, feature mtic
для Z=Z(1:M-1);
>> tic; feature mtic; Z=Z(1:M-1); feature mtoc, toc
ans =
TotalAllocated: 808011592
TotalFreed: 916009628
LargestAllocated: 403999996
NumAllocs: 86
NumFrees: 77
Peak: 808002024
Elapsed time is 0.951283 seconds.
Очистка, воссоздание Z
, другим способом:
>> tic; feature mtic; Z(M:end) = []; feature mtoc, toc
ans =
TotalAllocated: 1428019588
TotalFreed: 1536018372
LargestAllocated: 512000000
NumAllocs: 164
NumFrees: 157
Peak: 1320001404
Elapsed time is 4.533953 seconds.
В каждой метрике (TotalAllocated
, TotalFreed
, NumAllocs
и т.д.), Z(M:end) = [];
менее эффективен, чем Z=Z(1:M-1);
. Я ожидаю, что можно узнать, что происходит в памяти, исследуя эти числа для этих значений N
и M
, но мы будем гадать о старом MATLAB