V
32bit-System schrieb:
Ist es besser grundsätzlich alle Werte auf einem 32bit-System auch auf 32bit zu trimmen?
Da habe ich zB einen Wert der von 0-100 gehen kann, soll ich nun "unsigned char" als Typ benützen oder "unsigned long int" (32bit)?
---
Dass dies bei größeren Speicherallokationen nicht sinnvoll ist, ist mir auch klar. Und einen String lege ich weiterhin als char* an.
nein, ist nicht sinnvoll, grundsätzlich...
struct Datum{
unsigned char monat;
unsigned short jahr;
unsigned char tag;
};
schlecht. der code lebt davon, daß ein char 8 bit und ein short 16 bit hat. besser, man scheibt sich in nen header
typedef unsigned char u8;
typedef unsigned short u16;
und kann den immer wechseln, wenn sich die drunterliegende maschine ändert.
struct Datum{
u8 monat;
u16 jahr;
u8 tag;
};
und jetzt hängt es davon ab, was man damit machen mag.
bool operator==(Datum a,Datum b){
return a.tag==b.tag && a.monat==b.monat && a.jahr==b.jahr;
}
was macht daraus der geil otimierende compiler? wenn man glück hat, kommt er auf sowas:
bool operator==(Datum a,Datum b){
return *(int*)(&a)==*(int*)&b;
}
das ist mal ne wirklich performante funktion.
und was istbeim op<()?
bool operator<(Datum a,Datum b){
return a.jahr<b.jahr||(a.jahr!=b.jahr&&(a.monat<b.monat||(a.monat==b.monat&&(a.tag<b.tag))));//scnr
}
nee, das will ja keiner.
bool operator<(Datum a,Datum b){
return a.tag+32*a.monat+512*b.jahr<b.tag+32*b.monat+512*b.jahr;
}
jo, das kann ich lesen. heri muß der arme compiler leider viermal nen char nach short hochkonvertieren. wäre gleich ales short gewesen. würde es schneller sein.
aber falsch immernoch. short ist ja zu klein für den trick.
bool operator<(Datum a,Datum b){
return a.tag+32*a.monat+512u*b.jahr<b.tag+32*b.monat+512u*b.jahr;
}
so könnte es gehen. jetzt muß er nich mehr casten. her kommt man leicht af die idee, alles zu u32 zu trimmen.
interessant sind diese überlegungen eh nur für members. und da kann es ganz sinnig sein, sich zu überlegen, wie man das layout macht. so kann es sein, daß der zurgriff auf monat in
struct Datum{
u8 monat;
u16 jahr;
u8 tag;
};
schneller ist, als der auf die anderen atrribute, weil es das erste attribut ist. aus a.tag muß der compiler ja machen (((unsigned char)(&a))+3) und aus a.monat nur (unsigned char)(&a).
vermutlich mag man die rechnung aus den vergleichoperatoren raushalten, indem man gleich nr einen u32 nimmt, und darin tag+32*monat+512*jahr abspeichert. das macht vergleiche schneller, und algos, die vergleichen mössen, haben gerne O(n*log n), und macht dafür ein- und asgaben langsamer, aber diese algos haben gerne O(n) und bei diesen algos ist das extrahieren von tag/monat/jahr irrelevant, weil ne ausgabe auf cout oder ne datei gleich mal um größenordnungen langsamer ist, als das bißchen geshifte.
also ich kann keine grundsätzliche aussage machen, nur darauf hinweisen, daß es normalerweise schneller ist, gleich alles als 32-bitter zu haben, weil das hochcasten wegfällt, sobald man sie mit anderen 32-bittern verrechnet oder als arrayindex nimmt. daß es auf dem stack (also für auto-variablen) nrmalerweise egal ist...
echt?
naja, manchmal passen fein zwei auto-chars in ein register, als AL und AH zum bleistift. dann ist ein register mehr frei, als bei 32-bittern und das bringt für ne andere variable (im besten fall für die laufvariablen der innerste schleife!) wieder speed. müssen diese beiden chars nur sachen machen, wobei sie chars bleben dürfen, wars ein gewinn. wenn ich aber die vars zu int mache, darf der compiler sie wohl kaum klein machen. aber andersrum darf er! also sollte ich sie zu chars machen, und wenn der compiler nen speedvortiel sieht, sie zu int zu machen, macht der das von alleine. und was abschätzunen angeht, wann welcher assemblerbefehl der beste wäre, ist der compiler gandios gut. ich sollte ihm mit allen kräften helfen, indem ich ihm so viele freiheiten wie möglich lasse.
also wieder nix. weder für members noch für auto-variablen kann ich in erwägung ziehen, ne allgemeine aussage zu machen, welche version am meisten speed brint.