www.mikrocontroller.net

Forum: PC-Programmierung Externe Funktion inlinen


Autor: Sascha H. (Firma: --) (freeze2046)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich habe folgendes Problem:

Ich habe mehrere Assembler-Funktionen die ich bereits zu einem 
COFF-Obj-File kompiliert habe.
Nun würde ich gerne diese Funktionen in einem C/C++ Projekt benutzen 
(Visual Studio 2008 TS).

An und für sich kein Problem. Ich habe die Funktionen dort als extern 
"C" deklariert und kann sie dort auch verwenden.

Da diese Funktionen jedoch weit über 2 Millionen mal am Stück aufgerufen 
werden und es sich hier um einen zeitkritischen Prozess handelt, möchte 
ich die ständigen calls vermeiden und die Funktion lieber inlinen.

Da erst dem Linker die Funktion bekannt gemacht wird, hat der Compiler 
keine Chance dazu. Was kann ich tun?


Eine Möglichkeit wäre sicherlich inline assembler zu verwenden. Dies 
mache ich mit dem VC jedoch sehr ungern, da ich viele Redundanzen 
herausnehmen müsste (doppeltes Sichern von Registern).

Zudem stellt sich mir die Frage ob der Compiler an meinem Code 
rummurkst?!

Uber vorweihnachtliche Hilfe wäre ich sehr dankbar ;-)

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dir Frage ist ob es sinn macht, wenn du eine Funktion schon in Assembler 
schreibst dann vermutlich aus dem Grund damit sie sehr schnell ist. Ich 
vermute es ist auch nicht bloss ein 3 Zeiler. Die Frage ist also ob 
wirklich der eine Call etwas an der gesamtlaufzeit ändert. Klar sind es 
dann millionen calls weniger aber ob es nun 10 Stunden oder 10Stunden 
und 5minuten dauert ist doch egal.

Autor: Sascha H. (Firma: --) (freeze2046)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meine Messungen (mit anderen Bedinungen) haben ergeben, dass es in etwa 
10 Sekunden ausmacht.

Dass ist in meinem Fall zu viel. Ich habe für meine Funktion eine 
Zeitspanne von etwa. 5 bis max. 10 Sekunden Zeit. Die erreiche ich aber 
nicht.

Kann mir jemand sagen, ob es denn prinzipiell überhaupt möglich ist den 
Code aus einer externen Objektdatei zu inlinen?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha H. schrieb:

> ob es denn prinzipiell überhaupt möglich ist den
> Code aus einer externen Objektdatei zu inlinen?

Nein.

Autor: Sascha H. (Firma: --) (freeze2046)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Nein.

Angeblich schon:
http://msdn.microsoft.com/en-us/library/e7k32f4k%2...

Ich habe nur noch nicht ganz verstanden, wie genau dass genutzt werden 
muss.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
aus wenn besteht denn die funktion wenn sie so schnell ist? Bist du 
sicher das es mit C ohne asm nicht genauso schnell geht.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo steht dort, dass dies ginge? Voraussetzung für Inlining ist stets, 
dass der Compiler den zu inlinenden Code kennt. Hier ist aber 
vorgegeben, dass er den Code nicht kennt.

PGO sagt dem Compiler nur, wo sich Inling laufzeitmässig lohnt und wo 
nicht.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Wo steht dort, dass dies ginge?

Ich lese dort allerdings auch, dass der Linker das kann.

So wie ich das verstanden habe, wird aus den Profile-Läufen die 
Information gewonnen, ob sich inlinen für Funktionen lohnen würde und 
der Linker baut das dann entsprechend um.

> PGO sagt dem Compiler nur, wo sich Inling laufzeitmässig lohnt und wo
> nicht.

Nicht ganz.
Am Anfang des Artikels ist eine Übersicht über die durchzuführenden 
Schritte. Nach dem Schritt der Generierung der PGO Info kommt nur noch 
ein Linkerschritt mit dem Optimize Schalter.

Allerdings werde ich aus der Beschreibung des Linker-Schalters auch 
nicht richtig schlau. An einer Stelle steht, dass der Linker dann den 
Compiler benutzt um globale Optimierungen durchzuführen. Beim konkreten 
OPTIMZE Fall steht allerdings nichts davon. Da liest es sich wieder so, 
als ob der Linker das ganz alleine machen könnte. Hmmm


Ich würde allerings auch erst mal die Frage stellen, ob es sich wirklich 
lohnt von C auf Assembler umzusteigen oder ob da nicht auf C-Ebene noch 
was geht.

Autor: Sascha H. (Firma: --) (freeze2046)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Karl heinz Buchegger

Exakt, so habe ich das auch verstanden. Ich bin gerade dabei zu testen, 
ob es funktioniert. Prinzipiell wird offensichtlich, dass durch den 
Testlauf gewonnene *.pgc File dazu genutzt den Code zu optimieren.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:

> Ich lese dort allerdings auch, dass der Linker das kann.

