Блокноты MuPAD® будут демонтированы в будущем релизе. Используйте live скрипты MATLAB® вместо этого.
Live скрипты MATLAB поддерживают большую часть функциональности MuPAD, хотя существуют некоторые различия. Для получения дополнительной информации смотрите, Преобразуют Notebook MuPAD в Live скрипты MATLAB.
Профилирование является способом измериться, где программа проводит время. MuPAD® обеспечивает prog::profile
функционируйте, чтобы помочь вам идентифицировать узкие места производительности в своем коде. Используйте эту функцию, чтобы анализировать производительность сложных вложенных вызовов процедуры. Для более простых фрагментов кода измерение времен выполнения более удобно и может дать вам достаточно информации, чтобы идентифицировать узкие места производительности.
prog::profile
функция оценивает код, который вы хотите профилировать, и возвращает профильный отчет. Отчет содержит:
Таблица, показывающая время ваш код, потраченный на каждую функцию (общее количество и усредненный на один вызов), количество вызовов этой функции, дочерних элементов этой функции, и так далее. Информация для наиболее в большой степени используемых функций появляется на верхних строках таблицы. Первая строка в этой таблице представляет общее время выполнения.
График зависимости, показывающий саму функцию, функции, которые это вызывает (дочерние элементы) и функции, которые вызывают эту функцию. График также показывает синхронизацию и количество призывов к каждой функции.
По умолчанию, prog::profile
не измеряет уровень одного вызовов функций ядра.
Однако, когда prog::profile
измеряет уровень библиотечных функций, он также распечатывает накопленное время, которое система проводит в функциях ядра. Чтобы измерить уровень одного вызова функции ядра, используйте prog::trace
прослеживать ту функцию ядра.
Предположим, что вы хотите записать процедуру, которая проверяет, появляется ли каждое целое число от 1 до 1 000 в 1000×1000 матрица случайных целых чисел. Прямой подход должен записать процедуру, которая проверяет каждый элемент матрицы, продолжающей строка строкой и столбцом столбцом:
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:
Используйте linalg::randomMatrix
создать 1000×1000 матрица случайных целых чисел:
matrixSize := 1000: M := linalg::randomMatrix(matrixSize, matrixSize, Dom::Integer):
Затем вызовите процедуру f
1000 раз, чтобы проверять, появляется ли каждый номер от 1 до 1 000 в той матрице:
g := proc() begin f(M, matrixSize, i) $ i = 1..1000 end_proc:
Измерение времени должно было запустить процедуру g
показывает, что процедура требует оптимизации. Несмотря на то, что узкое место производительности в этой процедуре очевидно, не всегда легко идентифицировать узкие места производительности в более сложных процедурах. time
функция не указывает, где процедура проводит большую часть своего времени выполнения:
time(g())
62023.876
Чтобы получить полный профильный отчет, который показывает синхронизации для всех внутренних вызовов функции, используйте prog::profile
:
prog::profile(g()):
percent usage of all
| time self per single call
| | time self
| | | time children per single call
| | | | time children
| | | | | calls/normal exit
| | | | | | calls/remember exit
| | | | | | | calls/errors
| | | | | | | | [index] function name
--------------------------------------------------------------------------------------------------------------------
100.0 109982.9 109982.9 . . 1 . . [0] procedure entry point
--------------------------------------------------------------------------------------------------------------------
45.9 . 50467.2 . 27149.6 3019825 . . [1] (Dom::Matrix(Dom::Integer))::_index_intern
19.7 . 21689.3 . 5460.3 3019825 . . [2] Dom::Integer::coerce
16.7 . 18373.1 . 77616.9 3019825 . . [3] (Dom::Matrix(Dom::Integer))::_index
12.7 14.0 13984.8 96.0 95990.0 1000 . . [4] f
5.0 . 5460.3 . . 3019825 . . [5] Dom::Integer::convert
. 8.0 8.0 109974.9 109974.9 1 . . [6] g
--------------------------------------------------------------------------------------------------------------------
index %time self children called [index] name
---------------------------------------------------------------------------------------------
[0] 100.0 109982.8 0 1 procedure entry point
8.0 109974.8 1 [6] g
---------------------------------------------------------------------------------------------
50467.24 27149.65 3019825 [3] (Dom::Matrix(Dom::Integer))::_index
[1] 45.9 50467.24 27149.65 3019825 (Dom::Matrix(Dom::Integer))::_index_intern
21689.30 5460.346 3019825 [2] Dom::Integer::coerce
---------------------------------------------------------------------------------------------
21689.30 5460.346 3019825 [1] (Dom::Matrix(Dom::Integer))::_index_intern
[2] 19.7 21689.30 5460.346 3019825 Dom::Integer::coerce
5460.346 0 3019825 [5] Dom::Integer::convert
---------------------------------------------------------------------------------------------
18373.13 77616.89 3019825 [4] f
[3] 16.7 18373.13 77616.89 3019825 (Dom::Matrix(Dom::Integer))::_index
50467.24 27149.65 3019825 [1] (Dom::Matrix(Dom::Integer))::_index_intern
---------------------------------------------------------------------------------------------
13984.84 95990.02 1000 [6] g
[4] 12.7 13984.84 95990.02 1000 f
18373.13 77616.89 3019825 [3] (Dom::Matrix(Dom::Integer))::_index
---------------------------------------------------------------------------------------------
5460.346 0 3019825 [2] Dom::Integer::coerce
[5] 5.0 5460.346 0 3019825 Dom::Integer::convert
---------------------------------------------------------------------------------------------
[6] 0.0 8.0 109974.8 1 g
13984.84 95990.02 1000 [4] f
---------------------------------------------------------------------------------------------
Time sum: 109982.873 ms
Верхние строки профильного отчета указывают, что процедура проводит большую часть своего времени, получая доступ к каждому элементу матрицы. Чтобы улучшать производительность, перепишите процедуру так, чтобы это могло получить доступ к меньшему количеству элементов матрицы в каждом вызове процедуры f
. Например, используйте алгоритм на основе метода деления пополам:
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:
Прежде, чем вызвать процедуру f
, необходимо преобразовать матричный M
к списку и виду тот список. Сортировка списка, который содержит 104 записи, является дорогой операцией. В зависимости от количества вызовов процедуры f
, эта операция может потенциально устранить увеличение производительности, которую вы получаете путем улучшения процедуры f
самостоятельно:
g := proc() local M1; begin M1 := sort([op(M)]): f(M1, matrixSize^2, i) $ i = 1..1000 end_proc:
Для них конкретный матричный размер и количество вызовов f
, реализация bisectional алгоритма все еще эффективна несмотря на время, требуемое отсортировать список:
time(g())
3840.24
Профильный отчет показывает, что процедура тратит наиболее часто выполнение op
и g
вызовы функции. Это вызвано тем, что реализация алгоритма двоичного поиска добавила новые дорогие операции в g
(преобразование матрицы к списку и затем сортировке списка). Профильный отчет сгенерировал для вызова процедуры g()
очень длинно. Этот пример показывает только верхнюю часть отчета:
prog::profile(g()):
percent usage of all
| time self per single call
| | time self
| | | time children per single call
| | | | time children
| | | | | calls/normal exit
| | | | | | calls/remember exit
| | | | | | | calls/errors
| | | | | | | | [index] function name
-------------------------------------------------------------------------------------------------
100.0 3884.2 3884.2 . . 1 . . [0] procedure entry point
-------------------------------------------------------------------------------------------------
56.1 2180.1 2180.1 1704.1 1704.1 1 . . [1] g
33.0 1280.1 1280.1 188.0 188.0 1 . . [2] (Dom::Matrix(Dom::Integer))::op
6.1 0.2 236.0 . . 1000 . . [3] f
3.2 0.1 124.0 . . 1000 . . [4] `p -> [coeff(p, All)][2..-1]`
1.5 0.1 60.0 . . 1000 . . [5] `l -> l.[Rzero $ r - nops(l)]`
0.1 2.0 4.0 . . 2 . . [6] Dom::Integer::hasProp
. . . . . 2 . . [7] DomainConstructor::hasProp
. . . . . . 9981 . [8] is
-------------------------------------------------------------------------------------------------
Рекомендуемый подход для того, чтобы улучшать производительность вашего кода должен использовать функции MuPAD, если это возможно. Например, MuPAD обеспечивает has
функция для проверки, содержит ли один объект MuPAD другой объект MuPAD. Перепишите свой код с помощью has
функционируйте и объединение процедур f
и g
:
g := proc() local M1; begin M1 := {op(M)}: has(M1, i) $ i = 1..1000 end_proc:
Эта процедура также преобразует матричный M
к набору. Преобразование матрицы к набору может уменьшать число элементов. (MuPAD удаляет дублирующиеся элементы набора.)
Время выполнения для вызова процедуры g()
является самым коротким среди этих трех реализаций:
time(g())
1520.095
Профильный отчет показывает, что процедура проводит большую часть своего времени выполнения, получая доступ 1000×1000 матрица случайных целых чисел и преобразовывая его в набор. Этот пример показывает только верхнюю часть профильного отчета:
prog::profile(g()):
percent usage of all
| time self per single call
| | time self
| | | time children per single call
| | | | time children
| | | | | calls/normal exit
| | | | | | calls/remember exit
| | | | | | | calls/errors
| | | | | | | | [index] function name
----------------------------------------------------------------------------------------------
100.0 1556.1 1556.1 . . 1 . . [0] procedure entry point
----------------------------------------------------------------------------------------------
78.9 1228.1 1228.1 188.0 188.0 1 . . [1] (Dom::Matrix(Dom::Integer))::op
9.0 140.0 140.0 1416.1 1416.1 1 . . [2] g
8.2 0.1 128.0 . . 1000 . . [3] `p -> [coeff(p, All)][2..-1]`
3.9 0.1 60.0 . . 1000 . . [4] `l -> l.[Rzero $ r - nops(l)]`
. . . . . 2 . . [5] Dom::Integer::hasProp
. . . . . 2 . . [6] DomainConstructor::hasProp
----------------------------------------------------------------------------------------------