Hallo Forum
In einem Projekt (RealView Compiler, LM3S1968) wird ein grosser Struct,
bestehend aus 3008 Float (à 4-Bytes) benützt, macht also 12038 Bytes.
Diese Struktur enthält vordefinierte Kurvendaten, die konstant sind und
bleiben.
Gegenwärtig wird der Struct wie folgt deklariert:
1
TDataData={
2
{0.004133f,0.000003f,0.000000f},
3
{0.004546f,0.000023f,0.005283f},
4
...}
So wie ich das verstehe, liegt der Struct im RAM. Ferner wird irgend wo
Initialisierungscode liegen, welcher nach einem Reset die Werte ins RAM
schreibt.
Nun dachte ich, es wäre effizienter, wenn ich den Struct als const
deklariere:
1
constTDataData={
2
{0.004133f,0.000003f,0.000000f},
3
{0.004546f,0.000023f,0.005283f},
4
...}
Dann wäre 1. sichergestellt, dass niemand mehr darauf schreiben kann, 2.
müsste der Initialisierungscode entfallen und folglich weniger Flash
belegt werden.
Meine Erwartung (2.) wird aber nicht erfüllt, und ich verstehe nicht
warum:
variabel const
Code 146904 146880
ROdata 41800 53832
RWdata 13944 1912
ZIdata 35984 35984
Code used 200724 201100
Der Unterschied bei ROdata beträgt 12038, ebenso bei RWdata, wie
erwartet, da der Struct vom einen in den anderen Bereich wandert. Der
Code bleibt aber praktisch gleich gross. Insgesamt belegt die "const"
Variante mehr Platz im Flash!
Der Code für die Initialisierung von "Flash -> RAM" im Startup ist
"immer" vorhanden, da spielt es keine Rolle, wie viel kopiert wird. Da
fällt nichts weg.
An Deiner Rechnung verstehe ich nicht, weshalb bei (2) ganz unten eine
größere Zahl steht, obwohl die Einzelwerte in Summe kleiner sind
(verglichen mit (1)). Was bedeutet "Code used"?
Ist der einzige Unterschied zwischen den beiden Varianten nur das
"const"?
Spielt hier u. U. ein "alignment" eine Rolle, welches sich ungünstig für
Variante (2) auswirkt, da dort in diesem Fall der Verschnitt größer ist?
> da spielt es keine Rolle, wie viel kopiert wird. Da fällt nichts weg.
Doch muss aber, weil im einen Fall 13944 Bytes und im anderen Fall nur
1912 Bytes kopiert werden müssen. Die Initialwerte müssen ja auch
"irgendwo" stehen, da sie ja praktisch alle unterschiedlich sind.
Der Unterschied im Code ist einzig die Zeile mit dem "const".
Die Initialwerte sind bei beiden Varianten im Code vorhanden. Und für
den Init Code selbst ändert sich maximal eine Iterations Variable,
welche die Größe der zu kopierenden Daten repräsentiert.
StinkyWinky schrieb:>> da spielt es keine Rolle, wie viel kopiert wird. Da fällt nichts weg.>> Doch muss aber, weil im einen Fall 13944 Bytes und im anderen Fall nur> 1912 Bytes kopiert werden müssen.
Das ist doch völlig egal.
Das ist doch nur ein Zahlenwert bei
for( i = 0; i < 13944; i++ )
*Ziel++ = *Quelle++;
Ein Compiler wird sich allerdings nach Möglichkeit ALLE zu
initialisierenden Variablen zusammenfassen, so dass in Wirklichkeit
nicht 13944 steht, sondern eine höhere Zahl. Eben die Summe aller
Variablen die initialisiert werden müssen. Und ob dann in dieser
Schleife bis 25000 oder nur bis 14000 gezählt wird, ändert am Code ja
nichts.
> Die Initialwerte müssen ja auch> "irgendwo" stehen, da sie ja praktisch alle unterschiedlich sind.
Natürlich. Aber den Anteil hast du ja trotzdem. Denn: irgendwo müssen
die Daten ja erst mal sein. Der einzige Unterschied: im einen Fall
werden sie dann zusätzlich noch ins RAM umkopiert was im anderen Fall
unterbleibt.
Wenn "const" Daten direkt im Flash angesprochen werden, was bei ARM
problemlos möglich ist (im Unterschied zu AVR), dann entfällt die
Notwendigkeit, diese Daten aus dem ROM ins RAM umzukopieren. Somit
sollten sie in der RAM-Version zweimal und in der ROM-Version einmal im
Adressraum auftauchen. Im Image hingegen sollten sie in beiden Fällen
nur einmal auftauchen, da der Inhalt der RAM-Section dort keinen Sinn
ergibt.
Anders sieht es aus, wenn der Compiler auch "const" Daten ins RAM legt,
beispielsweise weil der Zugriff darauf üblicherweise schneller ist als
auf das ROM. Dann ändert sich substantiell überhaupt nichts.
Der Groschen ist gefallen:
Anstelle der Initialwerte für die Kopiererei in das RAM, steht halt der
Struct fixfertig initialisiert im ROM (Flash). Beides braucht gleich
viel Paltz.
Danke sehr!
Nur so am Rande:
Es gibt Architekturen (z.B. TC1796), wo ein Datenzugriff (nicht
Programmcodezugriff!) ins Flashs deutlich langsamer ist als ins RAM
(weil ein anderer Weg über interne Busse genommen wird). Hier macht es
durchaus Sinn, bestimmte konstante Daten ins RAM zulegen, um CPU-Zeit zu
sparen.
Eine eigene Frage?
Dieser Thread ist über 14 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.