Sorry, ich bin grad blind und seh's immer noch nicht.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha H. schrieb:

> Exakt, so habe ich das auch verstanden. Ich bin gerade dabei zu testen,
> ob es funktioniert. Prinzipiell wird offensichtlich, dass durch den
> Testlauf gewonnene *.pgc File dazu genutzt den Code zu optimieren.

Klar. Nur ist das nicht wirklich der Linker, bzw. nicht nur der, auf den 
es dabei ankommt. Zu dieser Form der Optimierung gehört beispielsweise 
auch die Entscheidung, welcher Zweig eines if-else Statements wichtiger 
ist. Der andere wird dann aus dem Weg geräumt um teure ausgeführte 
Sprungbefehle zu vermeiden. Das wird kaum der Linker machen. Wenn doch, 
dann allenfalls weil der Objektcode nur Pseudocode enthält und der 
Linker den eigentlichen Codegenerator.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Karl heinz Buchegger schrieb:
>
>> Ich lese dort allerdings auch, dass der Linker das kann.
>
> Sorry, ich bin grad blind und seh's immer noch nicht.

Wie gsagt: So sicher bin ich mir auch nicht.
Aber hier die durchzuführenden Schritte

* Compile one or more source code files with /GL.

  logisch. Das Object File muss attributiert werden.

* Link with /LTCG:PGINSTRUMENT.

  auch klar. Da muss noch eine Lib dazu, die die Infos sammelt
  und abspeichert

* Profile the application.

  Auch klar. Jetzt werden Profile Daten generiert

* Link with /LTGC:PGOPTIMIZE.

  Und jetzt werden die Profile Daten eingearbeitet.
  Interessant: Kein Recompile notwendig. Offenbar entfernt dieser
  Schritt auch die Profile-Attributierung

Und das wars.

Allerdings ist beim ersten Schritt ein Zusatz:
However, only those modules compiled with /GL will be instrumented and 
later available for profile-guided optimizations.

Hmm. Wie das bei Assemblermodulen geht .... keine Ahnung. Aber das 
müsste man rauskriegen können.
Auch interessant: /LTCG steht für Link Time Code Generation
Auf der anderen Seite: Namen sind Schall und Rauch :-)

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:

> * Link with /LTGC:PGOPTIMIZE.
>
>   Und jetzt werden die Profile Daten eingearbeitet.
>   Interessant: Kein Recompile notwendig. Offenbar entfernt dieser
>   Schritt auch die Profile-Attributierung

Jo, aber genau da liegt der Hase im Pfeffer. Erklär mit bitte mal, wie 
ohne Recompile eine "Conditional Branch Optimization" möglich sein soll.

Bloss weil du nur den Linker aufrufst, heisst das ja noch lange nicht, 
dass dabei nur das läuft, was man traditionell unter einem Linker 
versteht.

Autor: Sascha H. (Firma: --) (freeze2046)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Hmm. Wie das bei Assemblermodulen geht .... keine Ahnung. Aber das
> müsste man rauskriegen können.
> Auch interessant: /LTCG steht für Link Time Code Generation
> Auf der anderen Seite: Namen sind Schall und Rauch :-)

Ja, darüber bin ich auch gestolpert. Hört sich ja so an, als könnten 
dann nur solche Module optimiert werden.
Zur Not benutze ich MASM. Da wird evtl. eine solche Möglichkeit 
bestehen.


A. K. schrieb:
> Bloss weil du nur den Linker aufrufst, heisst das ja noch lange nicht,
> dass dabei nur das läuft, was man traditionell unter einem Linker
> versteht.

Behauptet ja niemand, dass das NUR der Linker macht. Und um ehrlich zu 
sein ist mir dass auch erst mal egal, so lange es funktioniert.
Ich gehe sowieso davon aus, dass der VS-Linker mehr macht als sein Name 
sagt.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber dann kommt's sehr drauf an, was aus dem Compiler im LTCG-Modus 
rauskommt und ob sich das mit extern zugefüttertem Assembler-Code 
verträgt.

Meine unmassgebliche Vermutung ist, dass der Compiler dabei halbgaren 
Zwischencode auswirft. Vom Assembler her steht aber nur der Binärcode 
(plus relocations) zur Verfügung. Ob das wohl zusammengeht? Denn 
eigentlich müsste dieser Linktime-Codegenerator den Fall eigens vorsehen 
und den Binärcode analysieren und tracen, um festzustellen welche 
Register der verwendet und wo der wirklich aufhört. Ist ja nicht in 
Stein gemeisselt, dass Assembler-Code immer mit dem letzten Byte Code 
aufhört.

Meine Prognose: Externer Binärcode bleibt externer Binärcode. Mit oder 
ohne LTCG.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Karl heinz Buchegger schrieb:
>
>> * Link with /LTGC:PGOPTIMIZE.
>>
>>   Und jetzt werden die Profile Daten eingearbeitet.
>>   Interessant: Kein Recompile notwendig. Offenbar entfernt dieser
>>   Schritt auch die Profile-Attributierung
>
> Jo, aber genau da liegt der Hase im Pfeffer. Erklär mit bitte mal, wie
> ohne Recompile eine "Conditional Branch Optimization" möglich sein soll.

