gcc compilation sehr langsam (große Datei)

7

Ich versuche eine große c-Datei zu kompilieren (speziell für MATLAB-Mexing). Die c-Datei ist ungefähr 20MB (verfügbar vom GCC-Bug-Tracker , wenn Sie damit spielen möchten es).

Hier ist der Befehl, den ich ausführe und die Ausgabe, um unten zu screenen. Dies läuft seit Stunden, und wie Sie sehen können, ist die Optimierung bereits deaktiviert (-O0). Warum ist das so langsam? Kann ich das schneller machen?

(Als Referenz: Ubuntu 12.04 64 bit, gcc 4.7.3)

%Vor%

EDIT: ein Follow-on: Ich folgte chqrlies Ratschlag und tcc kompilierte meine Funktion in & lt; 5 Sekunden (ich musste nur die -ansi-Flagge entfernen und "gcc" in "tcc" umwandeln), was ziemlich bemerkenswert ist, Ja wirklich. Ich kann mir nur die Komplexität von gcc vorstellen.

Beim Versuch, es dann zu ändern, gibt es jedoch einen anderen Befehl, den mex normalerweise braucht. Der zweite Befehl lautet typischerweise:

%Vor%

Ich kann das nicht mit tcc ausführen, da einige dieser Flags nicht kompatibel sind. Wenn ich versuche, diesen zweiten Übersetzungsschritt mit gcc auszuführen, bekomme ich:

%Vor%

EDIT: Die Lösung scheint zu klingeln. tcc kann die Datei kompilieren, aber die Argumente im zweiten Schritt in mexing sind nicht mit den Argumentoptionen von tcc kompatibel. Clang ist sehr schnell und erzeugt eine nette, kleine, optimierte Datei.

    
user650261 30.10.2015, 19:34
quelle

3 Antworten

11

Beim Testen habe ich festgestellt, dass der Clang-Compiler weniger Probleme beim Kompilieren großer Dateien hat. Obwohl Clang während der Kompilierung fast ein Gigabyte Speicher benötigte, verwandelte es das Quellcodeformular von OP erfolgreich in eine 70 kB-Objektdatei. Dies funktioniert für alle Optimierungsstufen, die ich getestet habe.

gcc war auch in der Lage, diese Datei schnell und ohne zu viel Speicher zu kompilieren, wenn die Optimierung aktiviert ist. Dieser Fehler im gcc stammt von dem großen Ausdruck im OP-Code, der das Register sehr belastet Zuweiser. Wenn Optimierungen aktiviert sind, führt der Compiler eine Optimierung namens gemeinsame Teilausblendung durch, die eine Menge Redundanz aus dem OP-Code entfernen kann, wodurch sowohl die Kompilierungszeit als auch die Größe der Objektdatei auf verwaltbare Werte reduziert werden.

Hier sind einige Tests mit dem Testfall aus dem oben genannten Fehlerbericht:

%Vor%

Dies ist die resultierende Größe der Objektdatei:

%Vor%     
fuz 31.10.2015, 20:27
quelle
15

Fast die gesamte Datei ist ein Ausdruck, die Zuordnung zu double f[24] = ... . Das wird eine gigantische abstrakte Syntaxbaumstruktur erzeugen. Ich wäre überrascht, wenn alles außer einem spezialisierten Compiler dies effizient bewältigen könnte.

Die 20-Megabyte-Datei selbst mag in Ordnung sein, aber der eine riesige Ausdruck mag das sein, was das Problem verursacht. Versuchen Sie als vorbereitenden Schritt, die Zeile in double f[24] = {0} und dann 24 Zuweisungen von f[0] = ...; f[1] = ... aufzuteilen und zu sehen, was passiert. Im schlimmsten Fall können Sie die 24 Zuweisungen in 24 Funktionen aufteilen, jede in ihrer eigenen .c -Datei, und sie separat kompilieren. Dies wird die Größe des AST nicht reduzieren, es wird es nur reorganisieren, aber GCC ist wahrscheinlich besser im Umgang mit vielen Anweisungen, die zusammen viel Code ergeben, im Gegensatz zu einem riesigen Ausdruck.

Der ultimative Ansatz wäre, den Code auf eine optimierte Weise zu generieren. Wenn ich zum Beispiel nach s4*s5*s6 suche, bekomme ich 77.783 Treffer. Diese s[4-6] Variablen ändern sich nicht. Sie sollten eine temporäre Variable, double _tmp1 = s4*s5*s6; , generieren und diese dann verwenden, anstatt den Ausdruck zu wiederholen. Sie haben gerade 311.132 Knoten aus Ihrem abstrakten Syntaxbaum entfernt (vorausgesetzt, s4*s5*s6 ist 5 Knoten und _tmp1 ist ein Knoten). Das ist viel weniger, was GCC zu tun hat. Dies sollte auch schneller Code generieren (Sie werden nicht die gleiche Multiplikation 77,783 mal wiederholen).

Wenn Sie dies auf eine clevere Weise rekursiv tun (zB s4*s5*s6 - & gt; _tmp1 , (c4*c6+s4*s5*s6) - & gt; (c4*c6+_tmp1) - & gt; _tmp2 , c5*s6*(c4*c6+s4*s5*s6) - - & gt; c5*s6*_tmp2 - & gt; _tmp3 , etc ...), Sie können wahrscheinlich den größten Teil des generierten Codes eliminieren.

    
Claudiu 30.10.2015 20:03
quelle
6

Probiere Fabrice Bellards winzigen C-Compiler tcc von Ссылка aus:

%Vor%

Ja, das sind 1,336 Sekunden auf einem ziemlich einfachen PC!

Natürlich kann ich die resultierende ausführbare Datei nicht testen, aber die Objektdatei sollte mit dem Rest Ihres Programms und Ihrer Bibliotheken verlinkt sein können.

Für diesen Test habe ich eine Dummy-Version der Datei mex.h :

verwendet %Vor%

gcc hat das Kompilieren noch nicht beendet ...

EDIT: gcc hat es geschafft, meine Linux Box so schlecht zu hoggen, dass ich keine Verbindung mehr herstellen kann: (

    
chqrlie 30.10.2015 21:06
quelle

Tags und Links