Phänomen: Rechenzeit Funktionsaufrufe

Gast #3229171
Lesenswert?

Hallo Zusammen,

bin in den letzten Tagen auf ein Problem gestoßen, das ich mir nicht 
erklären kann. Vielleicht hat jemand von euch eine Idee.

Ich habe Rechenzeitmessungen durchgeführt und es hat sich 
herausgestellt, dass die Funktion beim ersten Aufruf mindestens doppelt 
so lang wie bei den weiteren Aufrufen. Es wird kein Initialisierungscode 
oder ähnliches durchlaufen. Gemessen wurde die Rechenzeit sowohl mit 
internem Timer als auch mit Oszilloskop an einem Pin. Ich habe es an 
zwei Prozessoren (ARM9, Nios) mit zwei Entwicklungsumgebungen probiert. 
Messungen wurden z.T. mit un ohne Cache gemacht. Es ändert sich zwar 
einiges an den Absolutwerten und auch das Verhältnis, allerdings ist der 
erste Aufruf IMMER signifikant länger.

Bisher ist mir so etwas nie aufgefallen, weiß jemand, was der Grund 
dafür ist?

Mfg
Alex
Gast #3229282
Lesenswert?

NAja die heutigen CPUs sind halt ganz schön komplex und eigenlich nicht 
mehr echtzeitfähig (deterministisch). Da sind halt nicht nur chaes 
sondern auch noch Sprungvorhersage Einheiten drinne. Es könnte halt sein 
das er beim ersten durchlauf merkt an welchen Stellen wieoft, wohin 
verzweigt wurde und er beim zweitenmal da schon weiß.
Gast #3229285
Lesenswert?

Uwe schrieb:
> Es könnte halt sein
> das er beim ersten durchlauf merkt an welchen Stellen wieoft, wohin
> verzweigt wurde und er beim zweitenmal da schon weiß.

nein die Künstliche Intelligenz ist in den aktuellen CPUs noch nicht 
enthalten. Cache könnte zwar eine auswirkung haben, aber die 
Sprungvorhersage ist meines wissens nicht lernfähig.
#3229290
Lesenswert?

@ Uwe (Gast)

>NAja die heutigen CPUs sind halt ganz schön komplex

Ja.

>und eigenlich nicht
>mehr echtzeitfähig (deterministisch).

uhhh, da weden aber zwei völlig verschiedene Sachen zusammengerührt.

Auch komplexeste CPUs arbeiten VOLLKOMMEN deterministisch.

http://de.wikipedia.org/wiki/Determinismus_%28Algorithmus%29

Denn sonst würden sie nicht funktionieren. Das Problem ist jedoch, dass 
die Vorhersage über das Verhalten sehr komplex geworden ist und damit in 
vielen Anwendungen, die exaktes Zeitverhalten fordern, praktisch kaum 
vorhergesagt werden kann, es gibt zuviele Einflußgrößen und 
Übegrangsmöglichkeiten. Deutlich einfachere Automaten sind eben deutlich 
leichter und damit praktisch nutzbar vorhersagbar.
Gast #3229295
Lesenswert?

Ups Sorry :-D.. Ich dachte ich hab alle Infos eingefügt.

Programmiersprache: C
Compiler: IAR 6.40 für die Tests auf dem ARM9, Nios II IDE 9.0SP2 GCC 
für den Nios
Betrifft alle Funktionen die ich ausprobiert habe. Also so an die 15.
Interrupts waren beim NIOS komplett aus, auf dem ARM war der 
Funktionsaufruf aus einem Interrupt mit der höchsten Priorität

Im folgenden Beispielcode mit einer Dummy Funktion. ACKh_OFF und ACKh_ON 
setzt den Output.
1
volatile xy;
2
void testfcn(void)
3
{
4
    int i=0;
5
    int k=0;
6
    int array[100];
7
    for(i=0;i<1;i++)
8
    {
9
        xy=i;
10
        array[0]=i;
11
        array[0]=xy;
12
    }
13
        for(k=0;k<1;k++)
14
    {
15
        xy=k;
16
        array[1]=k;
17
        array[1]=xy;
18
    }
19
}
20

