Forum: Compiler & IDEs 'volatile' und Cache


von Wolattila (Gast)


Lesenswert?

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.)

von Wolattila (Gast)


Lesenswert?

Achja: Ich rede von C! :-)

von (prx) A. K. (prx)


Lesenswert?

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.

von 2ter Gast (Gast)


Lesenswert?

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)

von (prx) A. K. (prx)


Lesenswert?

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.

von Wolattila (Gast)


Lesenswert?

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.

von 2ter Gast (Gast)


Lesenswert?

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.

von 2ter Gast (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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.

von 2ter Gast (Gast)


Lesenswert?

Ist zwar C++ aber sollte hilfreich sein.
http://msdn.microsoft.com/de-de/library/12a04hfd.aspx

von (prx) A. K. (prx)


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Wolattila (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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
Noch kein Account? Hier anmelden.