Strutture di dati per codice di volume finito: Matrici vs Classi


11

Devo scrivere un codice di volume finito per la magnetoidrodinamica (MHD). Ho scritto un codice numerico prima ma non su questa scala. Volevo solo chiedere quale sarebbe stata una buona scelta, usando una struttura di dati (approccio orientato agli oggetti) con classi o semplicemente usando più array per proprietà diverse, in termini di velocità, scalabilità ecc. Ho intenzione di scrivere il codice in Python, e usa fortran per la parte numericamente intensiva.

Un esempio per la classe in Python sarebbe

class Cell:
   def __init__(self, x, y, z, U):

Le matrici possono essere semplicemente definite come

x[nx][ny][nz]
y[nx][ny][nz]
z[nx][ny][nz]
U[nx][ny][nz]

eccetera.

Risposte:


9

Risposta semplice: in Python moderno ogni tipo di dato è una classe, quindi formalmente non c'è differenza tra le due soluzioni che hai proposto. (Ricorda di usare classi di nuovo stile: le classi classiche sono obsolete! Vedi http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes )

Ora la domanda dovrebbe essere: come organizzo una struttura dati efficiente in Python? Non vi è dubbio che l'idea stessa di organizzare le cellule come una serie di class Cellistanze sia troppo inefficiente. Ti ritroverai con un casino di puntatori e dati non contigui organizzati come un complicato elenco di link. Ovviamente hai la possibilità di inserire facilmente nuove celle nel tuo elenco: ma hai bisogno di questa funzione? Al contrario, avrai una memorizzazione dei dati non contigua e dovrai accedere a ogni cella con diversi livelli di indiretta.

Se organizzi i tuoi dati come numpy.ndarrayallora, i dati sono contigui alla memoria e l'accesso a celle diverse è semplicemente fatto avanzando attraverso il tuo blocco di memoria: spazio efficiente (nessuna memoria sprecata per i puntatori) e veloce .

Come sottolineato da Ethan, i concetti di OO dovrebbero essere usati, ma a un livello superiore, una volta implementata un'efficiente struttura di dati di basso livello, di solito attraverso quella numpy.ndarraydi.

Programmazione OO significa associare i dati ai metodi che operano sui dati stessi a un livello di astrazione più elevato. (Un esempio: ho implementato un codice FEM in cui la matrice di rigidezza è stata definita come una classe con un metodo per la fattorizzazione sparsa e super-nodale cholesky. La prima implementazione era in-core: quando era necessaria un'implementazione out-of-core, questo è stato ottenuto tramite ereditarietà e aggiustamenti minimi alla memorizzazione dei dati di sottolineatura. Quasi il 100% del codice cholesky soprannodale è stato riutilizzato.)

Un ultimo commento, ma cruciale: un'efficiente procedura numerica è il risultato di una mappatura intelligente di un algoritmo e di una struttura di dati sulla tua architettura di calcolo target. Se si inizia con una struttura di dati errata, non è possibile ripristinare l'efficienza senza una riscrittura completa.


@EthanCoon Grazie per il tuo commento all'altra risposta, che mi ha portato a scrivere il mio.
Stefano M,

10

Ci stavo riflettendo qualche giorno fa (anche in Python). Personalmente non penso che la programmazione orientata agli oggetti sia sempre adatta alla programmazione numerica. Puoi distrarti nel progettare le classi piuttosto che risolvere le equazioni. Preferisco rimanere con funzioni semplici e con numpy puoi avere le tue equazioni vettorializzate in modo che il numero di linee di cui hai bisogno sia davvero pochissimo. Numpy è piuttosto veloce perché i calcoli effettivi vengono eseguiti con un back-end C (o FORTRAN?).

Cosa ti consiglierei di fare,

  1. Scrivi uno script Python che risolva la versione più semplice possibile del tuo problema usando un approccio funzionale con numpy. Ad esempio, avere tutto in unità arbitraria e provare solo 1D (o 2D). Va perfettamente bene in questa fase se il codice è disordinato. L'importante è che tu stia andando avanti con il tuo progetto.
  2. Una volta che hai qualcosa che funziona. Identifica dove il codice è dettagliato e rifrattore. A questo punto puoi giocare con idee diverse su come semplificare il tuo codice. Forse introduci funzioni in cui noti che ti stai ripetendo. Puoi confrontare con la versione originale in modo da sapere che non stai introducendo bug.
  3. Decidi se l'approccio orientato agli oggetti ridurrà ulteriormente la complessità del codice.

Il messaggio principale è non iniziare a scrivere classi finché non hai già risolto il problema nel modo più semplice possibile. Solo acquisendo l'esperienza di risoluzione di un problema saprai come definire l'interfaccia orientata agli oggetti. Se lo fai prima, è probabile che si metta in mezzo.


3
Non sono molto d'accordo con l'affermazione secondo cui OO non è adatto alla programmazione numerica, ma dove si adatta bene è a un livello molto più elevato. OO è molto utile per cose come modelli fisici, mesh, solutori, ecc., Ma è quasi sempre inappropriato a livello di cellule.
Ethan Coon,

Nel post ho voluto mettere in guardia sulle potenziali cadute di "oggettivazione precoce" del codice numerico, in particolare all'inizio. Non sono contrario all'utilizzo di oggetti, vedi il mio terzo punto: se gli oggetti possono ridurre la complessità, allora sono una buona idea. Sono d'accordo che gli esempi che citi sono buoni usi, ma arrivare a quel punto richiede esperienza.
boyfarrell,
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.