Для преобразования MATLAB® генератор кода вводит оптимизацию, которая намеренно заставляет сгенерированный код вести себя по-другому, и иногда приводит к другим результатам, чем исходный исходный код.
Вот некоторые из различий:
Индексация для циклов при помощи операндов с одной точностью (MATLAB Coder)
Индекс цикла Unentered for Loop (MATLAB Coder)
Размер пустого массива, который возникает в результате удаления элементов массива
Двоичные элементно-мудрые операции с одним и двумя операндами
Классы MATLAB в назначениях вложенных свойств, которые имеют установленные методы
Преобразование строк с последовательными унарными операторами в двойной точности
При запуске программы проверки ошибок времени выполнения могут обнаружить некоторые из этих различий. Чтобы помочь вам идентифицировать и устранить различия перед развертыванием кода, генератор кода сообщает подмножество различий как потенциальных различий.
Некоторые математические операции, такие как сингулярные разложения и разложение собственных значений матрицы, могут иметь несколько ответов. Два различных алгоритма, реализующих такую операцию, могут возвращать различные выходы для идентичных входных значений. Две различные реализации одного и того же алгоритма могут также демонстрировать одно и то же поведение.
Для таких математических операций соответствующие функции в сгенерированном коде и MATLAB могут возвращать различные выходы для идентичных входных значений. Чтобы увидеть, имеет ли функция такое поведение, на соответствующей странице с описанием функции, смотрите раздел C/C++ Code Generation под Extended Capabilities. Примеры таких функций включают 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 value равно или близко к максимальному или минимальному значению для типа индексных данных цикла. В сгенерированном коде последний шаг или уменьшение индекса цикла может привести к переполнению индексной переменной. Переполнение индекса может привести к бесконечному циклу.
Когда проверки целостности памяти включены, если генератор кода обнаруживает, что индекс цикла может переполниться, он сообщает об ошибке. Проверка программных ошибок является консервативной. Это может неправильно сообщить о переполнении индекса цикла. По умолчанию проверки целостности памяти включены для кода MEX и отключены для автономного кода C/C + +. Смотрите, зачем тестировать MEX-функции в MATLAB? (MATLAB Coder) и Сгенерируйте автономный код C/C + +, который обнаруживает и сообщает об ошибках времени выполнения (MATLAB Coder).
Чтобы избежать переполнения индекса цикла, используйте обходные пути в этой таблице.
Условия цикла, вызывающие потенциальное переполнение | Работа |
---|---|
| Если цикл не должен покрывать полную область значений целого типа, перепишите цикл так, чтобы конечное значение не равнялось максимальному значению целого типа. Для примера замените: N=intmax('int16') for k=N-10:N for k=1:10 |
| Если цикл не должен покрывать полную область значений целого типа, перепишите цикл так, чтобы конечное значение не равнялось минимальному значению целого типа. Для примера замените: N=intmin('int32') for k=N+10:-1:N for k=10:-1:1 |
| Если цикл должен охватывать всюсь область значений целого типа, приведите тип начального, шагового и конечного значений цикла к большему целому или к двойному. Для примера перепишите: M= intmin('int16'); N= intmax('int16'); for k=M:N % Loop body end M= 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 Coder).
for
ЦиклВ коде MATLAB и сгенерированном коде, после for
выполнение цикла завершено, значение индексной переменной равно ее значению во время окончательной итерации for
цикл.
В MATLAB, если цикл не выполняется, значение индексной переменной сохранено как [] (пустая матрица). В сгенерированном коде, если цикл не выполняется, значение индексной переменной отличается от индексной переменной.
Если вы предоставляете for
начальная и конечная переменные цикла во время исполнения, значение индексной переменной равно началу области значений. Для примера рассмотрим этот код MATLAB:
function out = indexTest(a,b) for i = a:b end out = i; end
Предположим, что a
и b
передаются как 1
и -1
. The 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 порядке. Выражения, которые вызывают побочные эффекты, включают те, которые:
Изменение стойких или глобальных переменных
Отображение данных на экране
Запись данных в файлы
Изменение свойств объектов класса handle
В сложение сгенерированный код не применяет порядок оценки логических операторов, которые не замыкаются.
Для более предсказуемых результатов рекомендуется разделить выражения, которые зависят от порядка оценки, на несколько операторов.
Переписать
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 | Функция Path | Локальная переменная, функция пути |
Если 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
foo
ans = '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-на-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. Для получения дополнительной информации смотрите Определение свойств класса для Генерации кода.
Когда вы присваиваете значение свойству указателя объекта, которое само является свойством другого объекта, и так далее, то сгенерированный код может вызвать методы set для классов handle, которые MATLAB не вызывает.
Например, предположим, что вы задаете набор переменных, таких что x
является указатели объекта, pa
является объектом, pb
является указатели объекта и pc
является свойством pb
. Затем вы делаете вложенное назначение свойств, такое как:
x.pa.pb.pc = 0;
В этом случае сгенерированный код вызывает метод set для объекта pb
и метод набора для x
. MATLAB вызывает только метод set для pb
.
Поведение деструкторов классов handle в сгенерированном коде может отличаться от поведения в MATLAB в таких ситуациях:
Порядок уничтожения нескольких независимых объектов может отличаться в MATLAB, чем в сгенерированном коде.
Время жизни объектов в сгенерированном коде может отличаться от времени их жизни в MATLAB.
Сгенерированный код не уничтожает частично построенные объекты. Если объект указатель не полностью построен во время исполнения, сгенерированный код выдает сообщение об ошибке, но не вызывает delete
метод для этого объекта. Для системного object™, если существует ошибка времени выполнения в setupImpl
сгенерированный код не вызывает releaseImpl
для этого объекта.
MATLAB вызывает delete
способ уничтожения частично построенного объекта.
Для получения дополнительной информации смотрите Генерацию кода для деструкторов классов Handle.
Смотрите Несовместимость с MATLAB в поддержке переменного размера для генерации кода.
Смотрите Генерацию кода для комплексных данных.
double
Преобразование строки, которая содержит несколько последовательных унарных операторов в double
может привести к различным результатам между MATLAB и сгенерированным кодом. Рассмотрим эту функцию:
function out = foo(op) out = double(op + 1); end
Для значения входа "--"
функция преобразует строку "--1"
на double
. В MATLAB ответ следующий NaN
. В сгенерированном коде ответ следующий 1
.