Archiv verlassen und diese Seite im Standarddesign anzeigen : zwei Fragen C++
Hallo :)
zwei kurze Fragen
lässt sich der Operator [] getrennt vom Operator [][] überschreiben?
was ist schneller:
wir haben eine Struktur in der Optionen zusammengefasst sind, diese wird an eine Klasse übergeben
Variante 1: als Pointer, Zugriffe auf die Optionen erfolgen als Pointer-Referenz
Varainte 2: über den Stack, Zugriffe auf die Optionen erfolgt auf eine lokale Kopie
Unterschied im Code ist nur "->" vs. "."
Gruss pest
BadCop
2011-11-25, 19:35:52
wie oft greifst du auf diese Struktur zu? wenn die nicht bei jedem Funktionsaufruf verwendet wird, mach dir lieber Gedanken über Aufbau und Wartbarkeit, der Speed ist dann zweitrangig.
ich würde ja sonst nicht fragen, wenn es nicht "wichtig" wäre
wie oft: für eine 1 MiB Datei...über 2^23 Zugriffe auf die Struktur
BadCop
2011-11-25, 20:14:51
hm, persönlich würd ich da einen Pointer vorziehen. Ist fraglich was das überhaupt für ne Struktur da ist, aber geht da eventl was zu parallelisieren? Threading bietet sich hier eventl an.
Hab mal ein XML-Parser gebaut der je nach CPUTyp n Threads generiert und so das ganze schon erheblich beschleunigt. Die XML-Files waren da aber auch nur 15-20MB gross. Keine Ahnung was bei dir da für Dimensionen anfallen.
Exxtreme
2011-11-25, 20:36:40
Endgültige Gewissheit sollten Tests zeigen. Sprich, beide Varianten ausprobieren und dann testen. Die Zeiger-Variante dürfte aber idR. schneller sein. Da ein Zeiger kleiner ist als eine Struktur.
Nimm ne Referenz, dann kannst du's einfach austesten.
ist ne referenz nicht intern auch nur nen Pointer?
wenn ich es als Referenz mache kann ich der Referenz im Constructor keine Kopie zuweisen (ach erst zuweisen, dann kopieren, gemein)
es kommt "uninitialized referenze member"
das geht
MyConstructor(tMyParam &Param):MyParam(Param)
habe jetzt 3 Varianten ausprobiert
Referenz übergeben, Zeiger zum Ansprechen: 28.813s,28.159s, 28.283s
Referenz übergeben, Kopie zum Ansprechen: 28.111s, 28.470s, 28.283s
Komplett übergeben, Kopie zum Ansprechen: 27.878s, 27.909s, 28.221s
bringt also nix
del_4901
2011-11-26, 01:02:55
Fuehlt sich fuer mich nach einem Cache Bottleneck an. Welche Platform, wie ist die Lokalitaet der Daten?
Gnafoo
2011-11-26, 12:41:21
Hast du schon mit einem Profiler verifiziert, ob der Engpass überhaupt an der Stelle ist, an der du gerade optimierst? Es ist erstaunlich schwer, so etwas selbst abzuschätzen.
Zu Frage 1:
Du kannst den „[][]-operator“ sowieso nicht überschreiben. Es gibt nur einen []-operator mit einem Index. Was du allerdings machen kannst ist folgendes: der []-operator gibt ein Objekt zurück, welches ebenfalls den []-operator überlädt. Dann hast du die [][]-Syntax und du kannst beide Stufen unterschiedlich handhaben. Alternativ kann man auch den „()-operator“ überladen. Der erlaubt beliebig viele Parameter.
http://stackoverflow.com/questions/1936399/c-array-operator-with-multiple-arguments
Zu Frage 2:
Ich persönlich würde die Struktur als Wert übergeben, wenn es nur um 4–5 Werte geht. Größere Strukturen dann als const Reference. Wenn die Stelle tatsächlich Performance-kritisch ist (→ Profiler), dann einfach ausprobieren, was schneller ist.
ich danke euch für die Antworten
das Bottleneck ist woanders, es war bloß eine einfache Möglichkeit vielleicht ein paar Takte rauszukitzeln
ich habe eine ca. 1GB große Hashtabelle auf die ich praktisch wahllos zugreife :freak:
del_4901
2011-11-26, 19:42:15
Mhm, haengen an der Hashtabelle teuere Berechnungen hintendran? Sind die Zugriffe weitestgehend unabhaenig voneinander? In dem Fall lohnt sich evtl. ein 2-pass Herangehensweise. Damit die Cache-Misses dir nicht andauernd in deine Berechnungen funken. Wenn haeufig mehrmals dieselben Werte geholt werden lohnt es sich evtl. eine mehrstufige Hashtabelle zu bauen wo haeufige werte gecached werden.
leider alles seriell, d.h. auf 8 Hashzugriffe folgen diverse Berechnungen
da gibt es einen Workaround, so dass man mehrere Hashelemente ähnlichen Typs in eine Cacheline schreibt...aber nunja das steht bei mir eher hinten
die Datenstruktur ist für diesen Zweck eh etwas hinderlich
würde es was bringen z.B., statt
p1=Hash[1]
p2=Hash[2]
p3=Hash[3]
p=Func(p1,p2)
p=Func(p,p3)
Folgendes zu machen
p1=Hash[1]
p2=Hash[2]
p=Func(p1,p2)
p3=Hash[3]
p=Func(p,p3)
del_4901
2011-11-27, 14:44:38
leider alles seriell, d.h. auf 8 Hashzugriffe folgen diverse Berechnungen
da gibt es einen Workaround, so dass man mehrere Hashelemente ähnlichen Typs in eine Cacheline schreibt...aber nunja das steht bei mir eher hinten
die Datenstruktur ist für diesen Zweck eh etwas hinderlich
Das klingt fuer mich aber sehr vernuentig.
würde es was bringen z.B., statt
p1=Hash[1]
p2=Hash[2]
p3=Hash[3]
p=Func(p1,p2)
p=Func(p,p3)
Folgendes zu machen
p1=Hash[1]
p2=Hash[2]
p=Func(p1,p2)
p3=Hash[3]
p=Func(p,p3)
Das waehre warscheinlich eher kontraproduktiv.
1) Reads/Writes sind alle aligned?
2) Wird die Hashmap veraendert? (Nicht das Reads und Writes kollidieren)
3) Mit was fuer Datentypen jonglierst du da? (BYTES, WORDS (x64 auch DWORDS) koennen sehr langsam werden, da haeufig Kollisionen entstehen)
4) Alloziert die Hashmap dynamisch? Vllt. bringt es schon was wenn du diese (bestimmte.. zB TreeNodes) Alloziierungen poolst und in einem Speicherblock hintereinander liegen hast.
5) Multithreaded? Vllt. rennen auch viele in den gleichen Lock? (evtl. Allocator Lock)
6) Multithreaded? Vllt. Kaempfen die CPUs auch um die Cacheline und invallidieren sie sich gegenseitig.
7) Was sagt der Profiler? Kannst du Screenshoots machen?
8) Du kannst es auch mit _mm_prefetch/__dcbt versuchen
Das waehre warscheinlich eher kontraproduktiv.
dache ich auch
1) Reads/Writes sind alle aligned?
geht so wie es jetzt ist nicht, da ein Hashelement 3-byte breit ist :|, 1-Byte checksum, 2-byte value
2) Wird die Hashmap veraendert? (Nicht das Reads und Writes kollidieren)
i.A. erst nach den Berechnungen
4) Alloziert die Hashmap dynamisch? Vllt. bringt es schon was wenn du diese (bestimmte.. zB TreeNodes) Alloziierungen poolst und in einem Speicherblock hintereinander liegen hast.
ja dynamisch zu Beginn...am Block
5) Multithreaded? Vllt. rennen auch viele in den gleichen Lock? (evtl. Allocator Lock)
6) Multithreaded? Vllt. Kaempfen die CPUs auch um die Cacheline und invallidieren sie sich gegenseitig.
nope
7) Was sagt der Profiler? Kannst du Screenshoots machen?
da bin ich mal gespannt, da muss ich mich mal kurz einarbeiten
generell würde ich gern was gänzlich anderes nehmen, aber speed ist mir oft erst einmal zweitrangig
ich danke dir erst einmal, habe erst am WE wieder Zeit für Hobbies
kurze Frage vielleicht noch, gibt es einen sinnvollen Grund warum in der STL die Template-Funktion Max so definiert ist
template <class T> const T& max ( const T& a, const T& b ) {
return (a<b)?b:a;
}
und nicht so
template <class T> T max (T a, T b ) {
return (a<b)?b:a;
}
da kommt bei verschachtelungen irgendwie totaler quatsch raus, warum weiß ich gerade nicht, arbeite selten mit referenzen
Marscel
2011-11-28, 21:56:39
template <class T> const T& max ( const T& a, const T& b ) {
return (a<b)?b:a;
}
und nicht so
template <class T> T max (T a, T b ) {
return (a<b)?b:a;
}
Der Aufruf würde sonst drei Kopiervorgänge mit sich ziehen, zwei für die Argumente, einen für die Rückgabe. Stattdessen werden nur die Adressen rumgereicht und dann implizit dereferenziert. Außerdem können damit konstante Objekte benutzt werden, das würde sonst einen Compilerfehler geben.
aber
int a=-2;
int b=5;
int v=max(abs(a),abs(b))
kommt müll heraus, int v=max(abs(-2),abs(5)) geht natürlich
Marscel
2011-11-28, 22:17:00
kommt müll heraus, int v=max(abs(-2),abs(5)) geht natürlich
Müll? Ich erhalte immer 5.
ich die adresse von b, kann aber auch am Bordland Compiler liegen
edit: mit meinem gcc gehts
schön 25.178s obwohl 20% untertaktet
del_4901
2011-11-29, 00:24:11
schön 25.178s obwohl 20% untertaktetdas klemmt garantiert woanders, probiere es mal mit prefetching die cmds dazu findest du inter 8)
Was du prefetchen musst sagt dir der profiler.
vBulletin®, Copyright ©2000-2025, Jelsoft Enterprises Ltd.