19.6 Разные приёмы
Вот несколько способов повышения скорости выполнения программ Octave.
- Избегайте многократного вычисления дорогостоящих промежуточных результатов. Octave в настоящее время не устраняет общие подвыражения. Кроме того, некоторые внутренние результаты вычислений кешируются для переменных. Например, если матричная переменная используется несколько раз в качестве индекса, проверка индексов (и внутреннее преобразование в целые числа) выполняется только один раз.
- Учитывайте ленивые копии (копирование при записи). Когда создаётся копия объекта, данные не копируются сразу, а вместо этого совместно используются. Фактическое копирование откладывается до тех пор, пока скопированные данные не потребуется изменить. Например:
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–2023 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/v8.1.0/Miscellaneous-Techniques.html