Im Test: Intels neue Compiler 9.0

05.07.2005 von THOMAS WOELFER  und Christian Vilsbeck
Intel bietet seine Compiler für C++ und Fortran in der neuen Version 9.0 an. Die Programmiertools sind optimiert für die Erstellung von „multi-threaded“ Applikationen. tecCHANNEL zeigt, wie es sich mit dem neuen Compiler arbeiten lässt.

Durch den zunehmenden Anteil von Multi-Core-Plattformen bieten Intels neue Compiler der Version 9.0 spezielle Funktionen zum einfacheren Programmieren von Multi-Thread-Anwendungen. Mit einer so genannten Auto-Parallelization-Funktion suchen die Compiler in Anwendungen automatisch nach Möglichkeiten, parallele Threads zu erzeugen.

Neben der speziellen Optimierung der Compiler für Multi-Core-Plattformen sollen die neuen 9.0er Versionen den Sicherheitsaspekt von Applikationen steigern. So reduzieren die Compiler bei den generierten Programmen die Verwundbarkeit durch Buffer Overflows. Laut Intel erzeugen die zusätzlichen Security Features nur einen geringen Overhead im Programmcode.

Intels Compiler für C++ und Fortran der Version 9.0 sind für Windows und Linux verfügbar. tecCHANNEL befasst sich mit dem C++-Compiler für Windows. Wie lässt es sich damit arbeiten und was gibt es bei der Integration in Microsofts Entwicklungsumgebungen zu beachten?

Installationshürden

Die Installation des Compilers erfolgt mit einem der üblichen Setup-Programme für Windows: Das extrahiert die etwa 250 MByte große komprimierte Datei und beginnt danach mit der eigentlichen Installation, indem das Setup-Programm eine lokale Webseite mit ersten Informationen über das Programm anzeigt.

Der Versuch, das Programm unter einem nicht administrativen Account zu installieren, schlägt fehl. Wie bei so vielen anderen Programmen erscheint eine unverständliche Fehlermeldung, der zufolge eine Datei nicht gefunden werden konnte.

Ist die administrative Hürde dann überwunden, kann die Installation einfach durchgeführt werden. Der C++-Compiler bietet zwei Versionen an: die eine ist für Intel-CPUs im Windows-Betrieb gedacht, das andere Kit versorgt Programmierer, die Microsofts eMbedded Visual C++ einsetzen.

Dabei kann man mit dem Windows-Kit nicht auf allen Plattformen auch Code für alle Plattformen generieren. Die folgenden Möglichkeiten sind gegeben:

Host-Systeme und darauf erzeugbarer Programmcode

Host

IA-32

EM64T

IA-64 Itanium

IA-32 Host

ja

ja

ja

Intel EM64T Host

nein

ja

nein

Intel Itanium Host

nein

nein

ja

Die Installation funktioniert unter Windows 2000, 2003 und XP, wobei sich der Compiler in eine der diversen IDEs von Microsoft integriert: Unterstützt werden Visual C++ 6.0, Visual Studio 98 sowie Visual Studio 2002 und 2003 ab der Standardversion. Für Visual Studio 2005, das momentan noch im Beta-Stadium ist, wird ein Update angekündigt.

Der erzeugte Code ist natürlich ebenfalls auf bestimmte Plattformen beschränkt: So kann ein Itanium-Programm nur unter Windows Advanced Server oder Windows 2003 Server (ab Enterprise) auf einem Itanium-2-System betrieben werden.

Bei Code für IA-32-Systeme ist die Sache etwas flexibler: Hier werden alle Windows-Versionen ab 98 unterstützt. Der Compiler für EM64T generiert Code, der nicht nur auf Intel-CPUs mit EM64T sondern - von Intel ausdrücklich erwähnt - auch unter AMDs Athlon 64 und Opteron betrieben werden kann.

Vor der Installation des Intel-Compilers gibt es somit je nach Host- und Zielplattformen einiges zu beachten. Ebenso spielt es eine Rolle, ob andere Intel-Compiler bereits installiert sind oder einmal installiert waren: Die Lektüre des mitgelieferten HTML-Readme ist daher dringend zu empfehlen.

Integration in Visual Studio

Die Installation von Intels C++ erfolgt paketorientiert. So kann man zum Beispiel nur den Compiler selbst installieren. Damit ist es dann möglich, auf der Kommandozeile Programme zu übersetzen. Weitere Pakete dienen der Installation des Intel Debuggers und der Integration von C++ 9.0 in Microsofts Visual Studio.

