2015-11-26 24 views
11

Quando si genera il codice C utilizzando il codificatore MATLAB, il comportamento è diverso quando un if si trova nel corpo di un altro if o nella sua sezione else. Il caso seguente crea facilmente il codice C con uscita con dimensioni 5x5:Come la generazione del codice MATLAB diminuisce le dimensioni di output con i rami nidificati

function y = foo1(u) 
if u > 0 
    y = zeros(2,2); 
else 
    y = zeros(5,5); 
end 

Ora questo funziona così

function y = foo2(u,v) 
if u > 0 
    y = zeros(2,2); 
else 
    y = zeros(5,5); 
    if v > 0 
     y = 2 * y; 
    end 
end 

Ma questo non riesce a generare il codice, lamentando non corrispondente dimensione:

function y = foo3(u,v) 
if u > 0 
    y = zeros(2,2); 
    if v > 0 
     y = 2 * y; 
    end 
else 
    y = zeros(5,5); 
end 

Qui è l'uscita in linea di comando:

>> codegen foo1.m -args {0} 
>> codegen foo2.m -args {0,0} 
>> codegen foo3.m -args {0,0} 
??? Size mismatch (size [2 x 2] ~= size [5 x 5]). 
The size to the left is the size of the left-hand side of the assignment. 

Error in ==> foo3 Line: 8 Column: 5 
Code generation failed: Open error report. 
Error using codegen (line 144) 

Ho visto questo comportamento in MATLAB R2013b e R2015a.

risposta

7

Da the docs, Matlab codegen deve conoscere la dimensione di una matrice in fase di compilazione menocodegen è detto o deduce che la matrice sia di dimensioni variabili. Ci sono diversi modi per far conoscere Matlab una matrice sarà di dimensioni variabili:

  1. Uso coder.varsize funzione, una matrice può essere esplicitamente dichiarato di essere di dimensioni variabili.
  2. MATLAB può dedurre una matrice di dimensioni variabili dalla struttura del codice.

Come suggerisce il codice, l'opzione (2) a quanto pare non è robusta. In alcuni casi Matlab cerca di inferire quando c'è una semplice dichiarazione else, ma quell'inferenza sembra essere piuttosto fragile, come mostrato dal tuo esempio.

Piuttosto che fare affidamento su MATLAB correttamente dedurre se una matrice è dimensione variabile, una soluzione è quella di fare una dichiarazione esplicita:

function y = foo3(u,v) 
    coder.varsize('y', []); % Let codegen know y is variable sized 
          % and can be arbitrary dimensions 
          % an alternative is: coder.varsize('y',[5,5]); 
    if u > 0 
    y = zeros(2,2); 
    if v > 0 
     y = 2 * y; 
    end 
    else 
    y = zeros(5,5); 
    end 

Perché potrebbe Matlab desiderare di conoscere queste informazioni? Se la dimensione di una matrice è nota al momento della compilazione, è possibile che siano possibili tutti i tipi di ottimizzazioni aggiuntive (ciclo di svolgimento ecc ...).

+1

Giusto per chiarire, poiché non è stato menzionato esplicitamente: 'coder.varsize ('y', [5,5])' specifica '[5 5]' come * limite superiore * per la dimensione variabile della matrice . È anche possibile specificare una o più dimensioni come fisse e altre come dimensioni variabili - questo e altro nella pagina della documentazione collegata nella risposta. – mikkola

+2

Vale la pena notare che nessuno degli esempi nell'OP è valido C. Le variabili dichiarate all'interno di un'istruzione if avranno un ambito separato in C. Poiché questo codice funziona in Matlab, si può sperare che il codificatore matlab sia in grado di risolverlo, ma non si può supporre questo. Direi che il problema in 'foo3' ha a che fare con che' y' è usato nell'istruzione if ('y = 2 * y') e quindi ridefinito nell'istruzione else, che è scritta in seguito nel testo. Penso che questo confonda il programmatore Matlab. Non sono del tutto sicuro però. – patrik

+0

@patrik, non è necessario che gli esempi siano validi C. Il lavoro di MATLAB Coder è di produrre C validi dal sottoinsieme del linguaggio MATLAB supportato per codegen. Detto questo, dichiarare le variabili MATLAB in primo piano, in modo simile allo stile C, può rendere il codice più facile da comprendere per Coder. –

2

Sono d'accordo con la risposta di Matteo Gunn, questo è quello di aggiungere qualche spiegazione per il comportamento. Un buon modello mentale su come Coder analizza il tuo codice MATLAB è che lo guarda dall'alto verso il basso.

Applicando questo modello mentale, nei vostri primi due esempi, le assegnazioni che determinano le dimensioni di y: y = zeros(2,2) e y = zeros(5,5), si verificano prima che il valore di y viene mai utilizzato. Quindi Coder può unire entrambe le dimensioni per rendere automaticamente y un array di dimensioni variabili. Nel terzo esempio, viene eseguita l'assegnazione y = zeros(2,2) e viene utilizzato : y = 2 * y. A questo punto, Coder deve determinare la dimensione e il tipo della moltiplicazione 2 * y. Viene visualizzato solo l'incarico 2-by-2, pertanto viene dedotto che 2 * y deve anche restituire una matrice 2-by-2.

esecuzione di questa inferenza quindi ingloba l'ipotesi che y è 2-by-2 nel codice ed essenzialmente blocca la dimensione y modo che la successiva assegnazione di y con una matrice 5-by-5 deve sicuro.