Hallo Leute,
wir haben hier eine Diskussion am Laufen, ob es den Code langsamer
macht, wenn man structs anstelle von "normalen Variablen" verwendet.
Hat das mal jemand ausgemessen, bzw. den assembler code sich angeschaut?
peterguy schrieb:
> Hallo Leute,>> wir haben hier eine Diskussion am Laufen, ob es den Code langsamer> macht, wenn man structs anstelle von "normalen Variablen" verwendet.>> Hat das mal jemand ausgemessen, bzw. den assembler code sich angeschaut?
Warum macht ihr das nicht einfach?
Erwarten würde ich, dass sich beide Varianten nichts schenken, eher im
Gegenteil, dass die struct Variante bei vernünftiger Programmierung
schneller ist.
Ich tippe mal auf gleich schnell. Im Endeffekt steht doch jede Variable
an einer bestimmten Stelle im Speicher. Zum Verarbeiten muss sie erst in
ein Register geladen werden usw.
Von daher wüsste ich jetzt nicht, warum es einen Unterschied machen
sollte? Es sei denn vielleicht dass bei einer struct die Variablen
direkt hintereinander im Speicher liegen und nicht "wild verstreut", und
dass der Prozessor auf aufeinanderfolgende Speicherstellen schneller
zugreifen könnte...
Mark Brandis schrieb:
> sollte? Es sei denn vielleicht dass bei einer struct die Variablen> direkt hintereinander im Speicher liegen und nicht "wild verstreut", und> dass der Prozessor auf aufeinanderfolgende Speicherstellen schneller> zugreifen könnte...
Das ist auch meine Überlegung, dass der Compiler dann mit einem
Basisregister und Offset arbeiten kann anstatt ständig irgendwelche
Adressregister mit Werten laden zu müssen. Auch sollten Funktionsaufrufe
einen Tick schneller gehen, wenn anstelle von 5 Variablen nur eine
Basisadresse einer struct übergeben werden muss.
Aber wie heißt es so schön: Versuch macht kluch.
Ich glaube auf einem Atmel ist zu lesende zugriff auf eine struct member
langsamber.
Erst muss er die adresse vom Struct lesen und dann darauf den offset
addieren (ich glaube nicht das er es optimieren kann).
Aber bei der übergaben an eine Funktion sollte eine struct schneller
sein, weil er ja nur eine Adresse übergeben muss, statt mehre Variablen.
Es wird wohl abhängig vom Programm sein, mal ist das eine mal das andere
schneller.
x = abcd;
ist ebenso schnell wie
x = a.b.c.d;
Weil der Compiler alle Offsets ausrechnen kann und keine zusätzlichen
Befehle zur Laufzeit notwendig sind
Falls es nicht gecshachtelte Strukturen/Unions sind sondern Zeiger,
müssen natürlich (idR) Indirektionen zur Laufzeit ausgeführt werden,
also
x = a->b->c->d;
Strukturen können ja nach Anwendungsfall Vor- oder Nachteile bieten.
Beispiel 1
avr-gcc (sizeof(int) = 2)
Es ist eine Funktion mit 4 char-Werten aufzurufen:
1
voidfoo(char,char,char,char);
Die Werte werden dann in den Registern R24, R22, R20, R18 übergeben und
R25,R23,R21,R19 bleiben ungenutzt. Mit Struktur
1
structchar2{chara,b;};
2
structchar4{chara,b,c,d;};
3
4
voidfoo2(structchar2,structchar2);
5
voidfoo4(structchar4);
wird die Struktur(en) in den Registern R22,R23,R24,R25 übergeben. Das
bedeutet eine bessere Registerausnutzung.
Sollen mehrere Werte zurückgegeben werden, ist dies je nach ABI auch
dann innerhalb eines Registers möglich, wenn eine Struktur zurückzugeben
ist.
Sind zB 4 Chars zurückzugeben, dann geht das effizient mit struct char4,
während die Standard-Lösung über Zeiger der Overkill ist:
Die zweite Variante ist um Längen effizienter.
Weiterhin eröffnen Strukturen die Möglichkeut, effizienter auf Daten
zuzugreifen, denn in einer Struktur sind alle Elemente definiert
angeordnet und haben bekannte Offsets zum Strukturanfang, was bei
Variablen nicht so ist. Deren Adressen haben keine dem Compiler bekannte
Beziehung und werden erst zur Linkzeit festgelegt:
1
inta,b,c,d;
2
structabcd{inta,b,c,d;};
3
4
voidadd1(void)
5
{
6
a++;
7
b++;
8
c++;
9
d++;
10
};
11
12
voidadd2(structabcd*s)
13
{
14
s->a++;
15
s->b++;
16
s->c++;
17
s->d++;
18
}
Schaut man sie hier die Codegröße für an (avr-gcc) dann belegt add1 76
Bytes, wohingegen add2 mit 46 auskommt und nur 2 Ticks langsamer ist.
(Gesamtdauer ca. 26 Ticks).
Johann
>Aber bei der übergaben an eine Funktion sollte eine struct schneller>sein, weil er ja nur eine Adresse übergeben muss, statt mehre Variablen.
Aber nur bei der Übergabe, beim Zugriff muss dann über Offset
zugegriffen werden, da kann sich das bei vielen zugriffen rächen.
Ist aber alles sehr Architektur und Compiler abhängig.
Also Compileroutput begutachten.
mfg.
Peter schrieb:
> Erst muss er die adresse vom Struct lesen und dann darauf den offset> addieren (ich glaube nicht das er es optimieren kann).
Hier mal ein Beispiel
Wie man sieht, wird da nix unnötig zur Laufzeit berechnet.
Die nötige Arithmetik wird -- falls möglich -- aufgehteilt zwischen
Compiler, Assembler und Linker.
Johann
dummi schrieb:
>>Aber bei der übergaben an eine Funktion sollte eine struct schneller>>sein, weil er ja nur eine Adresse übergeben muss, statt mehre Variablen.>>> Aber nur bei der Übergabe, beim Zugriff muss dann über Offset> zugegriffen werden, da kann sich das bei vielen zugriffen rächen.
Nö. Wie machst du es denn mit 10 Zugriffen wenn die Variablen im
Speicher verstreut sind? 10 Adressen übergeben?
Johann
Gab es nicht genau deswegen solche Compilerschalter wie WordAlignment ?
Bei denen "leerblöcke" mit eingabaut würden um den Zugriff zu
beschleunigen,
bzw weggelassen um Platz zu sparen ?!