Manuelle Kontrollmöglichkeiten des Application-Compilers

Zwar arbeitet der Application-Compiler normalerweise automatisch, es kann aber Fälle geben, wo man mehr oder weniger Funktionen inlinen oder klonen möchte. Insbesondere wenn man a priori Informationen über die Häufigkeit eines Routinen-Aufrufs hat, kann es sinnvoll sein, in den Optimierungsprozeß einzugreifen.
Um global die Häufigkeit des Inlining zu beeinflußen, kann man die Kostengrenze verändern, die der Application-Compiler bei der Auswahl von Funktionen zum Inlinen benutzt. Dazu gibt es eine Option des ''build''-Kommandos:
     build -inline DEGREE ,
wobei DEGREE die Werte ''none'', ''low'', ''medium'' und ''high'' annehmen kann. Der Standardwert ist ''medium''. In unserem Beispielprogramm ''linalg'' wird bei ''low'' die Funktion GETVEC, die nur einmal aufgerufen wird, nicht mehr eingefügt, wie sonst bei ''medium''. Die Option ''high'' bewirkt hier keine Veränderungen.
Man kann auch angeben, daß bestimmte Funktionen immer oder nie eingebaut werden sollen, indem man entweder im Buildfile eine Zeile
     inline(FUNKTION1 [, ...])
bzw.
     no_inline(FUNKTION1 [, ...])
vorsieht, oder direkt in den Sourcecode die Compilerdirektive INLINE bzw. NO_INLINE einfügt:
  Fortran:
  C$DIR INLINE
nach der SUBROUTINE- bzw. FUNCTION-Zeile
  C:
  /*$dir inline*/
nach der Deklaration von lokalen Variablen.
Mit der Direktive NO_INLINE_CALL bzw. INLINE_CALL im Source-Code direkt vor einem Funktionsaufruf kann man auch ganz spezifisch für diesen Aufruf ein Inlinen verhindern oder erzwingen. Auch das Erzeugen von Routinen-Klons kann man steuern: Mit der Build-Option ''-clone none'' verhindert man das Klonen völlig, mit ''-clone all'' wird für jede Routine, in die eine Konstante hineingezogen werden kann, ein eigener Klon erzeugt. Für einzelne Routinen kann man, wie beim Inlinen, entweder mit einer Buildfile-Zeile
     clone(FUNKTION1 [,...])
     no_clone(FUNKTION2 [,...])
oder mit einer Compiler-Direktive CLONE / NO_CLONE im Source-Code hinter der Deklaration das Klonen beeinflußen. Darüberhinaus gibt es noch die Möglichkeit, die Direktive CLONE in der Form
    C$DIR CLONE(ARG1 [,...]) bzw. /*$dir clone(ARG1 [,...])*/
zu verwenden, wobei die Parameter Argumente der Routine sind. Dies bewirkt, daß immer dann ein Klon angelegt wird, wenn für eines oder mehrere der angegebenen Argumente eine Konstante in die Funktion hineingezogen werden kann.
Außerdem gibt es noch die Möglichkeit, das Verhalten des Application-Compilers indirekt zu steuern, indem man ihn mit zusätzlichen Informationen versieht. Um beispielweise abzuschätzen, wie oft eine Routine aufgerufen wird, nimmt er bei einer IF-Anweisung an, daß beide Zweige gleich wahrscheinlich sind (falls die Bedingung nicht schon zur Compilezeit ausgewertet werden kann). Wenn man dagegen schon weiß, daß die Zweige sehr unterschiedlich oft ausgeführt werden, kann man dies durch eine Compiler-Direktive mitteilen:
     condition_true(NN)    (Syntax fuer C bzw. Fortran analog zu oben)
wobei NN, eine ganze Zahl zwischen 1 und 99, die Wahrscheinlichkeit dafür angibt, daß die Bedingung wahr ist. Die Direktive muß in der Zeile direkt vor der IF-Anweisung stehen. Eine ähnliche Direktive ist
     estimated_trips(NN)  ,
die vor einer Schleife stehen kann und angibt, wie oft die Schleife im Mittel ausgeführt wird. Bei beiden Direktiven ist schon eine grobe Schätzung hilfreich; nützlich sind auch die Werte, die der CXpa liefert.
Schließlich gibt es noch die Möglichkeit, dem Application-Compiler auf die Sprünge zu helfen, wenn er trotz seiner globalen Analysen fälschlicherweise annimmt, daß für einige Variable ein Alias vorliegt (d.h. eine Überlappung von Arraybereichen, s.o.). Dazu fügt man in das Buildfile Zeilen der Art
     no_alias(VAR1, VAR2)
ein, wobei VAR1 und VAR2 die beiden Variablen mit dem Pseudo-Alias sind. Sind es Funktionsargumente, so werden sie angegeben als ''funktionsname:variable'' , wobei in FORTRAN alles groß zu schreiben ist. Eine Fortran-COMMON-Block-Variable bezeichnet man mit ''/COMMONBLOCK/VARIABLE'' bzw. ''//VARIABLE'' für den unbenannten COMMON-Block. Mit
     no_alias(BLOCKNAME)
kann man pauschal angeben, daß kein Alias zwischen einer Variable aus dem Common-Block BLOCKNAME und irgendeiner anderen Variablen vorliegt.

previous    contents     next

Peter Junglas 18.10.1993