Я сохраняю память в MATLAB, объявляя переменные global вместо того, чтобы передавать их в качестве аргументов?

Я новичок в MATLAB, это не было в описании работы, и я был вынужден взять на себя ответственность за человека, который написал и поддерживал код, который использует моя компания. Жизнь сложная.

Парень, из которого я берусь, сказал мне, что он объявил все большие векторы данных как global, чтобы сохранить память. Более конкретно, так что, когда одна функция вызывает другую функцию, он не создает копию данных, когда он передает ее.

Это правда? Я читал Стратегии эффективного использования памяти, и он говорит, что

При работе с большими наборами данных следует помнить, что MATLAB создает временную копию входной переменной, если вызываемая функция изменяет ее значение. Это временно удваивает память, необходимую для хранения массива, что заставляет MATLAB генерировать ошибку, если достаточная память недоступна.

В нем говорится что-то очень похожее в Распределение памяти для массива Аргументы #Function:

Когда вы передаете переменную функции, вы фактически передаете ссылку на данные, которые представляет переменная. Пока входные данные не изменяются вызываемой функцией, переменная в вызывающей функции и переменная в вызываемой функции указывают на то же место в памяти. Если вызываемая функция изменяет значение входных данных, то MATLAB делает копию исходного массива в новом месте в памяти, обновляет, копирует с измененным значением, и указывает входную переменную в вызываемой функции на этот новый массив.

Так верно ли, что использование global может быть лучше? Кажется немного небрежным, чтобы blithely объявить все большие данные как global, вместо того, чтобы убедиться, что ни один из кодов не изменяет свой входной аргумент. Я ошибаюсь? Это действительно улучшает использование ОЗУ?

Ответ 1

По моему опыту, при условии, что ни один из кодов не изменяет большие данные, использование памяти одинаково, независимо от того, используете ли вы глобальную переменную или входной аргумент, как говорят документы в Matlab. Дополнительная информация содержится в этом сообщении

Ответ 2

Этот ответ может быть несколько касательным, но дополнительная тема, которая упоминается здесь, заключается в использовании вложенных функций для управления памятью.

Как уже было установлено в других ответах, нет необходимости в переменных global, если данные, которые вы передаете функции, не изменяются (поскольку они будут переданы по ссылке). Если он изменен (и таким образом передается по значению), вместо этого вместо переменной global будет сохранена ваша память. Однако переменные global могут быть несколько "грубыми" по следующим причинам:

  • Вам нужно сделать объявление типа global varName везде, где они вам нужны.
  • Это может быть концептуально немного беспорядочно, пытаясь отслеживать, когда и как они изменяются, особенно если они распределены по нескольким m файлам.
  • Пользователь может легко сломать ваш код с плохо размещенным clear global, который очищает все глобальные переменные.

Альтернатива переменным global была упомянута в первом наборе документации, которую вы указали: вложенные функции. Сразу после цитируемой цитаты приведен пример кода (который я отформатировал здесь несколько иначе):

function myfun

  A = magic(500);
  setrowval(400, 0);
  disp('The new value of A(399:401,1:10) is')
  A(399:401,1:10)

  function setrowval(row, value)
    A(row,:) = value;
  end

end

В этом примере функция setrowval вложена внутри функции myfun. Переменная A в рабочем пространстве myfun доступна в пределах setrowval (как если бы она была объявлена ​​global в каждом). Вложенная функция изменяет эту общую переменную, что позволяет избежать дополнительного распределения памяти. Вам не нужно беспокоиться о том, что пользователь непреднамеренно очистил что-либо и, по-моему, немного чище и легче следовать, чем объявлять переменные global.

Ответ 4

Решение кажется мне немного странным. Как вы уже выяснили, это не должно оказывать существенного влияния на использование памяти, если вызываемая функция не изменяет массив данных. Однако, если вызываемая функция изменяет массив данных, существует функциональная разница: в одном случае (делая массив данных глобальным) это изменение влияет на остальную часть кода, в другом случае (передавая его как ссылку) модификации являются только локальными и временными.