Ограничения массива ячеек для генерации кода

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

Назначение элемента массива ячеек

Перед использованием элемента массива ячеек необходимо назначить все пути выполнения. Для примера:

function z = foo(n)
%#codegen
c = cell(1,3);
if n < 1
    c{2} = 1;
    
else
    c{2} = n;
end
z = c{2};
end

Генератор кода рассматривает передачу массива ячеек в функцию или возвращение его из функции как использование всех элементов массива ячеек. Поэтому, прежде чем вы передадите массив ячеек в функцию или вернете его из функции, необходимо назначить все его элементы. Например, следующий код не разрешен, потому что он не присваивает значение c{2} и c является выходным параметром функции.

function c = foo()
%#codegen
c = cell(1,3);
c{1} = 1;
c{3} = 3;
end

Присвоение значений элементам должно быть последовательным для всех путей выполнения. Следующий код не разрешен из-за y{2} является двойным на одном пути выполнения и char на другом пути выполнения.

function y = foo(n)
y = cell(1,3)
if n > 1;
    y{1} = 1
    y{2} = 2;
    y{3} = 3;
else
    y{1} = 10;
    y{2} = 'a';
    y{3} = 30;
end

Массивы ячеек переменного размера

  • coder.varsize не поддерживается для гетерогенных массивов ячеек.

  • Если вы используете cell функция для определения массива ячеек фиксированного размера, вы не можете использовать coder.varsize чтобы указать, что массив ячеек имеет переменный размер. Для примера этот код вызывает ошибку генерации кода из-за x = cell(1,3) делает x массив ячеек фиксированного размера 1 на 3.

    ...
    x = cell(1,3);           
    coder.varsize('x',[1 5])
    ...

    Вы можете использовать coder.varsize с массивом ячеек, который вы задаете при помощи фигурных скобок. Для примера:

    ...
    x = {1 2 3}; 
    coder.varsize('x',[1 5])
    ...

  • Чтобы создать массив ячеек переменного размера при помощи cell function, использовать этот шаблон кода:

    function mycell(n)
    %#codegen
    x = cell(1,n);   
    for i = 1:n
        x{i} = i;
    end
    end

    См. Определение массива ячеек переменного размера при помощи камеры.

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

    function mycell(n)
    %#codegen
    x = cell(1,n);   
    for i = 1:n
        x{i} = i;
    coder.varsize('x',[1,20]);
    end
    end

Определение массива ячеек переменного размера при помощи cell

Для генерации кода, прежде чем вы используете элемент массива ячеек, вы должны назначить ему значение. Когда вы используете cell чтобы создать массив ячеек переменного размера, например cell(1,n)MATLAB присваивает пустую матрицу каждому элементу. Однако для генерации кода элементы не назначены. Для генерации кода, после того, как вы используете cell чтобы создать массив ячеек переменного размера, необходимо назначить все элементы массива ячеек перед любым использованием массива ячеек. Для примера:

function z = mycell(n, j)
%#codegen
x = cell(1,n);   
for i = 1:n
    x{i} = i;
end
z = x{j};
end

Генератор кода анализирует ваш код, чтобы определить, назначены ли все элементы перед первым использованием массива ячеек. Если генератор кода обнаруживает, что некоторые элементы не назначены, генерация кода прекращает работать с сообщением об ошибке. Например, измените верхнюю границу for-цикл, чтобы j.

function z = mycell(n, j)
%#codegen
x = cell(1,n);   
for i = 1:j %<- Modified here
    x{i} = i;
end
z = x{j};
end

С этой модификацией и с входами j меньше nфункция не присваивает значения всем элементам массива ячеек. Генерация кода приводит к ошибке:

Unable to determine that every element of 'x{:}' is assigned
before this line.

Иногда, даже если ваш код присваивает все элементы массива ячеек, генератор кода сообщает об этом сообщении, потому что анализ не обнаруживает, что все элементы назначены. См. «Не удается определить, что каждый элемент массива ячеек назначен».

