Forum: Mikrocontroller und Digitale Elektronik Riesiges Array in C


von Array on Diet (Gast)


Lesenswert?

Ich "möchte" (ich bin mir sicher das eigentlich nicht zu wollen und 
suche nach einer vernünftigen Lösung) in C ein grosses Array verwenden 
(z.B. um Messdaten abzuspeichern, momentan gehts aber eher ums Prinzip). 
Die Plattform ist ein Zynq mit insgesamt 1 GB RAM. In einem naiven 
Ansatz habe ich nun einfach ein grosses Array definiert:
1
uint32_t TestArray[125000000];

Da ein unit32_t 4 bytes benötigt belegt das Array also gut 500 MB (den 
halben Speicher).
Eigentlich hätte ich erwartet, dass der Compiler (bzw. Linker) sich 
beschwert, aber er frisst das ganze ohne Probleme.

Als nächsten Schritt habe ich eine Schleife geschrieben die das Array 
mit unnützen Daten beschreibt, zudem gibt die Schleife für jeden 
Millionsten Eintrag eine Meldung aus damit ich ein Gefühl für die 
benötigte Zeit bekommen. Dabei viel mir auf:
- für die ersten 40 Blöcke (à 1e6 uint32_t Werte, also 4e6 bytes) 
benötigt das Programm pro Block ca. eine Sekunde.
- Von da an wird die Zeit massiv länger, ein Block benötigt dann etwa 10 
Sekunden

Die Frage die sich mir nun stellt:
- Wo wird das Array abgespeichert? Ich dachte Arrays laden auf dem 
Stack, das erscheint mir bei der Grösse aber wenig realistisch, zudem 
ist der Stack laut Linker Script nur 64 kB gross
- Woher kommt die massiv länger Schreibzeit ab Block 40? Der Zynq hat 
256 kB internen Speicher, das reicht aber nicht ansatzweise für 40 
Blöcke. Der L2 Chache ist mit 512 kB auch nicht gross genug um irgendwas 
in der Grössenordnung zu halten.
- Wie macht man so etwas richtig? Die Idee, ein Riesenarray zu 
definieren erscheint mir nicht wirklich sinnvoll, ehrlicherweise fällt 
mir allerdings nichts besseres ein. Es geht eigentlich darum, 
Referenzwerte zu generieren die dann per DMA vom FPGA Teil aus dem 
Speicher gelesen werden. Die Samplerate ist dabei allerdings zwischen 10 
MHz und 50 MHz auf mehreren Kanälen, eine Online-Generierung per CPU 
geht sich also zeitlich niemals aus.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Array on Diet schrieb:
> Ich dachte Arrays laden auf dem Stack, das erscheint mir bei der Grösse
> aber wenig realistisch, zudem ist der Stack laut Linker Script nur 64 kB
> gross

Kommt drauf an. Wenn Du es lokal innerhalb einer Funktion definierst, 
kommt es auf den Stack. Globale Arrays und auch static Arrays (innerhalb 
einer Funktion) kommen nicht auf den Stack.

Nur letzteres ist sinnvoll bei einer derartigen Größe.

von Oliver S. (oliverso)


Lesenswert?

Wenn du das Array global deklarierst hast, liegt das nicht auf dem 
Stack, sondern in .bss. Über alles andere sollte dir die Doku deiner 
toolchain und des (ungenannten) Betriebssystems Auskunft geben.

Du kannst ja mal schauen, was passiert, wenn du das array auf dem heap 
anlegen willst. Da meldet dir malloc zumindest zurück, ob das geklappt 
hat.

Oliver

von Array on Diet (Gast)


Lesenswert?

Frank M. schrieb:
> Kommt drauf an. Wenn Du es lokal innerhalb einer Funktion definierst,
> kommt es auf den Stack. Globale Arrays und auch static Arrays (innerhalb
> einer Funktion) kommen nicht auf den Stack.

Danke, das erklärt schon mal wieso ich Platz dafür habe (das Array is 
global).

Oliver S. schrieb:
> Über alles andere sollte dir die Doku deiner
> toolchain und des (ungenannten) Betriebssystems Auskunft geben.

Die Toolchain ist Xilinx SDK, es gibt kein Betriebssystem (SDK 
bezeichnet das als "baremetal application").

Oliver S. schrieb:
> Du kannst ja mal schauen, was passiert, wenn du das array auf dem heap
> anlegen willst. Da meldet dir malloc zumindest zurück, ob das geklappt
> hat.

Werde ich bei Gelegenheit machen.

von Gerald K. (geku)


Lesenswert?

Array on Diet schrieb:
> - für die ersten 40 Blöcke (à 1e6 uint32_t Werte, also 4e6 bytes)
> benötigt das Programm pro Block ca. eine Sekunde.
> - Von da an wird die Zeit massiv länger, ein Block benötigt dann etwa 10
> Sekunden

Kann es nicht sein, dass ein Teil  des Arrays ins Flash ausgelagert 
wird?

https://de.m.wikipedia.org/wiki/Auslagerungsdatei

von xyz (Gast)


Lesenswert?

> es gibt kein Betriebssystem

> dass ein Teil  des Arrays ins Flash ausgelagert wird?

