Wenn eine Variable mit 'volatile' attributiert ist, dann ist der Compiler ja verpflichtet, die Variable bei jedem Zugriff explizit einlesen bzw. zurückschreiben zu lassen. Ein paar Aspekte sind mir aber nicht klar: - Bei Prozessoren mit Cache: Darf die Variable im Cache benutzt werden, oder muss der Compiler explizit ein Laden aus dem Hauptspeicher verlangen? - Muss der Compiler einen Lesezugriff auch dann ausführen lassen, wenn er ihn bei der Optimierung als sinnlos erachtet? (Z.B., weil die Variable nur gelesen wird, aber nichts weiter geschieht.)
Wolattila schrieb: > - Bei Prozessoren mit Cache: Darf die Variable im Cache benutzt werden, Ja. > - Muss der Compiler einen Lesezugriff auch dann ausführen lassen, wenn > er ihn bei der Optimierung als sinnlos erachtet? (Z.B., weil die > Variable nur gelesen wird, aber nichts weiter geschieht.) Ja. Bei volatile char a; a; muss ein Lesezugriff erfolgen.
zu 1) Die Variable muss sich im Arbeitsspeicher befinden und wird nicht gecachet. Stell dir ein memory-mapped system vor, in dem deine volatile variable auf ein hardware peripheral register zeigt. zu 2) Der Compiler optimiert die nicht weg, wg siehe Bsp. von 1)
2ter Gast schrieb: > Die Variable muss sich im Arbeitsspeicher befinden und wird nicht > gecachet. Falsch. Was C und volatile angeht. Ein C Compiler interessiert sich kein bischen dafür, was cachable ist und was nicht. Auch nicht mit volatile. > Stell dir ein memory-mapped system vor, in dem deine volatile variable > auf ein hardware peripheral register zeigt. Andere Baustelle. I/O-Register und Dual-Port Memory vom Caching auszunehmen ist nicht Sache des Compilers, sondern von Hardware oder MMU-Konfiguration.
A. K. schrieb: > Falsch. Was C und volatile angeht. Ein C Compiler interessiert sich kein > bischen dafür, was cachable ist und was nicht. Auch nicht mit volatile. Das habe ich vermutet. Der Compiler "sieht" den Cache gar nicht, sondern muss sich darauf verlassen, dass der Prozessor für Kohärenz sorgt zwischen allem, was er cacht und der tatsächlichen Aussenwelt.
A. K. schrieb: > I/O-Register und Dual-Port Memory vom Caching > auszunehmen ist nicht Sache des Compilers, sondern der Hardware oder der > MMU. Woher kennt dein Compiler den Aufbau deines uC-System? Stichwort FPGA und Soft-Core! A. K. schrieb: > Falsch. Was C und volatile angeht. Wo landet denn eine Deklaration?
1 | volatile char a; |
dein Compiler wird die Variable im Hauptspeicher anlegen; es sei du generierst ein Ptr und setzt selbst die Adresse.
Anmerkung bei dem Nios II von Altera umgeht man den Cache auf zwei Arten, 1) mit volatile 2) auf Nios II Art, in dem die Adresse mit 0x80000000U verodert wird.
2ter Gast schrieb: > Woher kennt dein Compiler den Aufbau deines uC-System? Überhaupt nicht. Der Linker weiss dank Adressraumbeschreibung ein bischen mehr, aber das ist hier nicht relevant. > dein Compiler wird die Variable im Hauptspeicher anlegen Richtig. Und das ist auch völlig korrekt. Was C angeht. Ob das dem entspricht was du dir dabei gedacht hast ist nicht sein Problem. Wenn das eine Speicherstelle ist, die als memory mapped i/o dient, dann ist es nicht Sache des Compilers, dafür zu sorgen, dass die Variable (bzw. dieser Speicherbereich) nicht gecached wird. Wenn du erreichen willst, dass die Variable in einem nicht gecachten Bereich liegt, dann musst du den Compiler über nicht standardisierte Verfahren wie die GCC attributes davon überzeugen.
2ter Gast schrieb: > 1) mit volatile Das hat dann aber nichts mit dem C Standard zu tun, sondern ist eine Spezialität dieser einen Plattform und dessen Entwicklungssystems. Du kannst das auf jedem beliebigen C Compiler für PCs ausprobieren. Du wirst im erzeugten Code keinerlei Adressraumspezifika für die Variable oder gar explizite Cache-Control-Befehle finden.
A. K. schrieb: >> - Muss der Compiler einen Lesezugriff auch dann ausführen lassen, wenn >> er ihn bei der Optimierung als sinnlos erachtet? (Z.B., weil die >> Variable nur gelesen wird, aber nichts weiter geschieht.) > > Ja. Bei > volatile char a; > a; > muss ein Lesezugriff erfolgen. Jein. Bei GCC ist das der Fall: Implementation defined, C90 6.5.3, C99 6.7.3 http://gcc.gnu.org/onlinedocs/gcc/Qualifiers-implementation.html#Qualifiers-implementation Was den Cache angeht, gibt's in GCC Builtins wie __builtin___clear_cache. Die Implementierung dürfte allerdings stark architekturabhängig sein :-) http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#Other-Builtins Ansonsten behilft man sich mit zur Verfügung gestellten Instrinsics oder Inline Assembler, wobei man da schon aufpassen muss, daß einem der Scheduler nicht dazwischen funkt.
Johann L. schrieb: > Jein. Bei GCC ist das der Fall: Implementation defined, C90 6.5.3, C99 > 6.7.3 Thx. Noch verschlüsselter konnte man das im Standard ohne Verwendung von DES wohl nicht ausdrücken. In C99 fand ich dazu ausschliesslich den Satz "What constitutes an access to an object that has volatile-qualified type is implementation-defined.". Sauber.
Ich hab mal einen ARM-Prozessor programmiert, da war einfach alles doppelt in den Adressraum gemappt. Eins der Adressbits oberhalb des regulären Adressraums war dann für den Cache zuständig. Hat man über einen Zeiger zugegriffen, wo das gesetzt war, war der Zugriff ohne Cache, sonst mit. Interessanter wird die Cache-Frage bei Multicore-Systemen, wenn man Daten zwischen Task austauschen will, die auf unterschiedlichen Kernen laufen, die jeweils ihre eigenen (ggf mehrstufigen) Caches haben. Aber dafür gibt's dann memory barriers.
2ter Gast schrieb: > Ist zwar C++ aber sollte hilfreich sein. > http://msdn.microsoft.com/de-de/library/12a04hfd.aspx Darin steht nichts darüber, dass volatiles nicht cachable wären. Nur umgekehrt, uncachables müssen natürlich volatile sein - was sicherzustellen Sache des Programmierers ist, nicht des Compilers.
Rolf Magnus schrieb: > Ich hab mal einen ARM-Prozessor programmiert, da war einfach alles > doppelt in den Adressraum gemappt. STR9: das RAM dreifach, die I/O doppelt. Dabei hat der noch nicht einmal einen Cache, nur ein bischen optionale Pufferung im Systembusinterface (1x gepuffert, 1x ungepuffert) und einen separaten schnellen RAM-Bus am Core. > Aber dafür gibt's dann memory barriers. Aber auch da ist es Sache des Programmierers, sie zu nutzen, nicht des Compilers.
Genau, es geht hier um ein Multicore-System. Schaut ganz danach aus, als hättet ihr Recht: Austausch zwischen 2 Prozessoren ist sehr schnell, so lange der ganze Datensatz im Cache Platz hat. Danach wird er langsamer. Der Compiler umgeht den Cache also nicht. Kann er ja eigentlich auch gar nicht, denn dann müsste der C-Standard ja voraussetzen, dass es einen Cache-Umgehungsmechanismus gibt. Sowas wäre völlig sinnfrei, denn der Cache ist ja per Definition ein völlig transparenter Zwischenspeicher.
Wobei solche Spielchen mit der Performance auch deutlich vom verwendeten Prozessor abhängen können. Das Verhalten und die Art des Datenaustauschs gemeinsamer Daten variiert abhängig von Verbindungstopologie und Art der Methode zur Gewährleistung von Konsistenz. Auch x86 können recht verschieden reagieren. Wenn es um Performance geht, dann kann an dieser Stelle auch explizites Prefetching nützlich werden.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.