Ограничение количества переменных Matlab

У меня есть код C++, который взаимодействует с Matlab через API Engine C. Мой код создает временные переменные в рабочей области Matlab, которые он старательно очищает с помощью вызовов clear как можно скорее. Однако в какой-то момент мое приложение дает сбой, сообщая мне, что оно не может создать следующую временную переменную Matlab (обычно после ~ 65530 таких операций).

После некоторых экспериментов с командной строкой Matlab я обнаружил, что могу воссоздать эту проблему в чистом Matlab (то есть независимо от моего кода C++ и использования им Engine API). Рассмотрим следующий код:

for i = 1 : 100000
  eval(sprintf('x_%d = %d', i, i));
  whos
  eval(sprintf('clear x_%d', i));
  whos
end

Выполняя этот код на моем 32-битном ноутбуке с Windows с Matlab R2008B (древний, я знаю), цикл в конечном итоге прерывается с сообщением об ошибке:

В текущей рабочей области уже слишком много переменных; нет места для "x_65532".

Итак, кажется, что по крайней мере эта устаревшая версия Matlab имеет ограничение таблицы символов в 64 КБ. Возможно, в более новых (64-разрядных) версиях Matlab предел больше - мне было бы интересно услышать, какие результаты получают другие.

Однако более интересный вопрос заключается в том, какой эффект вызывает вызов clear и как обойти его странное поведение. Вот результат итерации немного до прерывания:

x_65530 =

       65530

  Name         Size            Bytes  Class     Attributes

  i            1x1                 8  double              
  x_65530      1x1                 8  double              

  Name      Size            Bytes  Class     Attributes

  i         1x1                 8  double              

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

Итак, два вопроса для ТАК верующих:

  1. Как я могу обойти это несколько произвольное ограничение? То есть чем заменить мои clear вызовы?
  2. Изменилось ли это поведение с более новыми и/или 64-разрядными версиями Matlab?

person Drew Hall    schedule 02.12.2013    source источник
comment
Можете ли вы рассказать больше о вариантах использования, которые требуют так много временных переменных? P.S: вам не нужно eval для первого sprintf внутри цикла...   -  person Eitan T    schedule 02.12.2013
comment
Воспроизводится в 2011b (32 бита) - точно такая же ошибка. Интересно то, что если я затем определяю дополнительные переменные в командной строке или повторно запускаю цикл, я не получаю ошибку (пока я снова не нажму эту точку в цикле).   -  person nkjt    schedule 02.12.2013
comment
@EitanT: пример использования: мой код C++ анимирует график Matlab, отправляя ему много новых данных в каждом кадре. Вероятно, есть лучший способ сделать это, но он работает (по крайней мере, пока не достигнет предела). Что касается оценки, вы уверены? Я явно пытаюсь создать переменную с алгоритмически выбранным уникальным именем. Пропуск eval даст мне безымянную временную строку, не так ли?   -  person Drew Hall    schedule 02.12.2013
comment
@nkjt: Интересно. Возможно, контекст цикла имеет собственную таблицу символов, подчиненную глобальной таблице? Мой код C++, который дает сбой, не делает этого в цикле Matlab for, кстати, поэтому я, вероятно, загрязняю глобальную таблицу. Все предположения, конечно...   -  person Drew Hall    schedule 02.12.2013
comment
Также воспроизводится на 64-битной версии 2011b. Вопрос, однако, в том, почему, ну почему, вы делаете такие неприятные вещи? Почему бы не взять одну переменную и не обновить ее значение? Если вам дополнительно нужен i, извлеченный из имени, вам следует просто добавить вторую переменную - или использовать одну структурную переменную, например. с полями x и i, значения которых вы можете обновить.   -  person sebastian    schedule 02.12.2013
comment
@sebastian: Спасибо за точку данных. Что касается причины этого, у меня есть класс TempVar на С++, который содержит данные, которые я передаю в Matlab. Он поддерживает статический подсчет количества созданных TempVar, чтобы они не мешали друг другу, и очищает соответствующую переменную Matlab в деструкторе TempVar. Я уверен, что есть более элегантный способ сделать это, но мой способ не противоречит какой-либо документации API matlab/mex/engine, которую я могу найти, поэтому я ожидаю, что он тоже будет работать. Однако я пересмотрю свой код, чтобы посмотреть, можно ли применить более элегантный подход.   -  person Drew Hall    schedule 02.12.2013
comment
Итак, не все экземпляры TempVar обязательно содержат одинаковую информацию? Я предполагал, что все переменные читаются одним и тем же клиентом, и в этом случае обновление одной переменной казалось намного лучше. Если вам нужно придерживаться именования переменных, вы можете попробовать повторно использовать имена переменных после их очистки.   -  person sebastian    schedule 02.12.2013
comment
@sebastian: Ваша идея повторного использования имени может просто помочь - я бы поддерживал бесплатный список идентификаторов и извлекал бы из него, если бы мне не пришлось использовать новый идентификатор. Сообщу, как только попробую этот подход.   -  person Drew Hall    schedule 03.12.2013
comment
@sebastian: я внедрил вашу схему повторного использования временных имен, и мне удалось избежать запуска этого режима сбоя - спасибо за совет. Если вы превратите это в ответ, я приму это.   -  person Drew Hall    schedule 10.12.2013


Ответы (4)


Повторяю свой комментарий в форме ответа:

Если вам нужно придерживаться именования переменных, вы можете попытаться повторно использовать имена переменных после их очистки, избегая создания 65xxx разных имен переменных.

person sebastian    schedule 10.12.2013

Ответ на 2) заключается в том, что это ограничение применяется к более старым версиям Matlab. Хотя предел все еще присутствует в R2014b, его больше нет в R2015b.

person jpfeifer    schedule 27.08.2016

Дело в том, что в Matlab вам не нужно иметь столько переменных. Используйте большие переменные, а не много переменных.

Если каждый x является скаляром: используйте вектор

Если все x имеют одинаковый размер: используйте матрицу

Если каждый x отличается, используйте массив ячеек!

С x{65530} = magic(3) вы не будете приближаться к пределу.

person Dennis Jaheruddin    schedule 02.12.2013

Я просто наткнулся на то же самое. Из Python я создаю временные переменные в экземпляре Matlab, которые позже очищаются. Чтобы убедиться, что я не перезаписываю другую временную переменную, я создал для них новые имена с помощью модуля Python uuid(). Это должна была быть отличная идея. Однако через некоторое время я получил исключение с сообщением «В текущей рабочей области уже слишком много переменных». Выполняя whos, я вижу, что это всего лишь 8 переменных, поэтому я должен сделать вывод, что clear на самом деле не удаляет переменную из рабочей области. Это действительно трудно понять и очень неудобно. Это правда, что я могу использовать имена temp001, temp002, temp003, но затем, когда мне понадобится новая временная переменная, я должен убедиться, что в настоящее время я уже не использую это имя. Uuids были изобретены, чтобы избежать подобных проблем, но, похоже, неудобное поведение Matlab мешает мне их использовать. Кто-нибудь нашел хорошее решение для ДЕЙСТВИТЕЛЬНОГО удаления переменных из рабочей области Matlab?

person zeycus    schedule 06.07.2015