Wohl kaum.

von Udo S. (urschmitt)


Lesenswert?

Array on Diet schrieb:
> (ich bin mir sicher das eigentlich nicht zu wollen und
> suche nach einer vernünftigen Lösung) in C ein grosses Array verwenden
> (z.B. um Messdaten abzuspeichern, momentan gehts aber eher ums Prinzip)

Das kommt immer darauf an was du mit dem Array vorhast und wie schnell 
du an die Daten musst.
Abspeichern von Messdaten macht man eher auf eine sequentielle Datei. 
Chronologisches Suchen oder sequentielles Verarbeiten geht dann auch 
noch halbwegs schnell.
Für dünn besetzte Arrays gibt es extra Algorithmen, die das nicht als 
riesiges fast leeres Array anlegen, sondern als Listen oder Bäume.

Wenn du aber maximal schnell wahlfrei auf alle Elemente zugreifen können 
musst bleibt nur das Array im Speicher solange es passt.

Array on Diet schrieb:
> Es geht eigentlich darum,
> Referenzwerte zu generieren die dann per DMA vom FPGA Teil aus dem
> Speicher gelesen werden. Die Samplerate ist dabei allerdings zwischen 10
> MHz und 50 MHz auf mehreren Kanälen, eine Online-Generierung per CPU
> geht sich also zeitlich niemals aus.

Verstehe ich nicht so ganz, aber bei der Geschwindigkeit bleibt dir 
ausser im Speicher halten nichts anderes.

von Axel S. (a-za-z0-9)


Lesenswert?

Array on Diet schrieb:
> Oliver S. schrieb:
>> Über alles andere sollte dir die Doku deiner
>> toolchain und des (ungenannten) Betriebssystems Auskunft geben.
>
> Die Toolchain ist Xilinx SDK, es gibt kein Betriebssystem (SDK
> bezeichnet das als "baremetal application").

Wenn es kein Betriebssystem gibt, wird der Krempel statisch im Adreßraum 
angeordnet. Vom Linker nach Vorgabe des Linkerskripts. Der hätte sich 
dann schon beschwert, wenn das nicht reinpaßt. Irgendeine lazy 
Allocation gibt es dann auch nicht. Tatsächlich muß der Laufzeitcode ein 
globales Array vor dem Aufruf von main() auch initialisieren (vulgo: 
beschreiben).

Array on Diet schrieb:
> Woher kommt die massiv länger Schreibzeit ab Block 40? Der Zynq hat
> 256 kB internen Speicher

Speicher? Meinst du L1 Cache? Oder hat das SoC internen und externen 
RAM?

> das reicht aber nicht ansatzweise für 40
> Blöcke. Der L2 Chache ist mit 512 kB auch nicht gross genug

Ich kenne die Architektur nicht. Vielleicht ist ja nicht aller RAM 
gleichmäßig schnell an alle Kerne angebunden (NUMA)? Und dann haben 
etliche ARMe ja auch mehrere RAM Regionen. Mancher RAM hängt direkt an 
der CPU, anderer wird über einen Peripheriebus angesprochen. Wenn da ein 
Bus langsamer getaktet ist, kann das gut zum beobachteten Faktor 10 
führen.

von Mark B. (markbrandis)


Lesenswert?

Array on Diet schrieb:
> Ich "möchte" (ich bin mir sicher das eigentlich nicht zu wollen und
> suche nach einer vernünftigen Lösung) in C ein grosses Array verwenden
> (z.B. um Messdaten abzuspeichern, momentan gehts aber eher ums Prinzip).
> Die Plattform ist ein Zynq mit insgesamt 1 GB RAM. In einem naiven
> Ansatz habe ich nun einfach ein grosses Array definiert

Ich bin mir ziemlich brutal sicher ;-) dass Du nicht alle diese Daten 
gleichzeitig im Speicher benötigen wirst. Sondern eben nur einen Teil 
davon, der gerade groß genug ist um die jeweils benötigten Berechnungen 
anzustellen. Der Ansatz wäre also:

1.) Herausfinden, wieviel Speicher man tatsächlich benötigt für: 
Eingangsadaten und Ablage der Ergebnisse (evtl. auch Zwischenergebnisse)
2.) Diese Menge an Speicher allokieren

von Einer K. (Gast)


Lesenswert?

Axel S. schrieb:
> Tatsächlich muß der Laufzeitcode ein
> globales Array vor dem Aufruf von main() auch initialisieren (vulgo:
> beschreiben).
Naja...
Mein lieblings Gcc kennt eine .noinit Section.
Andere machen es lieber mit #pragma NOINIT

Also:
Grundsätzlich stimmt deine Aussage, aber es ist keine Mussbedingung, 
sondern mit Alternativen versehen.

von xyz (Gast)


Lesenswert?

> mehrere RAM Regionen

Womoeglich ist nur der Cache falsch konfiguriert.

von Wolfgang (Gast)


Lesenswert?

Array on Diet schrieb:
> Die Frage die sich mir nun stellt:
> - Wo wird das Array abgespeichert?

Der Compiler/Linker wird's wissen. Guck mal in den Listing-File den 
deine Tool Chain erstellt oder zumindest erstellen kann.

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.