Interprocedurel optimering

Interprocedural optimization ( eng.  Inter p rocedural Optimization , IPO ) , eller fuld-program optimering af programmer ( eng.  whole program optimization ) - compiler optimering , der bruger global kontrol flow analyse og påvirker mange procedurer, selv dem der er placeret i forskellige moduler, pga. hvortil der kan opnås en betydelig hastighedsforøgelse.

Efterhånden som programmer voksede i størrelse, begyndte udviklere at gøre deres kode mere læsbar og genbrugelig . Ofte fører det til, at procedurerne bliver yderst generelle, mens man i et specifikt program kan klare sig med en særlig sag. Opgaven med interprocessuelle optimering er netop genereringen af ​​sådanne særlige tilfælde.

Interprocedural optimering udføres automatisk af compileren (nogle gange med særlige direktiver). Aktivering af det kan føre til en betydelig stigning i kompileringstiden. Compilere, der kan udføre denne optimering, omfatter MLton og MLKit for Standard ML , Stalin for Scheme , for Haskell , Intel C++ Compiler .

Eksempler

Udskiftning af en funktionsparameter med en konstant

Efter gennemgang af koden sørger compileren for, at en af ​​parametrene altid er en konstant og ødelægger den.

Det var void DoSomething ( Object * aObj , int aParam ) { if ( aObj == NULL ) throw logic_error ( "aObj==NULL" ); cout << "DoSomething(" << aObj -> navn () << "," << aParam << ")" << endl ; } int main () { Objekt obj1 , obj2 ; Gør Noget ( & obj1 , 1 ); Gør Noget ( & obj2 , 1 ); returnere 0 ; } Blev void Gør Noget ( Objekt * aObj ) { if ( aObj == NULL ) throw logic_error ( "aObj==NULL" ); cout << "DoSomething(" << aObj -> navn () << "," << 1 << ")" << endl ; } int main () { Objekt obj1 , obj2 ; Gør Noget ( & obj1 ); Gør Noget ( & obj2 ); returnere 0 ; }

Udskiftning af et virtuelt opkald med et statisk

Det er her compileren sørger for, at alle virtuelle kald , der rent faktisk udføres, fører til det samme funktionskald. I stedet for at få adgang til den virtuelle metodetabel foretager compileren et direkte funktionskald.

I det samme eksempel, hvis Object::name() det er en virtuel metode, ville den optimerede funktion se sådan ud.

void Gør Noget ( Objekt * aObj ) { if ( aObj == NULL ) throw logic_error ( "aObj==NULL" ); cout << "DoSomething(" << Objekt :: navn ( aObj ) << "," << 1 << ")" << endl ; }

Fjerner ubrugt kode

Efter sletning får du:

void Gør Noget ( Objekt * aObj ) { cout << "DoSomething(" << Objekt :: navn ( aObj ) << "," << 1 << ")" << endl ; }

Samtidig kan virtuelle metodetabeller ryddes .

Inlining

Hvis en funktion bruges én gang, indgår den direkte på det sted, hvorfra den kaldes.

Små funktioner kan også inkluderes direkte i opkaldskoden.

Mange programmeringssprog ( Pascal , Java , D ) har ikke nøgleordet inline , og beslutningen om at inline en funktion tages af optimizeren (i tilfældet Java  , obfuscatoren ).

Det var inline int DoSomething ( int aParam ) { returnere aParam * aParam ; } int main () { int x = 2 ; int y = 3 ; cout << x << "^2=" << DoSomething ( x ) << ", " << y << "^2=" << DoSomething ( y ) << endl ; returnere 0 ; } Blev int main () { int x = 2 ; int y = 3 ; cout << x << "^2=" << x * x << ", " << y << "^2=" << y * y << endl ; returnere 0 ; }

Links

  • Thomas C. Spillman, "Exposing side effects in a PL/I optimizing compiler", i Proceedings of IFIPS 1971 , North-Holland Publishing Company, side 376-381.
  • Frances E. Allen, "Interprocedural Data Flow Analysis", IFIPS Proceedings, 1974.
  • Frances E. Allen og Jack Schwartz, "Determining the Data Flow Relationships in a Collection of Procedures", IBM Research Report RC 4989, aug. 1974.
  • Philip Abrams , "An APL Machine", Stanford University Computer Science Department, rapport STAN-CS-70-158, februar, 1970.
  • Terrence C. Miller, "Tentative Compilation: A Design for an APL Compiler", Ph.D. Afhandling, Yale University, 1978.