Open Source im professionellen Einsatz

© Visipix.com, Vortex study

GNU Compiler Collection 4.2

Schneller parallel?

,

Mit der Integration des OpenMP-Standards vereinfacht der GNU-Compiler ab Version 4.2 die Parallelprogrammierung in C, C++ und Fortran. Neue Optimierungen sollen übersetzte Programme beschleunigen. Ob der Plan aufgeht, verraten die Benchmarks.

Obwohl die GCC-Entwickler bis zur letzten Minute heftig diskutierten, ob überhaupt eine Version 4.2 erscheinen solle, ist es nun mit gewohnter Verspätung doch passiert: Eine neue Version des GNU-Compilers [1] ist auf dem freien Softwaremarkt und bringt eine Reihe kleiner, aber auch größerer Änderungen mit sich. Eine komplette Liste [2] findet sich auf der GCC-Homepage.

Die herausragende Neuerung ist die Unterstützung von OpenMP [3], eines offenen Standards zur Parallelisierung von Programmen, speziell für Computer mit Shared Memory. Sie erlaubt dem Programmierer anzugeben, wie Compiler und Laufzeitsystem Codepassagen auf mehrere Threads verteilen. Bisher war OpenMP nur in der Entwicklerversion vorhanden sowie im GCC 4.1 der Fedora-Distribution, deren Entwickler das Feature auf die alte Compiler-Version zurückportiert haben.

Die Implementierung von OpenMP in der neuen GCC-Version vereinfacht die parallele Programmierung auf den unterstützten Systemen. Entwickler können damit die eher komplizierte und fehleranfällige manuelle Anpassung ihres Quellcode an verschiedene, architekturabhängige APIs umgehen.

Pragmatisch parallelisieren

Die aktuelle GCC-Version unterstützt alle OpenMP-Funktionen. Schlüsselwörter bestimmen zur Übersetzungszeit, in welcher Form der Code parallel ablaufen soll. Durch so genannte Pragmas können auch solche Compiler den mit OpenMP ausgestatteten Code übersetzen, die von OpenMP keine Ahnung haben. Das vermeidet plattformabhängigen Code und undurchdringliche Ifdef-Dschungel. Das Schlüsselwort »#pragma omp ...« signalisiert dem Compiler, dass er den folgenden Block parallelisieren soll. Hinter den Kulissen erzeugt der GCC auf Unix-artigen Systemen wie Linux die Threads mit der Pthread-Bibliothek.

Da ein kürzlich erschienener Linux-Magazin-Artikel [4] OpenMP im Detail vorgestellt hat, bleiben an dieser Stelle nur kurz die Basisfunktionen zu beschreiben. Im einfachsten Fall werden Schleifen mit einem hinreichend großen Iterationsraum, für die es sich also lohnt, neue Threads zu erzeugen, markiert:

#pragma omp for
for(i = 0; i < N; i++)
  a[i] += b[i];

Die Kontrollmöglichkeiten bei OpenMP sind sehr umfassend. So ist es beispielsweise möglich, bei komplexeren Algorithmen anzugeben, dass ein Thread lokale Variablen verwendet, die das Programm erst am Ende summiert (so genannte Reduction):

#pragma omp parallel for private(w) reduction(+:sum) schedule(static,1)
for(i = 0; i < N; i++)
{
  w = i*i;
  sum = sum + w*a[i];
}

Eher zum Test als für konkrete Algorithmen lässt sich die Thread-ID ermitteln:

#pragma omp parallel private(id)
int id = omp_get_thread_num();
printf ("Dies ist Thread %dn", id);

Wegen der gewachsenen Modellvielfalt der x86-Prozessoren sind jetzt zwei weitere Architekturoptionen im x86-Backend enthalten. Die Architekturangabe »native« bewirkt, dass der GCC zur Compile-Zeit anhand der »cpuid«-Instruktion die für die vorhandene CPU beste Optimierung einsetzt. Das Schlüsselwort »generic« führt zu Programmen, die gleichermaßen gut auf AMD-, Intel- oder Via-CPUs laufen sollen.

Eine neue, mit der Option »-Waddress« zu aktivierende und in »-Wall« enthaltene Warnung macht auf typische Programmierfehler bei Vergleichen mit Funktionspointern und Adressen von String-Literalen aufmerksam. Die Option »-Wextra« warnt jetzt auch bei If-Ausdrücken mit einem direkt anschließenden Semikolon, um Tippfehler folgender Art zu erkennen:

if (a);
return 1;
return 0;

