Чтобы преобразовать код MATLAB ® в эффективный код C/C + +, генератор кода вводит оптимизации, которые намеренно заставляют сгенерированный код вести себя иначе и иногда дают другие результаты, чем исходный код.
Вот некоторые различия:
Индексирование для циклов с использованием операндов одиночной точности (кодер MATLAB)
Индекс неустановленного цикла для (кодер MATLAB)
Размер пустого массива в результате удаления элементов массива
Операции с двоичными элементами с одиночными и двойными операндами
Классы MATLAB во вложенных назначениях свойств с заданными методами
Преобразование строк с последовательными унарными операторами в двойные
Некоторые математические операции, такие как декомпозиция сингулярных значений и декомпозиция собственных значений матрицы, могут иметь несколько ответов. Два различных алгоритма, реализующих такую операцию, могут возвращать разные выходы для одинаковых входных значений. Две различные реализации одного и того же алгоритма также могут демонстрировать одинаковое поведение.
Для таких математических операций соответствующие функции в сгенерированном коде и MATLAB могут возвращать различные выходные сигналы для идентичных входных значений. Для получения информации о том, имеет ли функция такое поведение, см. раздел Генерация кода C/C + + в разделе Расширенные возможности. Примеры таких функций включаютsvd и eig.
ans ПеременнаяПри выполнении кода MATLAB, возвращающего выходные данные без указания выходного аргумента, MATLAB неявно записывает выходные данные в ans переменная. Если переменная ans уже существует в рабочей области, MATLAB обновляет свое значение до возвращенных выходных данных.
Код, генерируемый таким кодом MATLAB, не записывает неявно выходные данные в ans переменная.
Например, определите функцию MATLAB. foo , который явно создает ans переменная в первой строке. Затем функция неявно обновляет значение ans при выполнении второй строки.
function foo %#codegen ans = 1; 2; disp(ans); end
Управляемый foo в командной строке. Конечное значение ans, что является 2, отображается в командной строке.
foo
2
Создание функции MEX из foo.
codegen fooВыполнение сгенерированной функции MEX foo_mex. Эта функция явно создает ans переменная и присваивает значение 1 к нему. Но foo_mex неявно не обновляет значение ans кому 2.
foo_mex
1
Предположим, что код MATLAB имеет логические операторы & и | помещен в квадратные скобки ([ и ]). Для таких кодовых шаблонов сгенерированный код не использует поведение короткого замыкания для этих логических операторов, но выполнение MATLAB может использовать поведение короткого замыкания. См. раздел Логическое короткое замыкание.
Например, определите функцию MATLAB. foo который использует & оператор в квадратных скобках в условном выражении if...end блок.
function foo if [returnsFalse() & hasSideEffects()] end end function out = returnsFalse out = false; end function out = hasSideEffects out = true; disp('This is my string'); end
Первый аргумент & оператор всегда false и определяет значение условного выражения. Таким образом, при выполнении MATLAB используется короткое замыкание, и второй аргумент не оценивается. Итак, foo не вызывает hasSideEffects функция во время выполнения и не отображает ничего в командной строке.
Создание функции MEX для foo. Вызов сгенерированной функции MEX foo_mex.
foo_mex
This is my string
В генерируемом коде короткое замыкание не используется. Итак, hasSideEffects вызывается функция, и строка отображается в командной строке.
Предположим, что forЗначение -loop end равно или близко к максимальному или минимальному значению для типа данных индекса цикла. В сгенерированном коде последнее приращение или уменьшение индекса цикла может привести к переполнению переменной индекса. Переполнение индекса может привести к бесконечному циклу.
Когда проверки целостности памяти включены, если генератор кода обнаруживает, что индекс цикла может переполниться, он сообщает об ошибке. Проверка ошибок программного обеспечения является консервативной. Он может неправильно сообщить о переполнении индекса цикла. По умолчанию проверки целостности памяти включены для кода MEX и отключены для автономного кода C/C + +. Смотрите раздел Зачем тестировать функции MEX в MATLAB? (Кодер MATLAB) и Создание автономного кода C/C + +, который обнаруживает и сообщает об ошибках времени выполнения (кодер MATLAB).
Чтобы избежать переполнения индекса цикла, используйте обходные пути в этой таблице.
| Условия цикла, вызывающие потенциальное переполнение | Работа |
|---|---|
| Если цикл не должен охватывать весь диапазон целочисленного типа, перезаписайте цикл так, чтобы конечное значение не было равно максимальному значению целочисленного типа. Например, замените: N=intmax('int16')
for k=N-10:Nfor k=1:10 |
| Если цикл не должен охватывать весь диапазон целочисленного типа, перезаписайте цикл так, чтобы конечное значение не было равно минимальному значению целочисленного типа. Например, замените: N=intmin('int32')
for k=N+10:-1:Nfor k=10:-1:1 |
| Если цикл должен охватывать весь диапазон целочисленного типа, приведите тип начального, шагового и конечного значений цикла к большему целочисленному или двойному. Например, переписать: M= intmin('int16');
N= intmax('int16');
for k=M:N
% Loop body
endM= intmin('int16');
N= intmax('int16');
for k=int32(M):int32(N)
% Loop body
end |
| Перезаписать цикл таким образом, чтобы индекс цикла в последней итерации цикла был равен конечному значению. |
for Петли с помощью операндов с одной точностьюПредположим, что в коде MATLABcode выполняется индексация for цикл, имеющий оператор двоеточия, где по крайней мере один из операндов двоеточия является однотипным операндом и число итераций больше, чем flintmax('single') = 16777216. Если все эти условия верны, генерация кода может привести к ошибкам времени выполнения или компиляции, поскольку созданный код вычисляет значения переменной индекса цикла, отличные от значений, которые вычисляет MATLAB.
Например, рассмотрим этот код MATLAB:
function j = singlePIndex n = flintmax('single') + 2; j = single(0); for i = single(1):single(n) j = i; end end
Этот фрагмент кода выполняется в MATLAB, но он вызывает ошибку во время компиляции или выполнения, поскольку значение переменной индекса цикла, i, рассчитывается по-разному в сгенерированном коде. Генератор кода отображает ошибку времени компиляции или выполнения и останавливает создание или выполнение кода, чтобы предотвратить это расхождение.
Чтобы избежать этого несоответствия, замените однотипные операнды операндами двойного или целого типа.
Дополнительные сведения об ошибках времени выполнения см. в разделе Создание автономного кода C/C + +, который обнаруживает и сообщает об ошибках времени выполнения (кодер MATLAB).
for ПетляВ коде MATLAB и сгенерированном коде после for выполнение цикла завершено, значение индексной переменной равно ее значению во время окончательной итерации for цикл.
В MATLAB, если цикл не выполняется, значение индексной переменной сохраняется как [] (пустая матрица). В сгенерированном коде, если цикл не выполняется, значение индексной переменной отличается от значения индексной переменной MATLAB.
Если вы предоставляете for начальная и конечная переменные цикла во время выполнения, значение индексной переменной равно началу диапазона. Например, рассмотрим этот код MATLAB:
function out = indexTest(a,b) for i = a:b end out = i; end
Предположим, что a и b передаются как 1 и -1. for цикл не выполняется. В MATLAB, out назначается []. В созданном коде out присваивается значение a, что является 1.
Если вы предоставляете for начальное и конечное значения цикла перед временем компиляции, значение индексной переменной равно 0. Рассмотрим этот код MATLAB:
function out = indexTest for i = 1:-1 end out = i; end
Предположим, что вы называете эту функцию. В MATLAB, out назначается []. В созданном коде out присваивается значение 0.
MATLAB поддерживает 16-битные символы, но сгенерированный код представляет символы в 8 битах, стандартный размер для большинства встраиваемых языков, таких как C. См. раздел Кодирование символов при создании кода.
Созданный код не обеспечивает порядок вычисления в выражениях. Для большинства выражений порядок вычисления несущественен. Для выражений, имеющих побочные эффекты, созданный код может создавать побочные эффекты в порядке, отличном от исходного кода MATLAB. Выражения, которые вызывают побочные эффекты, включают в себя те, которые:
Изменение постоянных или глобальных переменных
Просмотр данных на экране
Запись данных в файлы
Изменение свойств объектов класса дескрипторов
Кроме того, сгенерированный код не обеспечивает порядок оценки логических операторов, которые не имеют короткого замыкания.
Для более предсказуемых результатов рекомендуется разбивать выражения, зависящие от порядка вычисления, на несколько операторов.
Переписать
A = f1() + f2();
как
A = f1(); A = A + f2();
чтобы сгенерированный код вызывал f1 прежде f2.
Назначьте выходы вызова функции с несколькими выходами переменным, которые не зависят друг от друга. Например, переписать
[y, y.f, y.g] = foo;
как
[y, a, b] = foo; y.f = a; y.g = b;
При доступе к содержимому нескольких ячеек массива ячеек назначьте результаты переменным, не зависящим друг от друга. Например, переписать
[y, y.f, y.g] = z{:};
как
[y, a, b] = z{:};
y.f = a;
y.g = b;
MATLAB и генерация кода следуют различным правилам приоритета для разрешения имен, следующих за символом @. Эти правила не применяются к анонимным функциям. Правила приоритета суммированы в этой таблице.
| Выражение | Порядок очередности в MATLAB | Порядок очередности при создании кода |
|---|---|---|
Выражение, не содержащее, например, точки @x | Вложенная функция, локальная функция, частная функция, функция тракта | Локальная переменная, вложенная функция, локальная функция, частная функция, функция тракта |
Выражение, содержащее, например, ровно один период @x.y | Локальная переменная, функция тракта | Локальная переменная, функция тракта (та же, что и MATLAB) |
Выражение, содержащее, например, несколько периодов @x.y.z | Функция тракта | Локальная переменная, функция тракта |
Если x - локальная переменная, которая сама является дескриптором функции, сгенерированный код и MATLAB интерпретируют выражение @x по-разному:
MATLAB выдает ошибку.
Сгенерированный код интерпретирует @x как функциональный дескриптор x сам.
Вот пример, показывающий эту разницу в поведении для выражения, которое содержит два периода.
Предположим, что текущая рабочая папка содержит пакет x, который содержит другой пакет y, который содержит функцию z. Текущая рабочая папка также содержит функцию точки входа foo для которого требуется создать код.

