Назначая матрицу в гораздо большую выделенную память, Matlab каким-то образом будет дублировать ее при «копировании», и если копируемая матрица будет достаточно большой, произойдет переполнение памяти. Это пример кода:
main_mat=zeros(500,500,2000);
n=500;
slice_matrix=zeros(500,500,n);
for k=1:4
parfor i=1:n
slice_matrix(:,:,i)=gather(gpuArray(rand(500,500)));
end
main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)=slice_matrix; %This is where the memory will likely overflow
end
Любой способ просто "разбить" slice_matrix
на main_mat
без накладных расходов? Заранее спасибо.
РЕДАКТИРОВАТЬ:
Переполнение произошло, когда main_mat
выделено заранее. Если main_mat
инициализируется с main_mat=zeros(500,500,1);
(меньший размер), переполнение не произойдет, но оно будет замедлено, так как распределение не будет выполнено до того, как в него будет назначена матрица. Это значительно снизит производительность по мере увеличения диапазона k
.
matlab
optimization
Грегор Исак
источник
источник
parfor
цикл . Кроме того,parfor
копирует ваши данные каждому отдельному работнику, таким образом, предполагая, что 4 работника дублируют ваши данные четыре раза в оперативной памяти.memory
функцию? Задача-менеджер? Ошибка памяти от Matlab? По какой строке кода это происходит?main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)
где возникает проблема переполнения памяти. Это проверено, когда я выделилmain_mat
заранее, это переполнится, если я не сделаю, это не будет. Matlab вернет сообщение об ошибке «Недостаточно памяти».h=h+slice_matrix(end)
передmain_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)=slice_matrix;
(и инициализировать h с 0)? Я подозреваю, что эта добавленная строка уже вызовет проблемы с памятью.Ответы:
Основная проблема заключается в том, что числа занимают больше места, чем нули.
main_mat=zeros(500,500,2000);
занимает мало ОЗУ, аmain_mat = rand(500,500,2000);
занимает много, независимо от того, используете ли вы графический процессор или парфор (фактически, парфор заставит вас использовать больше оперативной памяти). Так что это не противоестественный отек памяти. Следуя приведенной ниже ссылке Даниила, кажется, что присвоение нулей только создает указатели на память, а физическая память заполняется только при использовании матрицы для «чисел». Это управляется операционной системой. И это ожидается для Windows, Mac и Linux, либо вы делаете это с Matlab или другими языками, такими как C.источник
zeros
целой виртуальной памятью, она фактически выделяется, но память не используется.whos
показывает одинаковый размер для обеих матриц, в то время как моя ОС показывает разное потребление памяти. Я удалил свой комментарий, потому что ваш ответ определенно не ошибся.ones
вместо этогоzeros
, это гарантирует, что память фактически выделяется во время вызова соответствующей функции.main_mat
назначены ненулевые значения Ранее была назначена только виртуальная память (адресное пространство), теперь она назначена физической памяти.Удаление
parfor
, скорее всего, решит вашу проблему.parfor
там не полезно. MATLABparfor
не использует параллелизм разделяемой памяти (т.е. он не запускает новые потоки), а скорее параллелизм распределенной памяти (он запускает новые процессы). Он предназначен для распределения работы по множеству или рабочим узлам. И хотя он также работает в пределах одного узла (или одного настольного компьютера) для распределения работы по нескольким ядрам, он не является оптимальным способом параллелизма внутри одного узла.Это означает, что каждый из процессов, запускаемых пользователем,
parfor
должен иметь свою собственную копиюslice_matrix
, которая является причиной большого объема памяти, используемой вашей программой.См. «Решите, когда использовать
parfor
» в документации MATLAB, чтобы узнать больше о том,parfor
и когда использовать.источник
parfor
является единственным способом ? Обработка работает лучше всего, когда я спроектировал ее таким образом, поскольку все внутриparfor
интенсивно использует процессор и графический процессор, что значительно улучшило производительность.parfor
. Если так, то да, это, вероятно, полезно. - Может быть, еслиslice_matrix
это не так,gpuarray
он не будет скопирован в задании.slice_matrix
это не такgpuArray
, я все еще получаю симптом переполнения. Я оставлю этот вопрос открытым, посмотрим, есть ли альтернативное решение. Спасибо за ответ, хотя!Я предполагаю, что ваш код - это просто пример кода, который
rand()
представляет собой обычай в вашем MVE. Итак, есть несколько советов и приемов для использования памяти в Matlab.Вот фрагмент учебного пособия The MathWorks:
Первое, что нужно сделать, это проверить эффективность памяти (кода) вашего кода. Даже код превосходных программистов может быть дополнительно оптимизирован с помощью (немного) умственных способностей. Вот несколько советов относительно эффективности памяти
sum(X,2)
,mean(X,2)
,std(X,[],2)
bsxfun
x = 2*x+3
вместоx = 2*x+3
Имейте в виду, что оптимальное использование памяти не такое, как если бы вы хотели сократить время вычислений. Поэтому вы можете рассмотреть возможность сокращения числа работников или воздержаться от использования
parfor
-loop. (Посколькуparfor
нельзя использовать общую память, нет функции копирования при записи с использованием Parallel Toolbox.Если вы хотите поближе взглянуть на свою память , на то, что доступно и что может использовать Matlab, ознакомьтесь
feature('memstats')
. Что интересно , для вас это виртуальная память , которая являетсяБыстрый побочный узел : Matlab последовательно сохраняет матрицы в памяти. Вам нужно иметь большой блок свободной оперативной памяти для больших матриц. Это также причина, по которой вы хотите выделить переменные, потому что их динамическое изменение заставляет Matlab копировать всю матрицу в большее место в ОЗУ каждый раз, когда оно перерастает текущее место.
Если у вас действительно есть проблемы с памятью , вы можете просто погрузиться в искусство типов данных - как требуется для языков более низкого уровня. Например, вы можете сократить использование памяти вдвое, используя одинарную точность непосредственно с самого начала
main_mat=zeros(500,500,2000,'single');
- кстати, это также работает сrand(...,'single')
и более встроенными функциями - хотя некоторые из более сложных функций matlab требуют ввода типа double, который вы можете снова сбитый с толку.источник
Если я правильно понимаю, ваша главная проблема в том, что
parfor
не позволяет делиться памятью. Думайте о каждом работнике parfor как об отдельном экземпляре matlab.Мне известен только один обходной путь (который я никогда не пробовал), это «общая матрица» в Fileexchange: https://ch.mathworks.com/matlabcentral/fileexchange/28572-sharedmatrix
Больше решений: как предлагали другие: удаление parfor, безусловно, одно из решений, получите больше оперативной памяти, используйте высокие массивы (которые используют жесткие диски, когда оперативная память заполнена, читайте здесь ), делите операции на более мелкие куски, последнее, но не менее важное, рассмотрите альтернативу, отличную от Matlab.
источник
Вы можете использовать следующий код. Вам на самом деле не нужен slice_matrix
источник