2012-10-18 5 views
7

Ich habe einige Matlab-Code, der viele Millionen Male wie in dieser Frage erwähnt: Matlab: Does calling the same mex function repeatedly from a loop incur too much overhead?C und Matlab: Warum wird diese eine Zeile in Matlab so viele Zeilen in C++ - Code, generiert von Matlab Coder?

Ich versuche, mex-ify es zu sehen, ob das hilft. Wenn ich jetzt Code aus dem Matlab-Code unter Verwendung des Matlab Coder-Tools erzeuge, ist der Code im Allgemeinen vernünftig, aber diese eine Zeile Matlab-Code (in einem C++ - Kommentar in der ersten Zeile) erzeugt diese Monstrosität, und ich habe keine Ahnung warum. Jede Hilfe beim Verstehen und Reduzieren ihrer Komplexität wäre willkommen.

Für den Kontext ist d eine zweidimensionale Matrix und s1 ist ein Zeilenvektor. s1_idx zugeordnet Länge sein (s1) + 1 in der vorangehenden C++ Code,

/* d(:, 1) = 0:length(s1); */ 
cdiff = s1_idx_0 - 1; 
for (nm1d2 = 0; nm1d2 <= cdiff; nm1d2++) { 
    tmp_data[nm1d2] = nm1d2; 
} 
ndbl = (int32_T)muDoubleScalarFloor((real_T)s1_sizes[1] + 0.5); 
apnd = ndbl; 
cdiff = ndbl - s1_sizes[1]; 
if (muDoubleScalarAbs((real_T)cdiff) < 4.4408920985006262E-16 * (real_T)s1_sizes[1]) { 
    ndbl++; 
    apnd = s1_sizes[1]; 
} else if (cdiff > 0) { 
    apnd = ndbl - 1; 
} else { 
    ndbl++; 
} 
if (ndbl > 0) { 
    b_tmp_data[0] = 0.0; 
    if (ndbl > 1) { 
     b_tmp_data[ndbl - 1] = (real_T)apnd; 
     nm1 = ndbl - 1; 
     nm1d2 = nm1; 
     nm1d2 = (int32_T)((uint32_T)nm1d2 >> 1); 
     for (cdiff = 1; cdiff <= nm1d2 - 1; cdiff++) { 
      b_tmp_data[cdiff] = (real_T)cdiff; 
      b_tmp_data[(ndbl - cdiff) - 1] = (real_T)(apnd - cdiff); 
     } 
     if (nm1d2 << 1 == nm1) { 
      b_tmp_data[nm1d2] = (real_T)apnd/2.0; 
     } else { 
      b_tmp_data[nm1d2] = (real_T)nm1d2; 
      b_tmp_data[nm1d2 + 1] = (real_T)(apnd - nm1d2); 
     } 
    } 
} 
cdiff = s1_idx_0 - 1; 
for (nm1d2 = 0; nm1d2 <= cdiff; nm1d2++) { 
    SD->f0.d_data[tmp_data[nm1d2]] = b_tmp_data[nm1d2]; 
} 
+2

Warum implementieren Sie es nicht in der mex-Datei selbst? Das scheint eine ziemlich einfache Funktion zu sein. Es scheint mir, dass MATLAB explizit die Indizes 'd (:, 1)' und den '1: length (s1)' Vektor erzeugt, um sie in der letzten Schleife 'SD-> f0.d_data = ...' in der Ende. Wenn das, was Sie berechnen, die erste kommentierte Zeile ist, können Sie alles in einer einzigen Schleife schreiben. – angainor

+1

Ich würde es gerne direkt in C++ machen, anstatt automatisch generierten Code zu vertrauen, aber ich tue dies für einen Kunden, der nur Matlab kennt und den Code selbst später pflegen möchte, nachdem unser Vertrag beendet wurde . Daher muss man sich auf Matlab Coder verlassen. – sundar

Antwort

4

