C Globales Array effizient zugreifen in Funktion

hell-student

Lieutenant
Registriert
Nov. 2007
Beiträge
671
Guten Tag,

Ich muss meinen Code, der in C geschrieben ist, optimieren, da die Laufzeit noch zu hoch ist. Wie greife ich am besten auf ein globales Array zu? Leider muss ich diese Daten global machen. Es handelt sich hierbei um ein Array von Structs. Sollte ich mir in meiner Funktion eine Kopie erstellen und am Schluss das Array wieder aktualisieren (kostet bestimmt auch einiges an Performance), da ich oft darauf zugreife, oder lieber einen globalen Pointer verwenden? Was ist die effizienteste Variante in einer Funktion?
 
Ist doch egal ob das Array global ist oder nicht, die Laufzeit ist die selbe.
 
natürlich ist der globale Pointer das effizienteste
du must nichts kopieren, keine doppelgleisigkeit usw.

Funktionieren tut das aber nur wenn du kein Multithreading code auf die Struktur zugreift
den dann musst du mit Locks/Semaphoren sicherstellen das nur ein Thread auf die Daten zugreift. Das kann aufwendiger sein als wenn man die Daten gleich kopiert.

Bevor du da aber blind zum optimieren anfängst, schau mal mit einen Profiler nach wo die Zeit in der Funktion liegen bleibt.
nicht das du den ganzen Aufwand treibst um nur 10% der Zeit zu optimieren.

Wichtigster Grundsatz beim Optimieren:
Immer zuerst Messen bevor du was tust!
 
Prinzipiell haben meine Vorredner recht, wobei auch nicht ganz unter bestimmten Bedingungen. Die globalen Variablen liegen im RAM bzw SRAM. Die lokalen Variablen können jedoch in einigen Prozessorregistern abgelegt werden. Hängt von der Prozessorarchitektur ab. Und wenn noch die Zugriffe auf den RAM langsamer sind als auf die eigenen Prozessorregister, kannst du durchaus die Performance beeinflussen. Jedoch erlaubt dir C keine explizite Steuerung, wann welche lokale Variable wo abgelegt wird, zumindest ist es mir nicht bekannt. Lerne aber auch gerne dazu.

Worauf du achten kannst, ist ob Teile vom struct, die struct selber oder das Array "volatile" sind. Das führt dazu, dass absolut jeder Zugriff direkt auf dem RAM erfolgt. Wenn du volatile vermeiden kannst, dann wird C nach Bedarf die Inhalte oder Teile der struct in die Prozessorregister laden und darauf dann zugreifen.

Ein globaler Pointer macht hier keinen Unterschied, solange die Arraygröße nicht größer als die vom Prozessor vorgesehene Direktindizierungsgröße ist. Wobei glaube ich bei einer struct diese eh nicht greifen wird, sprich der Compiler macht eh darauf dann "Pointer"-Zugriffe mit entsprechender Pointerarithmetik. Du kannst natürlich explizit auf Pointer setzen (hier wären lokale Pointer sogar ein Tick effizienter, da diese ggf. in den Registern abgelegt werden), aber macht wirklich nur den unterschied, wenn du Querbeet auf die Arrayelemente zugreifst.

Naja ist alles nicht so einfach, hier wäre vielleicht deine Funktion als Code hilfreich. Vielleicht kannst/darfst du diesen posten?

Ansonsten stimme ich dem zu:

Wichtigster Grundsatz beim Optimieren:
Immer zuerst Messen bevor du was tust!

Gruß slash
 
Zuletzt bearbeitet:
Danke für die Antworten.

Gemessen habe ich einiges, doch nie genaue Werte erhalten, da alles auf einem FPGA läuft mit einer Clock von 10 ms (Muss eigentlich im ns Bereich messen). Daher verwende ich eine Implementierung, bei der Register genutzt werden, damit ich sehen kann, wieviel Cycles btw wieviele Instruktionen ausgeführt werden. Das mit den Prozessorregistern stimmt schon. Habe auch gemerkt, dass wenn ich register unsigned int bla statt unsigned int bla schreibe, dass dies bei oft zugegriffenen Variablen was hilft.
 
slashmaxx schrieb:
Prinzipiell haben meine Vorredner recht, wobei auch nicht ganz unter bestimmten Bedingungen. Die globalen Variablen liegen im RAM bzw SRAM. Die lokalen Variablen können jedoch in einigen Prozessorregistern abgelegt werden. Hängt von der Prozessorarchitektur ab. Und wenn noch die Zugriffe auf den RAM langsamer sind als auf die eigenen Prozessorregister, kannst du durchaus die Performance beeinflussen. Jedoch erlaubt dir C keine explizite Steuerung, wann welche lokale Variable wo abgelegt wird, zumindest ist es mir nicht bekannt. Lerne aber auch gerne dazu.

