Различия между сгенерированным кодом и кодом MATLAB

Чтобы преобразовать код MATLAB® в эффективный код C/C++, генератор кода вводит оптимизацию, которая намеренно заставляет сгенерированный код вести себя по-другому, и иногда приводит к различным результатам, чем код первоисточника.

Вот некоторые различия:

Переполнение индекса цикла

Предположим что for- значение конца цикла равно или близко к максимальному или минимальному значению для типа данных индекса цикла. В сгенерированном коде последний шаг или декремент индекса цикла могут заставить индексную переменную переполняться. Переполнение индекса может привести к бесконечному циклу.

Когда проверки целостности памяти включены, если генератор кода обнаруживает, что индекс цикла может переполниться, это сообщает об ошибке. Проверка программной ошибки консервативна. Это может неправильно сообщить о переполнении индекса цикла. По умолчанию проверки целостности памяти включены для кода MEX и отключены для автономного кода C/C++. Видеть Почему Тестовые MEX-функции в MATLAB? (MATLAB Coder) и Обнаружение Ошибки времени выполнения и Сообщающий в Автономном Коде C/C++ (MATLAB Coder).

Чтобы избежать переполнения индекса цикла, используйте обходные решения в этой таблице.

Условия цикла, вызывающие потенциальное переполнениеРабота вокруг
  • Индекс цикла постепенно увеличивается 1.

  • Значение конца равняется максимальному значению целочисленного типа.

Если цикл не должен покрывать полный спектр целочисленного типа, переписать цикл так, чтобы значение конца не было равно максимальному значению целочисленного типа. Например, замена:

N=intmax('int16')
for k=N-10:N
с:
for k=1:10

  • Индекс цикла постепенно уменьшается 1.

  • Значение конца равняется минимальному значению целочисленного типа.

Если цикл не должен покрывать полный спектр целочисленного типа, переписать цикл так, чтобы значение конца не было равно минимальному значению целочисленного типа. Например, замена:

N=intmin('int32')
for k=N+10:-1:N
с:
for k=10:-1: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

  • Шаг индекса цикла или декременты значением не равняются 1.

  • На последней итерации цикла индекс цикла не равен в конец значение.

Перепишите цикл так, чтобы индекс цикла в последней итерации цикла был равен в конец значение.

Размер символа

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 не делает.

Размер массивов Переменного Размера N-D

Для переменного размера массивы 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-01-by-0
Удалите все элементы вектора-строки при помощи colon оператор:).
coder.varsize('X',[1,4],[0,1]);
X = zeros(1,4);
X(:) = [];
0-by-01-by-0
Удалите все элементы вектор-столбца при помощи colon оператор:).
coder.varsize('X',[4,1],[1,0]);
X = zeros(4,1);
X(:) = [];
0-by-00-by-1
Удалите все элементы вектор-столбца путем удаления одного элемента за один раз.
coder.varsize('X',[4,1],[1,0]);
X = zeros(4,1);
for i = 1:4
    X(1)= [];
end
1-by-00-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 в них:

 Когда компьютерное оборудование использует регистры расширенной точности

 Для определенных усовершенствованных библиотечных функций

 Для реализации библиотечных функций BLAS

NaN и бесконечность

Сгенерированный код не может произвести точно тот же шаблон NaN и Inf значения как код MATLAB, когда эти значения математически бессмысленны. Например, если MATLAB вывел, содержит NaN, выход от сгенерированного кода должен также содержать NaN, но не обязательно в том же месте.

Комбинация двоичных разрядов для NaN может отличаться между кодом MATLAB выход и сгенерированным кодом выход, потому что стандартная математическая библиотека C99, которой пользуются, чтобы сгенерировать код, не задает уникальную комбинацию двоичных разрядов для NaN через все реализации. Постарайтесь не сравнивать комбинации двоичных разрядов через различные реализации, например, между MATLAB выход и SIL или PIL выход.

Отрицательный нуль

В типе с плавающей точкой, значение 0 имеет или положительный знак или знак минус. Арифметически, 0 равно -0, но некоторые операции чувствительны к знаку 0 входов. Примеры включают rdivideatan2atan2d, и 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. Это не повторно вычисляет значения по умолчанию. Если определение свойства использует вызов функции вычислить начальное значение, генератор кода не выполняет эту функцию. Если функция имеет побочные эффекты, такие как изменение глобальной переменной или персистентной переменной, то возможно, что сгенерированный код может привести к различным результатам, к которым приводит MATLAB. Для получения дополнительной информации смотрите Defining Class Properties для Генерации кода.

Методы доступа к свойствам класса MATLAB, которые изменяют значения свойств

При использовании объектов с методами доступа свойства результаты симуляции могут отличаться от результатов MATLAB. Эти различия происходят, когда объекты:

  • Введите к или выведите от функции точки входа.

  • Пройден к или возвратился из внешней функции.

  • Загруженный в память при помощи load.

Результаты могут отличаться при этих условиях:

  • Получить метод возвращает различное значение от сохраненного значения свойства.

  • Метод установки изменяет входное значение прежде, чем присвоить его свойству.

  • Получить метод или метод установки имеют побочные эффекты, такие как изменение глобальной переменной или запись в файл.

Результаты могут отличаться из-за несоответствий в использовании методов доступа свойства, когда MATLAB и передача программного обеспечения симуляции возражают друг против друга:

  • Если вы возвращаете объект во внешнюю функцию, MATLAB передает объект программному обеспечению симуляции. Программное обеспечение симуляции создает свою собственную версию объекта. Чтобы предоставить значения свойств процессу создания объекта, вызовы MATLAB получают методы. Процесс создания объекта присваивает эти значения свойств из MATLAB непосредственно к новому объекту, не вызывая методы установки.

  • Когда вы передаете объект внешней функции для выполнения в MATLAB, программное обеспечение симуляции передает объект MATLAB. MATLAB создает свою собственную версию объекта. Чтобы предоставить значения свойств MATLAB, вместо использования получают методы, программное обеспечение симуляции непосредственно читает значения свойств. Чтобы присвоить значения свойств в версии MATLAB объекта, процесс создания использует методы установки.

Чтобы избежать различий в результатах между MATLAB и симуляцией, не используйте классы с методами доступа свойства в этих случаях.

Для получения дополнительной информации смотрите Defining Class Properties для Генерации кода.

Классы MATLAB во вложенных присвоениях свойства, которые имеют методы установки

Когда вы присваиваете значение свойству объекта указателя, которое является самостоятельно свойством другого объекта, и так далее, затем сгенерированный код может вызвать методы установки для классов Handle, которые не вызывает MATLAB.

Например, предположите, что вы задаете набор переменных, таким образом что x объект указателя, pa объект, pb объект указателя и pc свойство pb. Затем вы делаете вложенное присвоение свойства, такое как:

x.pa.pb.pc = 0;

В этом случае сгенерированный код вызывает метод установки для объекта pb и метод установки для x. MATLAB вызывает только метод установки для pb.

Деструкторы класса Handle MATLAB

Поведение деструкторов класса 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.