Ich hab keine Ahnung :-)

> Bloss weil du nur den Linker aufrufst, heisst das ja noch lange nicht,
> dass dabei nur das läuft, was man traditionell unter einem Linker
> versteht.

Ich geh mal stark davon aus, das das was MS da hat, mit einem 
traditionellen Linker nicht mehr viel zu tun hat.
So wie MS bei vielen Dingen ihr eigenes Süppchen kocht (oder klaut)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:

> Meine unmassgebliche Vermutung ist, dass der Compiler dabei halbgaren
> Zwischencode auswirft. Vom Assembler her steht aber nur der Binärcode
> (plus relocations) zur Verfügung. Ob das wohl zusammengeht?

Mir gehts wie dir: Ich kanns mir nicht recht vorstellen.

Aber wie heißt es so schön:
Versuch macht kluch.

Autor: Sascha H. (Firma: --) (freeze2046)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstes Testergebnis:

Es wird versucht folgende Funktion in einem C-Projekt zu inlinen:
TITLE PGOTest.asm

.686P
.XMM
.MODEL FLAT


PUBLIC _MakeSth
EXTRN  __imp__printf:PROC


.CODE

CONST SEGMENT
  FORMAT DB '%d %d', 13, 10, 0
CONST ENDS

_TEXT    SEGMENT
  _i1$  = 8
  _i2$  = 12
_MakeSth PROC  
  push ebp
  mov  ebp, esp
  
  mov  eax, DWORD PTR _i2$[ebp]
  mov  edx, DWORD PTR _i1$[ebp]
  
  push eax
  push edx
  push OFFSET FORMAT
  call DWORD PTR __imp__printf
  add  esp, 12
    
  pop  ebp
  ret  
_MakeSth ENDP
_TEXT    ENDS 

END

Das ganze sieht in meinem Main-C-Projekt dann so aus:
#include <stdio.h>


extern void MakeSth(int i1, int i2);


int main()
{
  //MakeSth(77, 999);

  unsigned i = 0, j = (unsigned)(1 << 8);
  for( ; j; j--, i++ ) {
    MakeSth(i, j);
  }

  return 0;
}


Nach der PG-Optimierung habe ich folgendes Assembly-Listing erhalten:
; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01 

  TITLE  main.cpp
  .686P
  .XMM
  include listing.inc
  .model  flat

INCLUDELIB OLDNAMES

EXTRN  @__security_check_cookie@4:PROC
EXTRN  _MakeSth:PROC
PUBLIC  _main
; Function compile flags: /Ogtpy
;  COMDAT _main
_TEXT  SEGMENT
_main  PROC            ; COMDAT
; 2056 dynamic instrs
; entered 1 times
; Line 9
  push  esi
  push  edi
; Line 12
  xor  edi, edi
  mov  esi, 256        ; 00000100H
  npad  7
$LL3@main:
; Line 14
  push  esi
  push  edi
  call  _MakeSth
  dec  esi
  add  esp, 8
  inc  edi
  test  esi, esi
  jne  SHORT $LL3@main
;    taken 255(99%), not-taken 1(0%)
  pop  edi
; Line 17
  xor  eax, eax
  pop  esi
; Line 18
  ret  0
_main  ENDP
_TEXT  ENDS
END

Wie man sieht hat er hier nur "Optimierungen" hinsichtlich 
Sprunganweisungen getroffen und eine Analyse als Kommentar hinzugefügt. 
Der Grund für den Call von MakeSth kann natürlich auch die Tatsache 
sein, dass es nicht mit dem Schalter /GL kompiliert wurde, da ja durch 
ml.exe (MASM) kompiliert wurde.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sehe ich das richtig das du dir wegen dem call gedanken machst aber 
selber in der Funktion ein printf aufrufst? Printf macht doch bestimmt 
99.9% der Rechenzeit aus.

Autor: Sascha H. (Firma: --) (freeze2046)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:
> sehe ich das richtig das du dir wegen dem call gedanken machst aber
> selber in der Funktion ein printf aufrufst? Printf macht doch bestimmt
> 99.9% der Rechenzeit aus.

Glaubst du ehrlich, dass DAS meine ach so performante Funktion ist, die 
ich unbedingt inlinen will?

Da kann ich mir ein schmunzeln nicht verkneifen ;-).
Ich hab einfach mal ein paar Zeilen dahin geklatscht, um euch was zeigen 
zu können bzw. das Ganze mal zu testen.

Und ob der das inlined oder nicht, ist denke ich mal unabhängig davon, 
ob ich darin etwas aufrufe.

Meinen original Code kann ich nicht posten, da 1. zu viel und 2. 
Firmeneigentum.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.