Чтобы преобразовать код MATLAB® в эффективный код C/C++, генератор кода вводит оптимизацию, которая намеренно заставляет сгенерированный код вести себя по-другому, и иногда приводит к различным результатам, чем код первоисточника.
Вот некоторые различия:
Функции, которые имеют Несколько Возможных Выходных параметров
Размер пустого массива, который следует из удаления элементов массива
Бинарные поэлементные операции с одним и двойными операндами
Классы MATLAB во вложенных присвоениях свойства, которые имеют методы установки
Преобразование Строк с Последовательными Унарными операторами, чтобы удвоиться
Когда вы запускаете свою программу, проверки ошибки времени выполнения могут обнаружить некоторые из этих различий. По умолчанию проверки ошибки времени выполнения включены для кода MEX и отключены для автономного кода C/C++. Чтобы помочь вам идентифицировать и обратиться к различиям прежде чем, вы развертываете код, генератор кода сообщает о подмножестве различий как разности потенциалов.
Определенные математические операции, такие как сингулярное разложение и разложение собственного значения матрицы, могут иметь несколько ответов. Два различных алгоритма, реализующие такую операцию, могут возвратить различные выходные параметры для идентичных входных значений. Две различных реализации того же алгоритма могут также предоставить то же поведение.
Для таких математических операций соответствующие функции в сгенерированном коде и 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
функция вызвана, и строка отображена в командной строке.
Предположим это a for
- значение конца цикла равно или близко к максимальному или минимальному значению для типа данных индекса цикла. В сгенерированном коде последний шаг или декремент индекса цикла могут заставить индексную переменную переполняться. Переполнение индекса может привести к бесконечному циклу.
Когда проверки целостности памяти включены, если генератор кода обнаруживает, что индекс цикла может переполниться, это сообщает об ошибке. Проверка программной ошибки консервативна. Это может неправильно сообщить о переполнении индекса цикла. По умолчанию проверки целостности памяти включены для кода MEX и отключены для автономного кода C/C++. Видеть Зачем тестировать MEX-функции в MATLAB? и Обнаружение Ошибки времени выполнения и Сообщающий в Автономном Коде C/C++.
Чтобы избежать переполнения индекса цикла, используйте обходные решения в этой таблице.
Условия цикла, вызывающие потенциальное переполнение | Работа вокруг |
---|---|
| Если цикл не должен покрывать полный спектр целочисленного типа, переписать цикл так, чтобы значение конца не было равно максимальному значению целочисленного типа. Например, замена: 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
ЦиклВ вашем коде 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. Выражения, которые производят побочные эффекты, включают тех который:
Измените персистентные или глобальные переменные
Отобразите данные на экран
Запишите данные к файлам
Измените свойства объектов класса 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 | Функция пути | Локальная переменная, функция пути |
Если 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
.
coder.target
функция возвращает различные значения в MATLAB, чем в сгенерированном коде. Намерение состоит в том, чтобы помочь вам определить, выполняется ли ваша функция в MATLAB или была скомпилирована для цели генерации кода или симуляции. Смотрите coder.target
.
Перед генерацией кода, во время загрузки класса, MATLAB вычисляет значения по умолчанию класса. Генератор кода использует значения, которые вычисляет MATLAB. Это не повторно вычисляет значения по умолчанию. Если определение свойства использует вызов функции вычислить начальное значение, генератор кода не выполняет эту функцию. Если функция имеет побочные эффекты, такие как изменение глобальной переменной или персистентной переменной, то возможно, что сгенерированный код может привести к различным результатам, к которым приводит MATLAB. Для получения дополнительной информации смотрите Defining Class Properties для Генерации кода.
Когда вы присваиваете значение свойству объекта указателя, которое является самостоятельно свойством другого объекта, и так далее, затем сгенерированный код может вызвать методы установки для классов Handle, которые не вызывает MATLAB.
Например, предположите, что вы задаете набор переменных, таким образом что x
объект указателя, pa
объект, pb
объект указателя и pc
свойство pb
. Затем вы делаете вложенное присвоение свойства, такое как:
x.pa.pb.pc = 0;
В этом случае сгенерированный код вызывает метод установки для объекта pb
и метод установки для x
. MATLAB вызывает только метод установки для 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
.