Wann können parallele Arrays verwendet werden?

14

Ich habe auf Code gestoßen (neuen Code), der das verwendet, was ich "Parallele Arrays" oder "Listen" nenne. Dies bedeutet, dass es 2 Arrays gibt, die verwandte Daten enthalten und durch ihre Position (Index) im Array verknüpft sind.

Ich halte dies für verwirrend und fehleranfällig. Die Lösung, die ich normalerweise vorschlage, besteht darin, ein Objekt mit dem Namen zu erstellenCompany mit den Feldern CompanyId und CompanyName .

Ein sehr reales Beispiel:

List<string> companyNames;
List<int> companyIds;

//...They get populated somewhere and we then process

for(var i=0; i<companyNames.Count; i++)
{
    UpdateCompanyName(companyIds[i],companyNames[i]);
}

Werden diese parallelen Arrays als schlechte Praxis angesehen ?

GER
quelle
9
Einfach ein weiterer Beweis, dass keine Sprache erfunden wurde, in der man Fortran nicht schreiben kann.
Andy Mango
3
Es kann (ziemlich bedeutende) Caching-Vorteile geben, wenn Sie so etwas tun (obwohl Sie zusammenhängende Arrays und keine verknüpften Listen benötigen), und dies ist in der Spielprogrammierung im Zusammenhang mit "datenorientiertem Design" etwas populär geworden. Dies scheint jedoch nicht auf Ihren Fall zuzutreffen. Es sieht nicht so aus, als würden Sie leistungskritischen Code erstellen.
Derek Elkins verließ SE am
2
@DerekElkins ... Interessanterweise folgt Ihr Kommentar einem Vergleich mit Fortran-Code. In früheren Versionen von Fortran fehlte die Unterstützung für benutzerdefinierte Strukturen, und selbst nach der Hinzufügung wurden in idiomatischem Fortran-Code mehrere Arrays von Eigenschaften verwendet, keine Arrays von Strukturen. Und dies wird oft als Teil des Grundes angeführt, warum Fortran oft als die schnellste Sprache angesehen wird.
Jules
3
Ein tangentialer Gedanke zu dieser Frage: Viele funktionale Sprachen fördern aktiv die Arbeit mit solchen Listen. Sie haben eine Funktion, normalerweise zip genannt, die sie in eine Liste von Tupeln umwandelt. Ihr Code sieht aus wie C #. Die neueste Version von C # bietet Unterstützung für erstklassige Tupel. Ich frage mich, ob sie deshalb irgendwo eine Zip-Funktion hinzugefügt haben, die Ihre Listen automatisch in eine nützliche Struktur für Sie bringen könnte.
Jules
4
Nun, es gibt manchmal Gründe, zwei Arrays absichtlich zu verwenden, aber in 99% aller Fälle habe ich dies gesehen. Der einzige Grund dafür war die Trägheit des ursprünglichen Autors, eine umfassende Datenstruktur einzuführen.
Doc Brown

Antworten:

23

Hier sind einige Gründe, warum jemand Parrel-Arrays verwenden könnte:

  1. In einer Sprache, die keine Klassen oder Strukturen unterstützt
  2. So vermeiden Sie das Sperren von Threads, wenn einzelne Threads nur eine der Spalten ändern
  3. Wenn die Persistenzmethode erzwingt, dass diese Objekte separat gespeichert werden, stellen Sie sie gerade wieder her.
  4. Sie können weniger Speicher verbrauchen, wenn die Strukturen gepolstert sind. (gilt nicht für diese Datentypen in C #)
  5. Wenn Teile der Daten eng zusammengehalten werden müssen, um den CPU-Cache effizient zu nutzen (im obigen Code nicht hilfreich).
  6. Verwendung von SIMD-Operationscodes (Single Instruction Multiple Data). (gilt nicht für diesen Code oder Zeichenfolgen überhaupt)

In diesem Fall sehe ich keinen zwingenden Grund, dies zu tun ... und es gibt wahrscheinlich bessere Optionen in allen oben genannten Fällen oder sie sind in einer Hochsprache nicht so nützlich.

TheCatWhisperer
quelle
3
Sie können auch weniger Speicher verbrauchen, wenn die Strukturen gepolstert sind. Mehrere große, intelligent zugewiesene Arrays können weniger Speicher belegen als ein Array von Strukturen.
Frank Hileman
4
4. Wenn Teile der Daten eng zusammengehalten werden müssen, um den CPU-Cache effizient zu nutzen. (In seltenen Fällen
erforderlich
@Frank Hileman, Whilie Ich denke, dass die Antwort von TheCatWhisperer völlig richtig ist. Ihr Kommentar ist eigentlich der beste Grund, diesen Ansatz zu wählen. Wenn der Speicherverbrauch kritisch ist, kann der Speicheraufwand für das Auffüllen von Strukturen erheblich sein, insbesondere wenn große Zahlen abgespielt werden.
Vladimir Stokic
Ihre Vorschläge wurden zur Antwort
hinzugefügt
Zu (2), wie ist das? Ich kann ein Programm mit einem einzigen Array von Strukturen und einer Sperre pro Feld genauso einfach schreiben wie eines mit mehreren Arrays und einer Sperre pro Array.
Solomon Slow
7

Ich habe mich schuldig gemacht, parallele Arrays verwendet zu haben . Manchmal steckt man so sehr in der Struktur, dass man nicht darüber nachdenken möchte, wie man sie abstrahiert. Abstraktion kann etwas schwieriger umzugestalten sein, sodass Sie nur ungern darauf zugreifen, bis Sie bewiesen haben, was Sie wirklich brauchen.

An diesem Punkt lohnt es sich jedoch über eine Umgestaltung nachzudenken, um die Details zu abstrahieren. Oft ist es der Hauptgrund, warum ich es nicht gerne mache, dass es schwierig ist, sich einen guten Namen auszudenken.

Wenn Sie eine gute Möglichkeit finden, parallele Arrays zu abstrahieren, tun Sie dies jedes Mal. Aber lähmen Sie sich nicht, indem Sie sich weigern, sie zu berühren. Manchmal ist ein wenig schmutziger Code das beste Sprungbrett für großartigen Code.

kandierte_orange
quelle
6

Dieses Muster wird manchmal auch als Struktur von Arrays bezeichnet (im Gegensatz zu Array von Strukturen) und ist beim Vektorisieren von Code äußerst nützlich. Anstatt eine Berechnung zu schreiben, die auf einer einzelnen Struktur ausgeführt wird, und Bits davon zu vektorisieren, schreiben Sie die Berechnung wie gewohnt, mit Ausnahme der SSE-Eigenheiten, sodass sie auf 4 statt auf einer Struktur ausgeführt wird. Dies ist normalerweise einfacher und fast immer schneller. Das SoA-Format macht dies sehr natürlich. Es verbessert auch die Ausrichtung, wodurch die SSE-Speicheroperationen schneller werden.

Dan
quelle
Ja, dieser Ansatz wird beim maschinellen Lernen auf der GPU verwendet. Es ist üblich, die Felder vieler separater Beispiele auseinander zu ziehen, alle Werte jedes Feldes in einen separaten Tensor zu packen und diese Tensoren zur Berechnung in großen Mengen weiterzuleiten, um eine Liste von Vorhersagen zu erstellen.
Setzen Sie Monica am