exponenta event banner

Профилирование функций MEX с помощью профилировщика MATLAB

Время выполнения функций MEX, созданных MATLAB ® Coder™, можно профилировать с помощью профилировщика MATLAB. Профиль сгенерированного кода показывает количество вызовов и время, затраченное на каждую строку соответствующей функции MATLAB. Используйте Profiler для определения строк кода MATLAB, создающих сгенерированный код, который занимает наибольшее время. Эта информация поможет выявить и исправить проблемы производительности на ранних этапах цикла разработки. Дополнительные сведения о профилировщике MATLAB см. в разделеprofile и создайте профиль кода для повышения производительности.

Графический интерфейс к профилировщику не поддерживается в MATLAB Online™.

Создание профиля MEX

Профилировщик MATLAB можно использовать с созданной функцией MEX. Кроме того, если имеется тестовый файл, вызывающий функцию MATLAB, можно создать функцию MEX и профилировать ее за один шаг. Эти операции можно выполнить в командной строке или в приложении MATLAB Coder.

Для использования профилировщика с созданной функцией MEX:

  1. Включить профилирование MEX, задав свойство объекта конфигурации EnableMexProfiling кому true.

    Кроме того, можно использовать codegen с -profile вариант.

    Эквивалентная настройка в приложении MATLAB Coder - Включить профилирование выполнения на шаге Создать.

  2. Создание файла MEX MyFunction_mex.

  3. Запустите профилировщик MATLAB и просмотрите сводный отчет по профилю, который откроется в отдельном окне.

    profile on;
    MyFunction_mex;
    profile viewer;

    Убедитесь, что исходный файл MATLAB не был изменен или перемещен MyFunction.m. В противном случае профилировщик не учитывает MyFunction_mex для профилирования.

При наличии тестового файла MyFunctionTest.m который вызывает функцию MATLAB, можно:

  • Создайте функцию MEX и выполните ее профилирование за один шаг с помощью codegen с -test и -profile варианты. Если профилировщик MATLAB был включен ранее, выключите его перед совместным использованием этих двух опций.

    codegen MyFunction -test MyFunctionTest -profile
  • Выполните профилирование функции MEX, выбрав Включить профилирование выполнения на шаге Проверить приложения. Если профилировщик MATLAB был включен ранее, выключите его перед выполнением этого действия.

Пример

Профилировщик используется для определения функций или строк кода MATLAB, создающих сгенерированный код, который занимает наибольшее время. Ниже приведен пример функции MATLAB, которая преобразует представление своих входных матриц. A и B от главной строки к главной колонке в одной из ее линий. Такое преобразование имеет длительное время выполнения для больших матриц. Исключение преобразования путем изменения данной строки делает функцию более эффективной.

Рассмотрим функцию MATLAB:

function [y] = MyFunction(A,B) %#codegen

% Generated code uses row-major representation of matrices A and B
coder.rowMajor; 
length = size(A,1);

% Summing absolute values of all elements of A and B by traversing over the
% matrices row by row
sum_abs = 0;  
for row = 1:length 
   for col = 1:length  
       sum_abs = sum_abs + abs(A(row,col)) + abs(B(row,col));
   end
end

% Calling external C function 'foo.c' that returns the sum of all elements
% of A and B
sum = 0;
sum = coder.ceval('foo',coder.ref(A),coder.ref(B),length);

% Returning the difference of sum_abs and sum
y = sum_abs - sum;
end

Созданный код для этой функции использует главное представление строк квадратных матриц A и B. Код сначала вычисляет sum_abs (сумма абсолютных значений всех элементов A и B) путем обхода матриц по строкам. Этот алгоритм оптимизирован для матриц, представленных в главной строке. Код затем использует coder.ceval для вызова внешней функции C foo.c:

#include <stdio.h>
#include <stdlib.h>
#include "foo.h"