Чтобы избежать этой ошибки, следуйте следующим рекомендациям:

  • Когда вы используете cell Чтобы задать массив ячеек переменного размера, запишите код, который следует этому шаблону:

    function z = mycell(n, j)
    %#codegen
    x = cell(1,n);   
    for i = 1:n
        x{i} = i;
    end
    z = x{j};
    end
    

    Вот шаблон для многомерного массива ячеек:

    function z = mycell(m,n,p)
    %#codegen
    x = cell(m,n,p);
    for i = 1:m
        for j =1:n
            for k = 1:p
                x{i,j,k} = i+j+k;
            end
        end
    end
    z = x{m,n,p};
    end

  • Увеличьте или уменьшите счетчик цикла на 1.

  • Задайте массив ячеек в одном цикле или в одном наборе вложенных циклов. Для примера этот код не разрешен:

    function z = mycell(n, j)
    x = cell(1,n);
    for i = 1:5
        x{i} = 5;
    end
    for i = 6:n
        x{i} = 5;
    end
    z = x{j};
    end            

  • Используйте те же переменные для размерностей камер и начальных и конечных значений цикла. Для примера генерация кода прекращается для следующего кода, потому что создание камеры использует n и значение конца цикла использует m:

    function z = mycell(n, j)
    x = cell(1,n);
    m = n;
    for i = 1:m
        x{i} = 2;
    end
    z = x{j};
    end               

    Перепишите код для использования n для создания камеры и конечного значения цикла:

    function z = mycell(n, j)
    x = cell(1,n);
    for i = 1:n
        x{i} = 2;
    end
    z = x{j};
    end

  • Создайте массив ячеек с таким шаблоном:

    x = cell(1,n)

    Не присваивайте массив ячеек полю структуры или свойству объекта. Для примера этот код не разрешен:

    myobj.prop = cell(1,n)
    for i = 1:n
    ...
    end
    

    Не используйте cell функция внутри конструктора массива ячеек {}. Для примера этот код не разрешен:

    x = {cell(1,n)};

  • Создание массива ячеек и цикл, который присваивает значения элементам массива ячеек, должны быть вместе в уникальном пути выполнения. Для примера следующий код не разрешен.

    function z = mycell(n)
    if n > 3
        c = cell(1,n);
    else
        c = cell(n,1);
    end
    for i = 1:n
        c{i} = i;
    end
    z = c{n};
    end

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

    function z = cellerr(n)
    if n > 3
        c = cell( 1,n);
        for i = 1:n
            c{i} = i;
        end
    else
        c = cell(n,1);
        for i = 1:n
            c{i} = i;
        end
    end
    z = c{n};
    end

Индексация массива ячеек

  • Вы не можете индексировать массивы ячеек с помощью сглаженных круглых скобок (). Рассмотрите индексацию массивов ячеек при помощи фигурных скобок {} для доступа к содержимому камеры.

  • Вы должны индексировать в гетерогенные массивы ячеек с помощью постоянных индексов или с помощью for- циклы с постоянными границами.

    Для примера следующий код не разрешен.

    x = {1, 'mytext'};
    disp(x{randi});

    Можно индексировать в гетерогенный массив ячеек в for-loop с постоянными границами, потому что генератор кода разворачивает цикл. Unrolling создает отдельную копию тела цикла для каждой итерации цикла, что делает индекс в каждой итерации цикла постоянным. Однако, если for-цикл имеет большое тело или у него много итераций, развертывание может увеличить время компиляции и сгенерировать неэффективный код.

    Если A и B являются постоянными, следующий код показывает индексацию в гетерогенный массив ячеек в for-цикл с постоянными границами.

    x = {1, 'mytext'};
    for i = A:B
    	 disp(x{i});
    end

Выращивание массива ячеек при помощи {end + 1}

Чтобы вырастить массив ячеек X, можно использовать X{end + 1}. Для примера:

...
X = {1 2};
X{end + 1} = 'a';
...

Когда вы используете {end + 1} чтобы вырастить массив ячеек, следуйте следующим ограничениям:

  • Используйте только {end + 1}. Не используйте {end + 2}, {end + 3}и так далее.

  • Использование {end + 1} только с векторами. Например, следующий код не разрешен, потому что X является матрицей, а не вектором:

    ...
    X = {1 2; 3 4};
    X{end + 1} = 5;
    
    ...

  • Использование {end + 1} только с переменной. В следующем коде {end + 1} не вызывает {1 2 3} расти. В этом случае генератор кода обрабатывает {end + 1} как выходной индекс в X{2}.

    ...
    X = {'a' { 1 2 3 }};
    X{2}{end + 1} = 4;
    ...

  • Когда {end + 1} выращивает массив ячеек в цикле, массив ячеек должен иметь переменный размер. Поэтому массив ячеек должен быть однородным.

    Этот код разрешен, потому что X однороден.

    ...
    X = {1  2};
    for i=1:n
        X{end + 1} = 3;
    end
    ...

    Этот код не разрешен, так как X неоднороден.

    ...
    X = {1 'a' 2 'b'};
    for i=1:n
        X{end + 1} = 3;
    end
    ...

Содержимое массива ячеек

Массивы ячеек не могут содержать mxarrays. В массиве ячеек вы не можете хранить значение, которое возвращает внешняя функция.

Передача массивов ячеек во внешние функции C/C + +

Вы не можете передать массив ячеек в coder.ceval. Если переменная является входным параметром на coder.ceval, задайте переменную как массив или структуру, а не как массив ячеек.

Похожие темы