2010-04-01 9 views
7

sto porting di un'applicazione C++ scientifica per python, e come io sono nuovo a python, alcuni problemi vengono in mente:uso migliore una tupla o un array NumPy per memorizzare le coordinate

1) Sto definendo una classe che conterrà le coordinate (x, y). Questi valori saranno accessibili più volte, ma verranno letti solo dopo l'istanza della classe. È meglio usare una tupla o una matrice numpy, sia in memoria che in tempo di accesso?

2) In alcuni casi, queste coordinate verranno utilizzate per creare un numero complesso, valutato su una funzione complessa, e verrà utilizzata la parte reale di questa funzione. Supponendo che non ci sia modo di separare parti reali e complesse di questa funzione, e la parte reale dovrà essere utilizzata alla fine, forse è meglio usare numeri direttamente complessi da memorizzare (x, y)? Quanto è pessimo il sovraccarico con la trasformazione dal complesso al reale in python? Il codice in C++ fa molte di queste trasformazioni, e questo è un grande rallentamento in quel codice.

3) Anche alcune trasformazioni di coordinate dovranno essere eseguite, e per le coordinate i valori xey saranno accessibili separatamente, la trasformazione verrà eseguita e il risultato restituito. Le trasformazioni di coordinate sono definite nel piano complesso, quindi è ancora più veloce utilizzare direttamente i componenti xey piuttosto che affidarsi alle variabili complesse?

Grazie

+0

Perché non utilizzare solo una serie numpy di numeri complessi? – Gabe

+0

Questo è l'approccio migliore in senso algoritmico, ma fino ad ora i miei test mi hanno mostrato, questa è la combinazione più lenta possibile. – Ivan

risposta

5

In termini di consumo di memoria, gli array di numpy sono più compatti delle tuple di Python. Una matrice numpy utilizza un singolo blocco contiguo di memoria. Tutti gli elementi dell'array numpy devono essere di tipo dichiarato (es. Float a 32 o 64 bit). Una tupla Python non usa necessariamente un blocco contiguo di memoria, e gli elementi della tupla possono essere oggetti Python arbitrari, che generalmente consumano più memoria rispetto ai tipi numerici numpy.

Quindi questo problema è una vincita a discesa per numpy, (assumendo che gli elementi dell'array possano essere memorizzati come un tipo numerico numerico).

Sulla questione della velocità, penso che la scelta si riduce alla domanda "Si può vectorizzare il codice?"

Cioè, puoi esprimere i tuoi calcoli come operazioni eseguite su interi array in base agli elementi.

Se il codice può essere vettorizzato, allora numpy sarà molto più veloce delle tuple Python. (L'unico caso in cui potrei immaginare dove potrebbe non essere, è se tu avessi molte tuple molto piccole: in questo caso il sovraccarico di formazione degli array numpy e il costo una tantum dell'importazione di numpy potrebbe annegare i benefici della vettorizzazione.)

un esempio di codice che non poteva essere vettorializzato sarebbe se il calcolo coinvolto guardando, per esempio, il primo numero complesso in un array z, facendo un calcolo che produce un indice intero idx, quindi il recupero z[idx], facendo un calcolo su quel numero, che produce il prossimo indice idx2, quindi recuperando z[idx2], ecc. Questo tipo di calcolo potrebbe non essere vettorializzabile.In questo caso, potresti anche usare le tuple Python, dato che non sarai in grado di sfruttare la forza di Numpy.

Non mi preoccuperei della velocità di accesso alle parti reali/immaginarie di un numero complesso. La mia ipotesi è che il problema della vettorizzazione determinerà molto probabilmente quale metodo è più veloce. (Comunque, per inciso, numpy può trasformare una serie di numeri complessi nelle loro parti reali semplicemente scavalcando l'array complesso, saltando ogni altro float e visualizzando il risultato come float.Inoltre, la sintassi è semplice: se z è . una matrice NumPy complesso, quindi z.real è la parte reale come un array di float NumPy Questo dovrebbe essere molto più veloce rispetto al metodo puro Python di usare una lista di comprensione di ricerche di attributi:. [z.real for z in zlist])

Solo per curiosità, qual è la tua ragione per portare il codice C++ in Python?

+0

Solo per verificare se la struttura dell'oggetto Python è migliore per la mia applicazione e per provare le routine scipy. Finora, sto attaccando con C++ - sui miei test, almeno 2 ordini di grandezza più veloce! – Ivan

+0

Inoltre, l'accesso alle parti reali e immaginarie dei numeri è un grande rallentamento nel codice C++. – Ivan

+0

Sì, ci sono buone ragioni per usare Python, come la leggibilità e lo sviluppo rapido del codice, ma non ho incontrato alcun esempio in cui il codice è stato portato da C/C++ a Python e ho goduto di una maggiore velocità. Di solito quando c'è un collo di bottiglia in codice Python, la gente consiglia di riscrivere quella funzione in C/C++ e chiamarla da Python. – unutbu

3

Un numpy array con una dimensione in più è più stretto in uso della memoria, e almeno altrettanto veloce !, come numpy serie di tuple; i numeri complessi sono almeno altrettanto buoni o addirittura migliori, compresa la terza domanda. A proposito, forse avete notato che - mentre le domande poste dopo che le vostre hanno ottenuto risposte in abbondanza - la vostra era a riposo: una parte della ragione è senza dubbio che chiedere a tre domande all'interno di una domanda spegne i rispondenti. Perché non chiedi solo una domanda per domanda? Non è come se ti venissero addebitati per domande o altro, sai ...! -)

Problemi correlati