Per un esercizio universitario, abbiamo dovuto implementare uno Leapfrog integrator con forze Newtoniane esatte in Python. Il corso è finito e le nostre soluzioni erano più che sufficienti, ma mi chiedevo se/come si potesse migliorare ulteriormente le prestazioni del calcolo delle forze.Calcolo più performante delle forze newtoniane in numpy/scipy
il collo di bottiglia per calcolare tutte le forze (alias accelerazioni):
per un grande (1000 e oltre) numero di particelle N (i, j < N).
Qui r e r sono i vettori 3-dimensionale della posizione delle particelle immagazzinato in un ndarray di forma (N, 3) e Gm è la particella massa per la costante gravitazionale che ho salvato in un narray di forma (N).
la versione più veloce che ho trovato finora è la seguente:
def a(self):
sep = self.r[np.newaxis, :] - self.r[:, np.newaxis]
# Calculate the distances between all particles with cdist
# this is much faster than by hand
dists = cdist(self.r, self.r)
scale =dists*dists*dists
# set diagonal elements of dist to something != 0, to avoid division by 0
np.fill_diagonal(scale,1)
Fsum = (sep/scale.reshape(self.particlenr,self.particlenr,1))*self.Gm[:,None]
return np.add.reduce(Fsum,axis=1)
ma mi bug che questo non è probabilmente la versione più veloce. La prima riga sembra essere troppo lenta quando si confronta con il cd che sta facendo essenzialmente lo stesso calcolo. Inoltre, questa soluzione non utilizza la simmetria di commutazione r e r nel problema e calcola tutti gli elementi due volte.
Conosci qualche miglioramento delle prestazioni (senza modificare il calcolo della forza in una certa approssimazione o cambiare il linguaggio di programmazione)?