LabVIEWForum.de - Probleme beim Verketten von Arrays

LabVIEWForum.de

Normale Version: Probleme beim Verketten von Arrays
Du siehst gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.
Seiten: 1 2 3
1.Problem:
Ich möchte ein Array A mehrfach aneinanderhängen (concatenate).

Also wenn A=[1,2,3]; 3 mal anhängen soll dann z.B. [1,2,3,1,2,3,1,2,3,1,2,3] ergeben.
Habe keine Funktion gefunden, wo man A x-mal ansich selbst anhängen kann. Geht natürlich über Schleife, aber ist langsam bei großen Arrays.

2.Problem:
Habe ein axb Array. Ich möchte dieses Array einmal aneinanderfügen, so dass die Dimension ax2b wird. Geht aber nicht, siehe Bilder.
Aus einem 2x5 Array macht LV nur Arrays mit Dimensionen 2x2x5 oder 4x5. Ich möchte aber, dass so verknüpft wird, dass die Dimension 2x10 ist. Eine Variante wäre natüröich die Einzeldimensionen zu verknüpfen (im Blockdiagramm die beiden linken Arrays), ist aber umständlich.
[attachment=18753]
[attachment=18752]
VI als Version 8.0 gespeichert.
[attachment=18754]
' schrieb:Also wenn A=[1,2,3]; 3 mal anhängen soll dann z.B. [1,2,3,1,2,3,1,2,3,1,2,3] ergeben.
Habe keine Funktion gefunden, wo man A x-mal ansich selbst anhängen kann. Geht natürlich über Schleife, aber ist langsam bei großen Arrays.
So was schreit danach, ein entsprechend großes Array erst mal per "Initialize Array" vorzuinitialisieren und dann in einer Schleife mit "Replace Array Subset" zu arbeiten.
Merke, concetenate ist "langsam", denn bei jedem Aufruf muss neuer Speicher alloziert werden.
' schrieb:Habe ein axb Array. Ich möchte dieses Array einmal aneinanderfügen, so dass die Dimension ax2b wird. Geht aber nicht, siehe Bilder.
Aus einem 2x5 Array macht LV nur Arrays mit Dimensionen 2x2x5 oder 4x5. Ich möchte aber, dass so verknüpft wird, dass die Dimension 2x10 ist. Eine Variante wäre natüröich die Einzeldimensionen zu verknüpfen (im Blockdiagramm die beiden linken Arrays), ist aber umständlich.
Hier zwei funktionierende Möglichkeiten:
[attachment=18758]

Gruß, Jens
' schrieb:So was schreit danach, ein entsprechend großes Array erst mal per "Initialize Array" vorzuinitialisieren und dann in einer Schleife mit "Replace Array Subset" zu arbeiten.
Merke, concetenate ist "langsam", denn bei jedem Aufruf muss neuer Speicher alloziert werden.
Gruß, Jens

Danke für den Tip. Das Array erst zu initialisieren und dann aufzufüllen ist wirklich schneller. Woher weiß man solche Tricks? Komischerweise verstehe ich die Speicherverwaltung noch nicht. In einem einfachen Bsp. ( siehe Bild) wird ein UINT8-Array mit 100 Millionen Einträge erzeugt. Da pro Eintrag 8 bit=1 Byte Speicherplatz benötigt werden, sollten auch etwa 100 Megabyte RAM belastet werden. Es wird aber ziemlich genau die 3fache Menge, also 300 Megabyte RAM benötigt, als wenn er 24bit pro Array-Eintag belegen würde. Woran liegt das, und wie kann man das ändern?
[attachment=18776]

Danke auch für den anderen Tip. Kann man sagen, welche der beiden vorgeschlagenen Möglichkeiten weniger Speicher-/Rechenintensiv ist?
' schrieb:Danke für den Tip. Das Array erst zu initialisieren und dann aufzufüllen ist wirklich schneller. Woher weiß man solche Tricks?
Erfahrung.
' schrieb:Komischerweise verstehe ich die Speicherverwaltung noch nicht. In einem einfachen Bsp. ( siehe Bild) wird ein UINT8-Array mit 100 Millionen Einträge erzeugt. Da pro Eintrag 8 bit=1 Byte Speicherplatz benötigt werden, sollten auch etwa 100 Megabyte RAM belastet werden. Es wird aber ziemlich genau die 3fache Menge, also 300 Megabyte RAM benötigt, als wenn er 24bit pro Array-Eintag belegen würde. Woran liegt das, und wie kann man das ändern?
Hast du noch lokale Variable des Arrays? Jede lokale Variable erzeugt eine Kopie im Speicher.
Auch die Anzeige im FP erzeugt, wenn ich mich nicht total irre, eine Kopie im Speicher. Am wenigsten belastet man bei großen Arrays den Speicher, wenn man sie nur in einem Schieberegister einer Schleife speichert.
' schrieb:Danke auch für den anderen Tip. Kann man sagen, welche der beiden vorgeschlagenen Möglichkeiten weniger Speicher-/Rechenintensiv ist?
Dürfte ziemlich egal sein. Wenn ich mich recht erinnere, wird beim Transpose-Array keine Kopie im Speicher angelegt, sondern nur intern die Indizierung vertauscht.
Was bei beiden Varianten die Zeit braucht, ist die Speicherallozierung für das neue größere Array und dann das Kopieren der Daten.

