MEX-функции профиля при помощи Профилировщика MATLAB

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

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

Генерация профиля MEX

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

Чтобы использовать профилировщик с сгенерированной MEX-функцией:

  1. Включите профилирование MEX путем установки свойства объекта строения EnableMexProfiling на true.

    Также можно использовать codegen с -profile опция.

    Эквивалентная настройка в приложении MATLAB Coder Enable execution profiling на Generate шаге.

  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-функцию, выбрав Enable execution profiling в Verify шаге приложения. Если вы включили Профилировщика 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.

    На Сводный отчет по профилированию показаны общее время и собственное время для файла MEX и его дочернего элемента, который является сгенерированным кодом для исходной функции MATLAB.

  2. В разделе Имя функции щелкните первую ссылку, чтобы просмотреть Детализированный отчет профиля для сгенерированного кода для 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 Показы покрытие этого кода в Детализированный отчет Profile:

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

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

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

См. также

| | | | |

Похожие темы