Das ist ziemlich lustig generierten Code für das, was Sie eigentlich erreichen möchten. Sie wollen nur die ganzen Zahlen 0 bis k in ein Array stopfen. Aber der Code-Generator ist gebaut, um den allgemeinen Fall zu behandeln. Dem generierten Code sind also drei Teile zugeordnet:

  1. Erstellen Sie ein Array mit Indizes, die angeben, wo auf der linken Seite die Elemente von der rechten Seite angezeigt werden. Sie haben den Ausdruck : verwendet, aber Sie hätten etwas anderes verwenden können. Der Code-Generator muss so vorbereitet sein, dass Sie etwas wie tun können.
  2. Erstellen Sie ein Array von Werten für die rechte Seite.Sie tun nur sequenzielle Ganzzahlen, aber der Codegenerator ist darauf vorbereitet, mit Doppelbögen umzugehen, und wenn Sie Werte aus einer Reihe von Doppelbögen erstellen, können Sie lustige Rundungsprobleme haben. Es prüft auf alle Arten von Randfällen.
  3. Schließlich gibt es noch die Schleife, die tatsächlich die Werte auf der rechten Seite weist auf Speicherplätze auf der linken Seite, wie durch den 1.

In Ende in Schritt erstellten Array indiziert, könnte es sein, dass alles, was Sie brauchen, ist:

cdiff = s1_idx_0 - 1; 
for (nm1d2 = 0; nm1d2 <= cdiff; nm1d2++) { 
    SD->f0.d_data[nm1d2] = nm1d2; 
} 
+0

Ihre Erklärung half mir, den Code leichter durchzugehen, und ich verstehe jetzt, was vor sich geht. Vielen Dank! – sundar

2

MatLab ein Sonderfall ist, entworfen, um mit speziellen mathematischen Funktionen zu arbeiten. Sie erkennen, dass unter der Haube Zeug noch zu viel Maschinencode übersetzt wird, den Prozessor verstehen kann.

Es gibt viele Fragen zu SO, die dasselbe fragen: "Warum ist XX so einfach in Matlab und so schwer in C++?". Weil Matlab dafür entworfen wurde, während C++ eine allgemeine Sprache ist.

Matlab-Entwickler mussten diese großen Codeblätter schreiben, damit Sie diese Funktionalität mit nur einer Zeile nutzen können. C++ hat es nicht in der Standardbibliothek, daher müssen Sie es selbst erstellen.

Nun, nimm ein einfaches Beispiel. Angenommen, Benutzer A und B möchten eine quadratische Gleichung lösen. Benutzer A ist ein mathematisches Paket mit, und alles, was er zu tun hat, ist zu schreiben

FIND x IN 2x + 6x + 3 = 0

Benutzer B, auf der anderen Seite, ist mit C++, und er hat schreiben eine Funktion zum Zählen der Diskriminante, berechnen Sie die Werte (er muss natürlich auch über negative Diskriminante sorgen) und sie ausgeben, etwas, das die Entwickler des mathematischen Pakets bereits getan hatten Benutzer A. Das ist eine Menge Code wirklich, ein Beispiel, das ich schnell googelte.

Stellen Sie sich nun vor, Benutzer A sagt: "Hey, B, warum zur Hölle musst du so viel Code schreiben? Ich kann es in nur 1 Zeile tun!" Und das wird Ihr Fall sein;)

Vergessen Sie auch nicht, dass automatisch generierter Code nicht immer der beste Code ist, wenn Sie über Lesbarkeit und Verständlichkeit von Menschen sprechen.

+0

Während dies für eine beliebige Matlab-Anweisung und die entsprechende C++ - Version gelten würde, ist es in diesem speziellen Fall nur eine Array-Zuweisung und könnte leicht mit viel weniger Zeilen von C++ ausgeführt werden, wie @ JCooper's Antwort beschreibt. – sundar

1

ich bin zu spät zu dieser Party, aber die vorhandenen Antworten konzentrieren sich auf, warum es passiert ist und nicht diskutieren, was man dagegen tun kann.

Wenn Sie wissen, welche Zeile diesen seltsamen, unordentlich aussehenden C-Code verursacht, sollten Sie versuchen, diese Zeile zu ändern. Statt:

d(:, 1) = 0:length(s1); 

Eine Sache, um zu versuchen, ist die Abhängigkeit von variablen s1 Entfernung:

d(:, 1) = 0:size(d,1); 

Eine weitere Möglichkeit ist eine einfache Schleife zu schreiben, die fast direkt an C Hoffentlich codegen übersetzt werden können geben sehr ähnlicher und einfacher C-Code.

for i = 0:size(d,1) 
    d(i,1) = i; 
end