Gruß, Jens
' schrieb:Hast du noch lokale Variable des Arrays? Jede lokale Variable erzeugt eine Kopie im Speicher.
Auch die Anzeige im FP erzeugt, wenn ich mich nicht total irre, eine Kopie im Speicher. Am wenigsten belastet man bei großen Arrays den Speicher, wenn man sie nur in einem Schieberegister einer Schleife speichert.
Habe nur das kleine VI gestartet, was du im letzten Bild siehst. Wenn ich keine Anzeige mache, dann wird auch kein Speicher belegt. Natürlich will ich mir das nicht anzeigen lassen, sondern weiterverwenden, und mit anderen Werten auffüllen. Dann muss logischerweise Speicher belegt werden. Die Frage ist nur, warum er 3mal so viel belegt.

Kannst ja mal ausprobieren. Bin so vorgegangen:
Statt 100 Millionen die Länge zuerst auf 1 stellen und Vi starten. Im Task Manager Speicherbelegung notieren.
Dann mit Länge von 100 Millionen starten, Speicherdifferenz ist nun ca. 300 Megabyte. Erwartet habe ich ca. 100 Megabyte.

Habe Vista64 und 4GB RAM undLv86_img(gibts wohl nur als 32bit?). Speicher war noch genug frei bei mir, als ich testete.
Hallo,

vielleicht hilft Dir der folgende Link weiter, warum LV mehr Speicher allokiert hat als Du denkst.

http://zone.ni.com/reference/en-XX/help/37...w_buffer_alloc/

In Deinem Beispiel wird min. der doppelte Speicher im RAM allokiert, und zwar für das Init. Array und den Indikator auf dem FP.
Es ist immer noch nicht klar. Wenn ich mein kleines Bsp. nehme wo ein uint8-Array mit 100 Millionen Elementen initialisiert wird, dann wird kein Speicher belegt, wenn ich keinen Indikator benutze. Wenn ich aber einen Indikator einfüge, dann werden 300 Megabyte eingezogen. Erwartet werden 100 Megabyte. Warum soll ein Indikator das 3fache belegen, wenn ohne Indikator gar kein Speicher belegt wird? Probiert es doch mal aus!
Hallo,

Erster Fall kein Indikator:
Wenn Du das Tool verwendet hättest, hättest Du auch gesehen, dass kein Speicher allokiert wird wenn kein Indikator angeschlossen ist. (Warum auch wird auch nicht benutzt!)

Zweiter Fall mit Indikator: Wenn Du das Tool verwendet hättest, hättest Du auch gesehen, dass für das Init. Array und für den Indikator Speicher allokiert wird.

Wenn das ganze jetzt auch noch angezeigt wird, wird für das FP auch noch mal der Speicherplatz allokiert. Kannst Du ganz einfach testen, wenn du dein Diagramm in einem SubVI laufen lässt.

Also in deinem Fall 300MB.
Ok, ich kapiere. Dass für Indikatoren extra Speicher benötigt wird ist nicht so das Problem, da man sie ja nicht anzeigen muss.
Aber schlimmer ist es, wenn man ein größeres Array erzeugen möchte und LV automatisch interne Kopien anlegt. Siehe dafür das folgende Beispiel. Es wird ein eindimensionales Array mit 5000x10000=50 Millionen Elementen des Typs UINT8 initialisiert. Dann wird das Array mit 5000 Subarrays á 10000 Elementen aufgefüllt. Es wird glatt der doppelte Speicher belegt (100 MB statt 50 MB). Lässt sich diese Doppelbelegung irgendwie vermeiden? Muss man zu anderen Algotithmen greifen?
[attachment=18838]
Ich habe da mal was auf LAVAG gelesen, finde den Thread aber auf die Schnelle nicht mehr.

Schließ mal anstatt einer Konstanten ein FP-Control bei der Größenangabe des Arrays an. Ich meine, dann wird eine Kopie weniger erstellt.

Hängt irgendwie mit dem LV-Compiler zusammen.

Gruß, Jens
Seiten: 1 2 3
Referenz-URLs