Измерьте время

Блокноты MuPAD® будут демонтированы в будущем релизе. Используйте live скрипты MATLAB® вместо этого.

Live скрипты MATLAB поддерживают большую часть функциональности MuPAD, хотя существуют некоторые различия. Для получения дополнительной информации смотрите, Преобразовывают Notebook MuPAD в Live скрипты MATLAB.

Вызовы процессов MuPAD

Самый простой инструмент, который можно использовать, чтобы оценить производительность кода, является функцией time. Эта функция измеряет время выполнения вашего фрагмента кода. Функция time не считает время проведенным за пределами процессов MuPAD®: внешние вызовы функции или процессы, запускающиеся в фоновом режиме, не влияют на результаты time. Функция возвращает результаты, измеренные в миллисекундах.

Следующий пример демонстрирует различные алгоритмы, реализованные для той же задачи. Задача состоит в том, чтобы проверять, появляется ли каждое целое число от 1 до 1 000 в 1000×1000 матрица случайных целых чисел. Чтобы создать 1000×1000 матрица случайных целых чисел, используйте linalg::randomMatrix:

matrixSize := 1000:
M := linalg::randomMatrix(matrixSize, matrixSize, Dom::Integer):

Прямой подход должен записать процедуру, которая проверяет каждый элемент матрицы, продолжающей строка строкой и столбцом столбцом:

f := proc(M, n, x)
begin
  for j from 1 to n do
    for k from 1 to n do
      if M[j, k] = x then
        return(TRUE)
      end_if
    end_for
  end_for;
  return(FALSE)
end_proc:

Вызовите процедуру f 1000 раз, чтобы проверять, появляется ли каждый номер от 1 до 1 000 в той матрице:

g := proc()
begin
  f(M, matrixSize, i) $ i = 1..1000
end_proc:

Этот алгоритм очень неэффективен для заданной задачи. Функциональный f выполняет 104 шага вычисления, чтобы узнать, что целое число не происходит в матричном M. Поскольку вы вызываете функциональный f 1000 раз, выполнение этого алгоритма занимает много времени:

time(g())
 62435.902 

В этом примере узкое место выбранного подхода является, очевидно, алгоритмом, это получает доступ к каждому элементу матрицы. Чтобы ускорить вычисление, перепишите процедуру f с помощью метода деления пополам. Перед использованием этого метода преобразуйте матричный M в список и отсортируйте список. Затем выберите первые и последние элементы отсортированного списка, когда начальная буква указывает. Каждый шаг в этом алгоритме делит список элементов в средней точке:

f := proc(M, n, x)
begin
  if (M[1] - x)*(M[n] - x) > 0 then
    return(FALSE)
  elif (M[1] - x)*(M[n] - x) = 0 then
    return(TRUE);
  else
    a := 1: b := n:
    while (b - a > 1) do
      if is(b - a, Type::Odd) then
        c := a + (b - a + 1)/2
      else
        c := a + (b - a)/2
      end_if;
      if M[c] - x = 0 then
        return(TRUE)
      elif (M[a] - x)*(M[c] - x) < 0 then
        b := c:  
      else
        a := c:
      end_if;
    end_while;
  end_if;
  return(FALSE)
end_proc:

Используйте функцию op, чтобы получить доступ ко всем элементам матричного M. Эта функция возвращает последовательность элементов. Используйте скобки, чтобы преобразовать эту последовательность в список. Затем используйте функцию sort, чтобы отсортировать список в порядке возрастания. Наконец, вызовите процедуру f для каждого целого числа от 1 до 1 000:

g := proc()
local M1;
begin
  M1 := sort([op(M)]):
  f(M1, matrixSize^2, i) $ i = 1..1000
end_proc:

Используя метод деления пополам вместо того, чтобы получить доступ к каждому элементу матрицы значительно улучшает производительность примера:

time(g())
 3724.233 

Как правило, лучший подход должен использовать соответствующие функции MuPAD, когда это возможно. Например, чтобы улучшать производительность далее, перепишите код с помощью функции MuPAD has. Кроме того, преобразование матрицы к набору может уменьшать число элементов. (MuPAD удаляет дублирующиеся элементы набора.) В дополнение к убыстряются, этот подход делает ваш код значительно короче и легче читать:

g := proc()
local M1;
begin
  M1 := {op(M)}:
  has(M1, i) $ i = 1..1000
end_proc:

В этом случае время выполнения еще короче, чем для кода, который реализует bisectional метод:

time(g())
 1508.094 

Вызовы внешних процессов

Результаты, возвращенные функцией time, исключают время, проведенное на вызовах внешних программ. Если ваш код использует внешние программы, можно измерить общее время, проведенное тем кодом, включая вызовы внешних процессов. Чтобы измерить общее время, используйте функцию rtime вместо time. Например, вызов функции rtime() возвращает прошедшее время текущего сеанса MuPAD. Это время включает время простоя текущего сеанса:

t := rtime():
print(Unquoted, "This session runtime is ".stringlib::formatTime(t))
This session runtime is 5 minutes, 25.579 seconds

При измерении производительности кода с помощью rtime постарайтесь не запускать другие процессы в фоновом режиме. Также гарантируйте, что достаточно памяти доступно. Функция rtime считает общее время, включая время простоя, в течение которого некоторый другой процесс использует центральный процессор, или ваш компьютер подкачивает данные между различными типами памяти.