34.3.2 Оптимизация индексированного присваивания
Повсеместная семантика передачи по значению с отложенным копированием в Octave создает проблему производительности для определяемых пользователем методов subsasgn. Рассмотрим следующий вызов subsasgn
ss = substruct ("()", {1});
x = subsasgn (x, ss, 1); где соответствующий метод выглядит следующим образом:
function x = subsasgn (x, ss, val)
...
x.myfield (ss.subs{1}) = val;
endfunction Проблема заключается в том, что при входе в метод subsasgn на x по-прежнему ссылается область видимости вызывающего кода, а это означает, что перед выполнением присваивания методу сначала потребуется отменить совместное использование (создать копию) x и x.myfield. После завершения вызова, если не возникла ошибка, результат немедленно присваивается x в области видимости вызывающего кода, так что предыдущее значение x.myfield забывается. Таким образом, язык Octave предполагает копирование N элементов (где N — размер x.myfield), хотя на самом деле достаточно изменить всего один элемент. Иными словами, операция с постоянным временем выполнения становится операцией с линейным временем выполнения. Это может стать реальной проблемой для пользовательских классов, которые по своей природе хранят большие массивы.
Для частичного решения этой проблемы Octave использует специальную оптимизацию для определяемых пользователем методов subsasgn, написанных в виде m-файлов. Если метод вызывается в результате использования встроенного синтаксиса присваивания (а не прямого вызова subsasgn, как показано выше), то есть x(1) = 1, И если метод subsasgn объявлен с одинаковыми входными и выходными аргументами, как в примере выше, Octave проигнорирует копию x в области видимости вызывающего кода; следовательно, любые изменения, внесенные в x во время выполнения метода, также будут напрямую влиять на копию вызывающего кода. Это позволяет, например, определить класс многочленов, в котором изменение одного элемента занимает постоянное время.
Важно понимать последствия применения этой оптимизации. Поскольку в области видимости вызывающего кода не будет дополнительной копии x, исключительно вызываемый метод отвечает за то, чтобы не оставить x в недопустимом состоянии, если во время выполнения произойдет ошибка. Кроме того, если метод частично изменит x, а затем завершится с ошибкой, эти изменения повлияют на x в области видимости вызывающего кода. Удаление или полная замена x внутри subsasgn, однако, ни на что не повлияет: учитываются только индексированные присваивания.
Поскольку эта оптимизация может изменить работу кода (особенно если он написан небрежно), для управления ею предусмотрена функция optimize_subsasgn_calls. По умолчанию эта функция включена. Еще один способ избежать оптимизации — объявить методы subsasgn с разными входными и выходными аргументами, например так:
function y = subsasgn (x, ss, val) ... endfunction
© 1996–2026 The Octave Project Developers
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.
https://docs.octave.org/v9.4.0/Indexed-Assignment-Optimization.html