double foo(double *A, double *B, double length)
{
 int i,j,s;
 double sum = 0;
 s = (int)length;
 
 /*Summing all the elements of A and B*/
 for(i=0;i<s*s;i++)
 {
         sum += A[i] + B[i];
 }
 return(sum);
}

Соответствующий файл заголовка C foo.h является:

#include "rtwtypes.h"

double foo(double *A, double *B, double length);

foo.c возвращает переменную sum, которая является суммой всех элементов A и B. Выполнение функции foo.c не зависит от того, являются ли матрицы матрицами A и B представлены в компоновках «основные строки» или «основные столбцы». MyFunction возвращает разность sum_abs и sum.

Вы можете измерить производительность MyFunction для больших входных матриц A и B, а затем оптимизировать его дальше:

  1. Включение профилирования MEX и создание кода MEX для MyFunction. Управляемый MyFunction_mex для двух больших случайных матриц A и B. Просмотр сводного отчета по профилю.

    A = rand(20000);
    B = rand(20000);
    
    codegen MyFunction -args {A,B} foo.c foo.h -profile
    
    profile on; 
    MyFunction_mex(A,B);
    profile viewer;

    Откроется отдельное окно с обзором сводного отчета по профилю.

    Profile summary exhibiting a table with field Function Name Calls, Total Time in seconds, Self Time in seconds and total time plot. A flame graph is present, representing the table in a bar graph.

    В Сводном отчете по профилю (Profile Summary Report) показано общее время и самостоятельное время для файла MEX и его нижестоящего элемента, который является сгенерированным кодом для исходной функции MATLAB.

  2. В разделе Имя функции (Function Name) щелкните первую ссылку, чтобы просмотреть подробный отчет профиля для созданного кода для MyFunction. Вы можете увидеть строки, где было потрачено больше всего времени:

    Table with fields Line Number, Code, Cells, Total time in seconds, Percentage of time and time plot with relevant data entries from example code. Important to point out that the total time for coder.ceval is relatively high.

  3. Вызывающая линия coder.ceval занимает много времени (16,914 с). Эта строка имеет значительное время выполнения, потому что coder.ceval преобразует представление матриц A и B от макета основной строки к макету основной строки перед передачей их внешней функции C. Избежать этого преобразования можно с помощью дополнительного аргумента -layout:rowMajor в coder.ceval:

    sum = coder.ceval('-layout:rowMajor','foo',coder.ref(A),coder.ref(B),length);
  4. Создайте функцию MEX и профиль снова с помощью измененного MyFunction.

    A = rand(20000);
    B = rand(20000);
    
    codegen MyFunction -args {A,B} foo.c foo.h -profile
    
    profile on; 
    MyFunction_mex(A,B);
    profile viewer;
    Подробный отчет о профиле для MyFunction показывает, что вызывающая линия coder.ceval теперь занимает всего 0,653 с:

    Same image as mentioned above, here coder.ceval has a reduced total time of 0.653s.

Влияние выражений сворачивания на охват кода MEX

При использовании coder.const сворачивание выражений в константы приводит к различию в покрытии кода между функцией MATLAB и функцией MEX. Например, рассмотрим функцию:

function y = MyFoldFunction %#codegen
a = 1;
b = 2; 
c = a + b;
y = 5 + coder.const(c);
end

Профилирование функции MATLAB MyFoldFunction показывает покрытие кода в подробном отчете о профиле:

Однако профилирование функции MEX MyFoldFunction_mex показывает другое покрытие кода:

Строки 2, 3 и 4 не выполняются в созданном коде, поскольку выражение было свернуто c = a + b в константу для генерации кода.

В этом примере используется пользовательское сворачивание выражений. Генератор кода иногда автоматически сворачивает определенные выражения для оптимизации производительности создаваемого кода. Такие оптимизации также приводят к тому, что охват функции MEX отличается от охвата функции MATLAB.

См. также

| | | | |

Связанные темы