Die schon seit einiger Zeit ins Blickfeld der Entwickler geratene Startzeit von Programmen, gerade auch von C++-Code, insbesondere die Zeit, die der dynamische Linker zum Auflösen von Symbolen benötigt, kann der neue Compiler weiter reduzieren. So sind jetzt per Default mehr lokale Symbole unsichtbar; »visibility«-Attribute überträgt der Compiler nun auch automatisch von Klassen auf ihre Member und von Funktionen auf statische lokale Variablen.

Für Code, beispielsweise Inline-Assembler, der sich auf eine bestimmte Reihenfolge des Code verlässt, ist es jetzt möglich, mit der Option »-fno-toplevel-reorder« Funktion und Variablen in der Reihenfolge der Quellcode-Dateien auszugeben. Zu beachten ist, dass ab Optimierungsstufe »-O2« neue Overflow-Optimierungen stattfinden. So nimmt der neue Compiler für eine Schleife wie »for (int i=1; i>0; i*=2)« an, dass kein Überlauf stattfindet, und optimiert sie zu einer Endlosschleife.

Neuer C++-Standard

Weiter vervollständigt haben die GCC-Entwickler die Unterstützung des neuen, noch in der Standardisierungsphase befindlichen C++-Standards 200x. So sind jetzt auch »<random>«, »<complex>« im TR1-Namespace zu finden. Ebenfalls aufgenommen haben sie Lock-freie Container-Templates, die im Google Summer of Code entstanden sind.

Erfreulich ist, dass die neue GCC-Version 4.2 offenbar kaum neue Fehler eingeführt hat. Bei einem kurzen Versuch, mit dem T2-Distributions-Build-Kit [5] ein ganzes System mit dem neuen Compiler zu übersetzen, sind lediglich zwei Fehler aufgefallen: Zum einen verbraucht die Übersetzung einige Dateien des Pakets Xorg-Server [6] sehr viel mehr Speicher, sodass der Kernel den Compiler auf Systemen mit weniger als 1 GByte Speicher beendet. Zum anderen benutzt OpenSSL Typecasts von Funktions-Pointern in einer vom C-Standard undefinierten Weise, was zu Abbrüchen des Programms zur Laufzeit führt [7].

Als Testrechner kam ein Intel Core 2 Duo mit 2 GHz und 1 GByte RAM zum Einsatz, dazu die aktuelle Version der Open Bench [8] sowie die GCC-Versionen 3.4, 4.0, 4.1 und 4.2. Die CPU arbeitete dafür im 64-Bit-Modus 64-Bit-Programme ab. Gemessen wurden die Zeiten des Übersetzungsvorgangs (Abbildung 2) und die Laufzeiten in Sekunden, speziell bei OpenSSL die Laufzeit pro Iteration in Millisekunden (Abbildung 1).

Abbildung 1: Die Benchmark-Ergebnisse für die Laufzeiten der Testprogramme zeigen: Der neue GNU-Compiler bringt keine besonderen Geschwindigkeitsvorteile.

Abbildung 1: Die Benchmark-Ergebnisse für die Laufzeiten der Testprogramme zeigen: Der neue GNU-Compiler bringt keine besonderen Geschwindigkeitsvorteile.

Abbildung 2: Die Übersetzungszeiten der Benchmark-Programme für die GNU-Compiler-Versionen von 3.4 bis 4.2: Die Optimierung dauert immer länger.

Abbildung 2: Die Übersetzungszeiten der Benchmark-Programme für die GNU-Compiler-Versionen von 3.4 bis 4.2: Die Optimierung dauert immer länger.

Auf den ersten Blick fällt auf, dass sich die Version 4.2 mehr Zeit für die Optimierung nimmt als ihre Vorgänger. Der Lohn ist eine etwas geringere Laufzeit auch bei einigen klassischen C-Programmen. Obwohl der Compiler mit den üblichen Optimierungen »-O2« und »-O3« deutlich langsamer geworden ist, kann der Benutzer bei der Software-Entwicklung mit »-O0« von einer schnelleren Übersetzung profitieren. Ein Blick in die Logdateien der Benchmark-Übersetzung verrät, dass der neue Compiler mehr Schleifen selbstständig vektorisiert, beispielsweise bei Gzip 14 Stück gegenüber GCC 4.1 mit zwölf.

Die Integration von OpenMP in GCC 4.2 erleichtert das Programmieren auf Mehrprozessorsystemen und lässt den freien Compiler mit der kommerziellen Konkurrenz gleichziehen. Kritisch zu betrachten ist allerdings der mit jeder Version wachsende Zeitaufwand der Optimierungsstufen des Compilers.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 3 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Als digitales Abo

Als PDF im Abo bestellen

comments powered by Disqus

Ausgabe 07/2013

Preis € 6,40

Insecurity Bulletin

Insecurity Bulletin

Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...

Linux-Magazin auf Facebook