Это определение для файла foo:
function out = foo x.y.z = @()'x.y.z is an anonymous function'; out = g(x); end function out = g(x) f = @x.y.z; out = f(); end
Это определение функции z:
function out = z out = 'x.y.z is a package function'; end
Создание функции MEX для foo. Отдельно вызовите обе сгенерированные функции MEX. foo_mex и функцию MATLAB foo.
codegen foo
foo_mex
fooans =
'x.y.z is an anonymous function'
ans =
'x.y.z is a package function'Сгенерированный код создает первый выходной сигнал. MATLAB выдает второй выход. Создание кода разрешается @x.y.z к локальной переменной x которая определена в foo. MATLAB разрешает @x.y.z кому z, которая находится в пределах пакета x.y.
Созданный код не соответствует режиму завершения исходного кода MATLAB. Например, если бесконечные циклы не имеют побочных эффектов, оптимизации удаляют их из сгенерированного кода. В результате генерируемый код может завершаться даже при отсутствии соответствующего кода MATLAB.
Для массивов N-D переменного размера: size функция может возвращать результат, отличный от результата в исходном коде MATLAB. size функция иногда возвращает конечные единицы (одиночные измерения) в сгенерированном коде, но всегда сбрасывает конечные единицы в MATLAB. Например, для массива N-D X с размерами [4 2 1 1], size(X) может вернуться [4 2 1 1] в сгенерированном коде, но всегда возвращает [4 2] в MATLAB. См. раздел Несовместимость с MATLAB при определении размера массивов N-D переменного размера.
Размер пустого массива в созданном коде может отличаться от размера в исходном коде MATLAB. См. раздел Несовместимость с MATLAB при определении размера пустых массивов.
Удаление всех элементов массива приводит к появлению пустого массива. Размер этого пустого массива в созданном коде может отличаться от его размера в исходном коде MATLAB.
| Случай | Пример кода | Размер пустого массива в MATLAB | Размер пустого массива в сгенерированном коде |
|---|---|---|---|
Удалите все элементы массива m-by-n с помощью команды colon оператор (:). |
coder.varsize('X',[4,4],[1,1]);
X = zeros(2);
X(:) = [];
| 0-by-0 | 1-by-0 |
Удаление всех элементов вектора строки с помощью colon оператор (:). |
coder.varsize('X',[1,4],[0,1]);
X = zeros(1,4);
X(:) = []; | 0-by-0 | 1-by-0 |
Удаление всех элементов вектора столбца с помощью colon оператор (:). |
coder.varsize('X',[4,1],[1,0]);
X = zeros(4,1);
X(:) = []; | 0-by-0 | 0-by-1 |
| Удаление всех элементов вектора столбца путем одновременного удаления одного элемента. |
coder.varsize('X',[4,1],[1,0]); X = zeros(4,1); for i = 1:4 X(1)= []; end | 1-by-0 | 0-by-1 |
Если код MATLAB содержит операцию на основе двоичных элементов, которая включает операнд одного типа и операнд двойного типа, созданный код может привести к тому же результату, что и MATLAB.
Для такой операции MATLAB переводит оба операнда в двойной тип и выполняет операцию с двойными типами. Затем MATLAB приводит результат к одному типу и возвращает его.
Созданный код приводит операнд двойного типа к одному типу. Затем он выполняет операцию с двумя одиночными типами и возвращает результат.
Например, определите функцию MATLAB foo который вызывает операцию двоичного элемента plus.
function out = foo(a,b) out = a + b; end
Определение переменной s1 одного типа и переменной v1 двойного типа. Создание функции MEX для foo который принимает ввод одного типа и ввод двойного типа.
s1 = single(1.4e32); d1 = -5.305e+32; codegen foo -args {s1, d1}
Позвоните обоим foo и foo_mex с входами s1 и d1. Сравните два результата.
ml = foo(s1,d1); mlc = foo_mex(s1,d1); ml == mlc
ans = logical 0
Вывод сравнения является логическим 0, что указывает на то, что сгенерированный код и MATLAB дают различные результаты для этих входных данных.
Созданный код может не дать таких же числовых результатов с плавающей запятой, как MATLAB в следующих:
Когда компьютерное оборудование использует регистры расширенной точности
Сгенерированный код может не создать точно такой же шаблон NaN и Inf значения как код MATLAB, когда эти значения математически бессмысленны. Например, если выход MATLAB содержит NaN, выходные данные сгенерированного кода также должны содержать NaN, но не обязательно там же.
Битовый шаблон для NaN может отличаться между выводом кода MATLAB и выводом сгенерированного кода, поскольку стандартная математическая библиотека C99, используемая для генерации кода, не задает уникальный битовый шаблон для NaN во всех реализациях. Избегайте сравнения битовых шаблонов в различных реализациях, например, между выходом MATLAB и выходом SIL или PIL.
В типе с плавающей запятой значение 0 имеет либо положительный, либо отрицательный знак. Арифметически, 0 равно -0, но некоторые операции чувствительны к знаку входа 0. Примеры: rdivide, atan2, atan2d, и angle. Разделение по 0 производит Inf, но разделение на -0 производит -Inf. Аналогично, atan2d(0,-1) производит 180, но atan2d (-0,-1) производит -180.
Если генератор кода обнаруживает, что переменная с плавающей запятой принимает только целочисленные значения подходящего диапазона, то генератор кода может использовать целочисленный тип для переменной в сгенерированном коде. Если генератор кода использует целочисленный тип для переменной, то переменная сохраняет -0 как +0 потому что целочисленный тип не хранит знак для значения 0. Если созданный код возвращает переменную к типу с плавающей запятой, знак 0 является положительным. Разделение по 0 производит Inf, не -Inf. Аналогично, atan2d(0,-1) производит 180, не -180.
Существуют и другие контексты, в которых созданный код может обрабатывать -0 отличается от MATLAB. Например, предположим, что код MATLAB вычисляет минимум два скалярных дубля x и y с помощью z = min(x,y). Соответствующая строка в сгенерированном коде C может быть z = fmin(x,y). Функция fmin определяется в математической библиотеке среды выполнения компилятора C. Потому что операция сравнения 0.0 == -0.0 прибыль true в C/C + +, реализация компилятором fmin может вернуться либо 0.0 или -0.0 для fmin(0.0,-0.0).
coder.target функция возвращает значения в MATLAB, отличные от значений в сгенерированном коде. Цель состоит в том, чтобы помочь определить, выполняется ли функция в MATLAB или была скомпилирована для цели моделирования или генерации кода. Посмотрите coder.target.
Перед созданием кода во время загрузки класса MATLAB вычисляет значения класса по умолчанию. Генератор кода использует значения, вычисляемые MATLAB. Значения по умолчанию не пересчитываются. Если определение свойства использует вызов функции для вычисления начального значения, генератор кода не выполняет эту функцию. Если функция имеет побочные эффекты, такие как изменение глобальной переменной или постоянной переменной, то возможно, что созданный код может дать результаты, отличные от результатов MATLAB. Дополнительные сведения см. в разделе Определение свойств класса для создания кода.
При присвоении значения свойству объекта-дескриптора, которое само по себе является свойством другого объекта и т.д., созданный код может вызывать методы набора для классов-дескрипторов, которые MATLAB не вызывает.
Например, предположим, что вы определяете набор переменных, таких, что x является объектом-дескриптором, pa является объектом, pb является объектом-дескриптором и pc является свойством pb. Затем выполняется назначение вложенного свойства, например:
x.pa.pb.pc = 0;
В этом случае сгенерированный код вызывает метод set для объекта pb и метод установки для x. MATLAB вызывает только метод set для pb.
Поведение деструкторов класса дескрипторов в сгенерированном коде может отличаться от поведения в MATLAB в следующих ситуациях:
Порядок уничтожения нескольких независимых объектов в MATLAB может отличаться от порядка уничтожения в сгенерированном коде.
Время жизни объектов в сгенерированном коде может отличаться от времени жизни объектов в MATLAB.
Созданный код не уничтожает частично построенные объекты. Если объект дескриптора не полностью создан во время выполнения, генерируемый код выдает сообщение об ошибке, но не вызывает delete метод для этого объекта. Для системного object™, если имеется ошибка времени выполнения в setupImpl, сгенерированный код не вызывает releaseImpl для этого объекта.
MATLAB вызывает delete способ разрушения частично построенного объекта.
Дополнительные сведения см. в разделе Создание кода для дескрипторов деструкторов классов.
См. раздел Несовместимость с MATLAB в разделе Поддержка создания кода переменного размера.
См. раздел Создание кода для сложных данных.
doubleПреобразование строки, содержащей несколько последовательных унарных операторов, в double может давать различные результаты между MATLAB и сгенерированным кодом. Рассмотрим эту функцию:
function out = foo(op) out = double(op + 1); end
Для входного значения "--", функция преобразует строку "--1" кому double. В MATLAB ответ: NaN. В сгенерированном коде ответ: 1.