Die Integration in Visual Studio ist dabei sehr gelungen. Zunächst merkt man Visual Studio keinerlei Veränderungen an: Wer einen „Wizard“ für Anwendungen mit dem Intel-Compiler erwartet, wird enttäuscht.

Um nun eine Anwendung vom Intel Compiler übersetzen zu lassen, wird zunächst ganz normal ein Projekt beziehungsweise eine Solution angelegt – und die wird auch weiterhin wie gewohnt im Solution Explorer dargestellt. Beim Klick auf das Projekt im Solution Explorer enthält das Objektmenü aber den neuen Befehl „Convert to use Intel C++ Project System“. Das Ausführen des Befehls baut das Projekt um. Ein „konvertiertes“ Projekt hat nun im Solution Explorer ein Intel-Icon. Ein derart konvertiertes Projekt enthält dann im Objektmenü einen Befehl zum „zurück konvertieren“.

Die Konvertierung macht sich aber bemerkbar, wenn man den Build-Prozess startet: Im Output-Fenster meldet sich nicht länger der Microsoft Compiler, sondern der von Intel. Auch beim Linken arbeitet nicht mehr Microsofts Linker, sondern Intels „xilink“.

Beim Öffnen der Dialoge für die Einstellung der Compiler- und Linker-Optionen findet man im Property-Grid für die jeweiligen Einstellungen immer einen Bereich mit dem Titel „Intel specific“. Alle normalen Build-Einstellungen können genauso vorgenommen werden, als würde Microsofts Compiler beziehungsweise Linker verwendet werden. Zusätzlich gibt es spezielle Optionen für den Intel-Compiler und -Linker.

Compiler-Wechsel möglich

Eine dieser Einstellungen bei den „General Properties“ dient zum Beispiel dem Umschalten zwischen den Compilern. Es ist somit ein Leichtes, zwischen den Compilern hin- und herzuschalten. Unter Nutzung der Configurations von Visual Studio ist also auch ein Build möglich, bei dem zwei Versionen eines Programms gebaut werden: eine mit den Intel-Tools, die andere mit Microsofts Werkzeugen.

Intels Optionen finden sich hauptsächlich im „Optimization“-Bereich von Compiler und Linker sowie im „Code Generation“-Bereich des Compilers. Die Optionen sind größtenteils vernünftig erläutert, und die Dokumentation ist leicht zu erreichen: Intels Integration in die IDE geht so weit, dass auch der kontextsensitive Hilfe-Button auf dem Dialog zum Einstellen der Optionen funktioniert.

Auf die Kompatibilität zu Microsofts Compiler legt Intel ebenfalls großen Wert. Dabei werden extra drei Optionen für das Behandeln von bekannten Fehlern im Microsoft-Compiler angeboten: So lässt sich einstellen, wie stark der Intel-Compiler diese Fehler selbst übernehmen soll. Ein Beispiel wäre der folgende Fall:

int i = 5;
+i = 4;

Der Compiler von Microsoft bemängelt das mit left operand must be lvalue und weist zumindest auf einen Fehler hin. Ältere Versionen des Compilers ignorierten aber einfach einen „unary operator“, wenn dieser auf ein lvalue angewendet wurde.

Intels C++-Compiler bemängelt das angegebene Beispiel (besser als Microsoft) mit error: expression must be a modifiable lvalue. Wünscht man sich aber vom Intel-Compiler das gleiche fehlerhafte Verhalten der älteren Microsoft-Versionen, dann kann man dem Compiler dies per Option mitteilen.

.NET: Geht nicht

An einer anderen – nicht unwichtigen – Stelle ist Intels C++-Compiler dafür mit Microsofts Compiler nicht kompatibel: wenn es um .NET-Programme geht. Zwar unterstützt Intels C++ 9.0 viele der Features des aktuellen C++-Compilers aus Visual Studio .NET 2003, aber keinen „Managed Code“.

So fehlt der Support für die „Managed Extensions for C++“ völlig. Intels Compiler übersetzt somit keinen „Managed Code“. Ebenso fehlt der Support für Attribute, das Event Handling und diverse Keywords wie __abstract und __box, die alle für die .NET-Entwicklung in den Microsoft-Compilern eingebaut werden. Intel beschränkt sich vollständig auf nativen Code. Verständlich, denn schließlich will Intel mit dem eigenen Compiler den besten Code für die Ziel-CPU erzeugen. Dabei gibt es bei .NET keinerlei Einfluss auf die Code-Erzeugung oder Optimierung.