Sollte der Compiler nicht alles Zwischenspeichern was geht? Wenn es freie callee saved Register gibt können diese verwendet werden, oder nicht?
 
Also zuerst würd ich mal gucken, was der Algorithmus für ne Komplexitätsklasse hat und ob man die verringern kann. Das sollte schon mal helfen.

Dann: Wie sieht es mit Latenz aus? Bei einem modernen x86 kann eine etwas linearere Struktur gleich mal 50% mehr Speed geben.
Was ist auf dem FPGA teuer? Speicherzugriff? Fließkomma? Damit kann man ja abschätzen, was Zeit kostet.
Sonst: Schau mal, ob die NOOPs einbauen kannst, dann siehst du gut, was du maximal an Zuwachs erwarten kannst.
 
slashmaxx schrieb:
Prinzipiell haben meine Vorredner recht, wobei auch nicht ganz unter bestimmten Bedingungen. Die globalen Variablen liegen im RAM bzw SRAM. Die lokalen Variablen können jedoch in einigen Prozessorregistern abgelegt werden. Hängt von der Prozessorarchitektur ab. Und wenn noch die Zugriffe auf den RAM langsamer sind als auf die eigenen Prozessorregister, kannst du durchaus die Performance beeinflussen. Jedoch erlaubt dir C keine explizite Steuerung, wann welche lokale Variable wo abgelegt wird, zumindest ist es mir nicht bekannt. Lerne aber auch gerne dazu.
also 1. gilt deine aussage für die lokalen veriablen genau so auch für globale
2. schlag mal das key-word "register" nach. das erlaubt zu steuern, dass bestimmte variablen in register gehalten werden sollen. natürlich gibt es da einschränkungen, da man ja nicht beliebig viele register hat. auch können bestimmte compiler-einstellungen das zu nichte machen. aber es geht sehr wohl.
 
NemesisFS schrieb:
Sollte der Compiler nicht alles Zwischenspeichern was geht? Wenn es freie callee saved Register gibt können diese verwendet werden, oder nicht?

Denke schon. Sollte davon abhängen wieviele noch frei sind.


Dese schrieb:
also 1. gilt deine aussage für die lokalen veriablen genau so auch für globale
Vielleicht hab ich mich nur falsch ausgedrückt. Natürlich kann auch eine globale Variable in ein Register gecached werden. Aber hierzu ist ein lesender RAM Zugriff nötig und spätestens beim verlassen der Funktion ein schreibender. Eine lokale Variable kann dahingehen auch direkt einem Register angelegt werden und muss dann aber auch nirgendshin zurückgeschrieben werden. Unterschiede hinsichtlich Handling und der Performance gibts dann meiner Meinung doch.


Dese schrieb:
2. schlag mal das key-word "register" nach. das erlaubt zu steuern, dass bestimmte variablen in register gehalten werden sollen. natürlich gibt es da einschränkungen, da man ja nicht beliebig viele register hat. auch können bestimmte compiler-einstellungen das zu nichte machen. aber es geht sehr wohl.

Danke, werde ich machen. Die oben gemachte Aussage basiert auf der Unkenntnis des "register" keywords ;-)
Kann eine globale Variable dann permanent in einem CPU Register gehalten werden?

gruß slash
 
Danke, werde ich machen. Die oben gemachte Aussage basiert auf der Unkenntnis des "register" keywords ;-)
Kann eine globale Variable dann permanent in einem CPU Register gehalten werden?

Das Schlüsselwort register geht nur für automatische bzw lokale Variablen. Ausserdem ist es deprecated, weshalb es auch viele moderne Compiler einfach ignorieren. Des Weiteren war es zuvor eher ein Performance-Hint, wodurch der Compiler es auch nach Lust und Laune einfach ignorieren konnte. Des Weiteren kommt hinzu, dass man Register nicht dynamisch indexieren kann; dh das Registerschlüsselwort war nur bei statisch indexierten Variablen (???oder bei Variablen, wo der Compiler eine statische Indexierung durch Optimierung erreichen konnte???) erlaubt.
 
Zuletzt bearbeitet:
Nai schrieb:
Das Schlüsselwort register geht nur für automatische bzw lokale Variablen. Ausserdem ist es deprecated, weshalb es auch viele moderne Compiler einfach ignorieren. Des Weiteren war es zuvor eher ein Performance-Hint, wodurch der Compiler es auch nach Lust und Laune einfach ignorieren konnte. Des Weiteren kommt hinzu, dass man Register nicht dynamisch indexieren kann; dh das Registerschlüsselwort war nur bei statisch indexierten Variablen (???oder bei Variablen, wo der Compiler eine statische Indexierung durch Optimierung erreichen konnte???) erlaubt.

Danke für die Hintergrundinfos.
 
Zurück
Oben