Quando va bene usare le matrici parallele?


14

Mi sono imbattuto nel codice (nuovo codice) che utilizza ciò che chiamo 'Parallel Arrays' o Lists. Significa che ci sono 2 array che contengono dati correlati e sono collegati dalla loro posizione (indice) nell'array.

Considero questo confuso e incline a tutti i tipi di errori. La soluzione che normalmente propongo è quella di creare un oggetto chiamato Companycon i campi CompanyId e CompanyName.

Un esempio molto reale:

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]);
}

Queste matrici parallele sono considerate cattive pratiche ?


9
Semplicemente ulteriore prova che non è stata inventata alcuna lingua in cui non è possibile scrivere Fortran.
andy mango,

3
Ci possono essere (abbastanza significativi) vantaggi nella memorizzazione di cache nel fare qualcosa del genere (anche se sono necessari array contigui non elenchi collegati), e questo è diventato in qualche modo popolare nella programmazione di giochi relativa al "design orientato ai dati". Tuttavia, questo non sembra applicarsi al tuo caso. Non sembra che tu stia creando un codice critico per le prestazioni.
Derek Elkins lasciò SE il

2
@DerekElkins ... Interessante che il tuo commento ne segua uno confrontandolo con il codice Fortran. Le prime versioni di Fortran mancavano del supporto per le strutture definite dall'utente e anche dopo che è stato aggiunto il codice Fortran idiomatico utilizza più array di proprietà e non array di strutture. E questo è spesso accreditato come parte del motivo per cui Fortran è spesso considerato il linguaggio più veloce.
Jules,

3
Un pensiero tangente a questa domanda: molti linguaggi funzionali incoraggiano attivamente a lavorare con tali elenchi. Hanno una funzione, di solito chiamata zip, che li converte in un elenco di tuple. Il tuo codice sembra C #. L'ultima versione di C # ha aggiunto il supporto per le tuple di prima classe. Mi chiedo se, quindi, hanno aggiunto una funzione zip da qualche parte che potrebbe mettere automaticamente le tue liste in una struttura utile per te?
Jules,

4
Bene, a volte ci sono ragioni per usare due array intenzionalmente, ma nel 99% di tutti i casi l'ho visto, l'unica ragione è stata la pigrizia dell'autore originale di introdurre una struttura di dati che abbraccia.
Doc Brown,

Risposte:


23

Ecco alcuni motivi per cui qualcuno potrebbe usare array di parrel:

  1. In una lingua che non supporta classi o strutture
  2. Per evitare il blocco dei thread quando i singoli thread stanno modificando solo una delle colonne
  3. Quando il metodo di persistenza impone che queste cose vengano archiviate separatamente e le stai ricostituendo.
  4. Possono consumare meno memoria se le strutture sono imbottite. (non applicabile per questi tipi di dati in C #)
  5. Quando parti dei dati devono essere tenute vicine per fare un uso efficiente della cache della CPU (non sarebbe di aiuto nel codice sopra).
  6. Utilizzo di codici op SIMD (Single Instruction Multiple Data). (non applicabile per questo codice o per le stringhe)

Non vedo alcun motivo convincente per farlo in questo caso ... e probabilmente ci sono opzioni migliori in tutto quanto sopra o non sono così utili in un linguaggio di alto livello.


3
Possono consumare meno memoria anche se le strutture sono imbottite. Numerose matrici di grandi dimensioni, allocate in modo intelligente, possono consumare meno memoria di una matrice di strutture.
Frank Hileman,

4
4. Quando parti dei dati devono essere tenute vicine per fare un uso efficiente della cache della CPU. (Necessario in rari casi.)
Blrfl

@Frank Hileman, Whilie Penso che la risposta di TheCatWhisperer sia completamente corretta, il tuo commento è, in realtà, il miglior motivo per scegliere questo approccio. Se il consumo di memoria è critico, l'overhead della memoria sull'imbottitura delle strutture può essere significativo, specialmente se sono in gioco numeri grandi.
Vladimir Stokic,

Aggiunti i tuoi suggerimenti alla risposta
TheCatWhisperer,

Ri (2), Come va? Posso scrivere un programma con un singolo array di strutture e un lock per campo con la stessa facilità con cui posso scriverne uno con più array e un lock per array.
Solomon Slow

7

Sono stato colpevole di usare array paralleli . A volte ti capita così tanto nella struttura che non vuoi pensare a come astrarla. L'astrazione può essere un po 'più difficile da refacturing, quindi sei riluttante a lanciarti fino a quando non hai dimostrato ciò di cui hai veramente bisogno.

A quel punto però vale la pena considerare il refactoring per sottrarre i dettagli. Spesso il motivo principale per cui sono riluttante a farlo risulta che è difficile pensare a un buon nome.

Se riesci a vedere un buon modo per astrarre array paralleli di distanza, fallo ogni volta. Ma non paralizzarti rifiutandoti di toccarli. A volte un po 'di codice sporco è il miglior trampolino di lancio per un ottimo codice.


6

Questo modello viene talvolta chiamato anche Struttura delle matrici (in contrapposizione alla Matrice delle strutture) ed è estremamente utile durante la vettorializzazione del codice. Anziché scrivere un calcolo che viene eseguito su una singola struttura e vettorializzare i bit di esso, si scrive il calcolo come si farebbe normalmente, tranne che con intrinseci SSE in modo che venga eseguito su 4 strutture anziché su una. Questo di solito è più facile e quasi sempre più veloce. Il formato SoA lo rende molto naturale. Migliora anche l'allineamento, il che rende più veloci le operazioni di memoria SSE.


Sì, questo approccio viene utilizzato durante l'apprendimento automatico sulla GPU. È consuetudine separare i campi di molti esempi separati, raggruppare tutti i valori di ciascun campo in un tensore separato e passare quei tensori per essere calcolati in blocco per produrre un elenco di previsioni.
Ripristina Monica il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.