19.6 Разные приёмы
Вот несколько других способов ускорить выполнение программ Octave.
- Избегайте многократного вычисления дорогостоящих промежуточных результатов. Octave в настоящее время не устраняет общие подвыражения. Кроме того, некоторые внутренние результаты вычислений кэшируются для переменных. Например, если матричная переменная используется несколько раз в качестве индекса, проверка индексов (и внутреннее преобразование в целые числа) выполняется только один раз.
- Учитывайте ленивые копии (copy-on-write). При создании копии объекта данные не копируются немедленно, а вместо этого разделяются. Фактическая копия откладывается до тех пор, пока скопированные данные не потребуется изменить. Например:
a = zeros (1000); # create a 1000x1000 matrix b = a; # no copying done here b(1) = 1; # copying done here
Ленивое копирование применяется к целым объектам Octave, таким как матрицы, ячейки, структуры, а также к отдельным элементам ячеек или структур (не элементам массива).
Кроме того, выражения индексирования также используют ленивое копирование, когда Octave может определить, что индексируемая часть находится в памяти contiguously. Например:
a = zeros (1000); # create a 1000x1000 matrix b = a(:,10:100); # no copying done here b = a(10:100,:); # copying done here
Это относится к массивам (матрицам), массивам ячеек и структурам, индексируемым с помощью «()». Выражения индексирования, генерирующие список, разделённый запятыми, также могут извлечь выгоду из поверхностного копирования в некоторых случаях. В частности, когда a — массив структур, выражения типа
{a.x}, {a(:,2).x}будут использовать ленивое копирование, чтобы данные могли разделяться между массивом структур и массивом ячеек.Большинство выражений индексирования существуют не дольше своих родительских объектов. Однако в редких случаях лениво скопированный срез переживает своего родителя, в результате чего он становится сиротой, по-прежнему занимая излишне больше памяти, чем необходимо. Чтобы обеспечить решение, работающее в большинстве реальных случаев, Octave проверяет наличие сиротских ленивых срезов в определённых ситуациях, когда значение сохраняется в «постоянном» месте, например, в именованной переменной или элементе ячейки или структуры, и, возможно, экономит их. Например:
a = zeros (1000); # create a 1000x1000 matrix b = a(:,10:100); # lazy slice a = []; # the original "a" array is still allocated c{1} = b; # b is reallocated at this point - Избегайте глубокой рекурсии. Вызовы функций к m-файловым функциям имеют сравнительно значительную накладную, поэтому переписывание рекурсии в виде цикла часто помогает. Кроме того, обратите внимание на то, что максимальный уровень рекурсии ограничен.
- Избегайте ненужного изменения размера матриц. При построении единственной матрицы результата из ряда вычислений сначала задайте размер матрицы результата, а затем вставляйте значения в неё. Запишите
result = zeros (big_n, big_m) for i = over:and_over ridx = … cidx = … result(ridx, cidx) = new_value (); endfor
вместо
result = []; for i = ever:and_ever result = [ result, new_value() ]; endfor
Иногда количество элементов нельзя вычислить заранее, и необходимы операции типа стека. Когда элементы многократно вставляются или удаляются из конца массива, Octave распознаёт это как использование стека и пытается использовать более разумную стратегию управления памятью, предварительно выделяя массив большими блоками. Эта стратегия также применяется к массивам ячеек и массивам структур.
a = []; while (condition) … a(end+1) = value; # "push" operation … a(end) = []; # "pop" operation … endwhile
- Избегайте чрезмерного вызова
evalилиfeval. Разбор входных данных или поиск имени функции в таблице символов — относительно дорогостоящие операции.Если вы используете
evalтолько как механизм обработки исключений, а не потому, что вам нужно выполнить произвольный текст, используйте операторtry. См. Оператор try. - Используйте
ignore_function_time_stampпри необходимости. Если вы вызываете много функций, и ни одна из них не должна меняться во время выполнения, установите переменнуюignore_function_time_stampв значение"all". Это позволит Octave прекратить проверку отметки времени файла функции, чтобы убедиться, что он не был обновлён во время выполнения программы.
© 1996–2022 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/v5.2.0/Miscellaneous-Techniques.html