Das Debugging von Intels übersetzten Programmen erfolgt wie gewohnt in der Visual Studio IDE mit dem integrierten Debugger. Die benötigten Debug-Informationen generiert der Intel-Compiler im passenden Format, so dass sich hier für den Entwickler keinerlei Veränderungen ergeben. Alternativ lässt sich Intels eigener GUI-Debugger benutzen, den Intel zusammen mit dem Compiler ausliefert.

Debugger: Besser der von Microsoft

Die „grafische Oberfläche“ des Intel-Debuggers erinnert mehr an Tools aus MS-DOS-Zeiten als an zeitgemäße Entwicklungsprogramme. In Spezialfällen mag der Debugger durchaus seine Wichtigkeit haben – im Normalfall wird man aber auf den integrierten Visual Studio Debugger zurückgreifen.

Dafür packte Intel bei seinem Compiler-Paket ein paar andere „Goodies“ bei, die es in Form von Libraries und Klassenbibliotheken gibt. Hier ist besonders die Mathematik-Bibliothek mit hochoptimierten Funktionen zu nennen. Die Bibliothek eignet sich besonders für den Einsatz in technischen oder grafischen Programmen, bei denen hohe Performance und Präzision wichtig sind.

Des Weiteren gibt es einen Satz an „Intrinsics“, die im Wesentlichen dafür gedacht sind, Zugriff auf MMX und Streaming SIMD Extensions zu gewähren, ohne dass der Programmierer auf Assembly zurückfallen muss. Außerdem stellt Intel noch Integer- und Floating-Point-Vektor-Klassen zur Verfügung, deren Verwendung für besseren parallelisierbaren Code gedacht ist.

Die Optimierung

Die besonderen Möglichkeiten von Intels Compiler liegen im Bereich der Optimierung: Intel glänzt hier durch viele Optionen zum Erzeugen von optimalem Code für verschiedene eigene Architekturen und Prozessoren. So existiert auch eine sehr umfangreiche Online-Hilfe für den Bereich der Optimierung, die deutlich weiter geht als alles, was Microsoft in diesem Bereich zur Verfügung stellt.

Es gibt speziellen Support für Loop unrolling, für Vektorisierung und Prefetching sowie für das Pipelining bei Itanium-Programmen. Dabei bietet Intels 9.0er Compiler unter anderem drei unterschiedliche Arten von Unterstützung für das parallele Programmieren. So kann der Programmierer unter Verwendung von OpenMP explizit parallel programmieren – und das sowohl für Itanium als auch für IA-32-Systeme.

Ebenso bietet der Compiler implizites Parallelisieren über “Auto parallelization“ und „Auto vectorization“. Alle drei Features können gemischt genutzt werden. Beim impliziten Parallelisieren erledigt der Compiler das Erzeugen des passenden Codes, zum Teil mit Hilfe von Hinweisen im Quellcode.

Automatisches Parallelisieren

Bei der Auto-Vektorisierung verwendet der Intel-Compiler beispielsweise automatisch SIMD-Befehle aus dem MMX, SSE und SSE2 Instruction Set. Dabei untersucht der Vektorisierer den Code auf Sequenzen, die parallel ausgeführt werden können. Er konvertiert die eigentlich sequenziellen Operationen dann in SIMD-Instruktionen, die 2, 4, 8 oder 16 Elemente gleichzeitig bearbeiten. Wie viele parallele Instruktionen stattfinden, ist vom betroffenen Datentyp abhängig.

Im folgenden Beispiel, in dem ein Array aus Fließkommazahlen kopiert wird, tritt der Vektorisierer beispielsweise in Kraft, wenn er erkennen kann, das Quelle und Ziel (dest[i] und src[i]) unterschiedlich sind.

void CopyVector(float *dest, float *src, int len)
{
int i;
for(i=0; i<len; i++;)
{
dest[i]=src[i];
}
}

Fazit

Insgesamt betrachtet ist Intels neuer C++-Compiler ganz sicher für jedermann interessant, der möglichst „performanten“ Code generieren möchte und dem die von Microsoft gebotenen Möglichkeiten dazu nicht ausreichen. Gleichzeitig muss aber auf den Komfort von Visual Studio nicht verzichtet werden.

Für einen relativ günstigen Preis von knapp 400 US-Dollar erhält der professionelle Entwickler ein Werkzeug, das den am besten optimierten Code für Intel-CPUs liefert. (cvi)