21
int main()
22
{ 
23
    int i=0;
24
    ACKh_OFF;
25
    for(i=0;i<50;i++)
26
    {
27
      ACKh_OFF;
28
    }
29
    while (1)
30
    {
31
      ACKh_ON;
32
      testfcn();
33
      ACKh_OFF;
34
    }
35
  return 0;
36
}

Ich hoffe jetzt sinds genügend Infos?

Gruß
Alex
#3229337
Lesenswert?

1
volatile xy;
2
void testfcn(void)
3
{
4
    int i=0;
5
    int k=0;
6
    int array[100];
7
    for(i=0;i<1;i++)
8
    {
9
        xy=i;
10
        array[0]=i;
11
        array[0]=xy;
12
    }
13
        for(k=0;k<1;k++)
14
    {
15
        xy=k;
16
        array[1]=k;
17
        array[1]=xy;
18
    }
19
}

Der Compiler sollte das so optimieren:
1
volatile xy;
2
void testfcn(void)
3
{
4
        xy=0;
5
        xy;
6
        xy=0;
7
        xy;
8
}

Da ist also kaum Code übrig und dann ist der Cache laufzeit 
entscheidend.
Gast #3231911
Lesenswert?

Ihr habt recht, ich hatte aber auch schon andere Werte > 1 drin.

Was die Cache Laufzeit angeht: da habe ich auch schon Tests dazu 
gemacht. Hatte am Anfang der Funktion eine Schleife die für einige 
Zyklen nichts gemacht hat, dann das Ausgangs-Bit getoggelt, und dann den 
eigentlichen Algorithmus abgearbeitet. So müsste ja der Cache wieder 
gefüllt sein, oder?

Werd mich mal eingehend mit der Branch prediction beschäftien. 
Vielleicht ist das wirklich die Lösung...

Sonnige Grüße aus dem Süden
Alex
Gast #3232015
Lesenswert?

Eine mögliche Ursache könnten die lokalen Variablen: Das Reeservieren 
von Speicher für die loaklen Variablen kann davon abhängen was vorher an 
Speicher genutzt wurde.

Ohne sich den erzeugten ASM Code anzusehen ist das ganze aber ein 
relativ wildes raten.
Gast #3232022
Lesenswert?

Ulrich schrieb:
> Eine mögliche Ursache könnten die lokalen Variablen: Das Reeservieren
> von Speicher für die loaklen Variablen kann davon abhängen was vorher an
> Speicher genutzt wurde.

lokale Variabel werden doch auf den Stack gelegt, dabei ist egal was 
vorher vorhanden war.
Persönliche Seite #3232181
Lesenswert?

ab schrieb:
> So müsste ja

Warum? Man sollte, wenn man irgendwas messen will (und erst recht wenn 
man auf scheinbare Widersprüche trifft) verifizieren.
Die komplette Architektur des NIOS-II ist dokumentiert, auch Caches, 
Branch-Predict und man kann das ganze sogar simulieren lassen... Also 
kein Grund zu spekulieren.

Der schrieb:
> Stimmt, das habe ich übersehen

Ich auch, trotzdem ist die Laufzeit konstant wie Peter Dannegger 
schriebt, vermutlich wird sogar der Funktionsaufruf wegoptimiert, selbst 
bei > 1 kann der Compiler durch loop-unrolling Sprünge vermeiden.

ab schrieb:
> eine Schleife die für einige Zyklen nichts gemacht hat

Wenn wirklich "nichts" gemacht wird, wird auch diese wegoptimiert, auch 
ist hier weniger der Instructioncache interessant sondern der 
Branch-Predict.
Gast #3259184
Lesenswert?

Ich wollte nur kurz informieren, dass es der (Instruction) Cache war, 
der hier die Unterschiede in der Rechenzeit verursacht hat. Bei komplett 
abgeschaltetem Cache oder Aufruf anderweitiger Funktionen, die zu einer 
Cache-Umwälzung geführt haben, war die Rechenzeit für die 
Funktionsaufrufe gleich (langsam).

Danke für die Unterstützung hier im Forum!

Gruß
Alex

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren