19.5 Разные приёмы
Вот несколько других способов повышения скорости выполнения программ Octave.
- Избегайте многократного вычисления дорогостоящих промежуточных результатов. Octave в настоящее время не устраняет общие подвыражения. Кроме того, некоторые внутренние результаты вычислений кешируются для переменных. Например, если матричная переменная используется несколько раз в качестве индекса, проверка индексов (и внутреннее преобразование в целые числа) выполняется только один раз.
- Учитывайте ленивые копии (копирование при записи). Когда создается копия объекта, данные не копируются сразу, а, скорее, разделяются. Фактическое копирование откладывается до тех пор, пока скопированные данные не потребуются для изменения. Например:
a = zeros (1000); # create a 1000x1000 matrix b = a; # no copying done here b(1) = 1; # copying done here
Ленивое копирование применяется к целым объектам Octave, таким как матрицы, ячейки, структуры, а также к отдельным элементам ячеек или структур (не элементам массива).
Кроме того, выражения с индексами также используют ленивое копирование, когда Octave может определить, что индексированная часть находится в памяти непрерывно. Например:
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/v7.2.0/Miscellaneous-Techniques.html