Sto lavorando a una simulazione di fluido in C#. Ogni ciclo ho bisogno di calcolare la velocità del fluido in punti discreti nello spazio. Come parte di questo calcolo, ho bisogno di alcune decine di kilobyte per lo spazio di scrittura per contenere alcuni array double [] (la dimensione esatta degli array dipende da alcuni dati di input). Gli array sono necessari solo per la durata del metodo che li usa, e ci sono alcuni metodi diversi che richiedono uno spazio come questo.Scratch di memoria in ambiente gestito
come la vedo io, ci sono un paio di soluzioni diverse per costruire le matrici zero:
Usa 'nuovo' per afferrare la memoria dal mucchio ogni volta che il metodo viene chiamato. Questo è quello che stavo facendo all'inizio, tuttavia mette molta pressione sul garbage collector, ei picchi di pochi ms una o due volte al secondo sono davvero fastidiosi.
Gli array scratch sono passati come parametri durante la chiamata dei metodi. Il problema è che questo costringe l'utente a gestirli, incluso il dimensionamento appropriato, il che è un enorme problema. Inoltre, rende difficile l'utilizzo di più o meno memoria scratch, poiché modifica l'API.
Utilizzare stackalloc in un contesto non sicuro per allocare la memoria scratch dallo stack di programmi. Funzionerebbe bene, tranne che dovrei compilare con/non sicuro e cospargere costantemente blocchi non sicuri nel mio codice, cosa che vorrei evitare.
Preallocare gli array privati una volta all'avvio del programma. Questo va bene, tranne che non conosco necessariamente la dimensione degli array di cui ho bisogno fino a quando non riesco a vedere alcuni dei dati di input. E diventa davvero complicato dal momento che non è possibile limitare l'ambito di queste variabili private a un solo metodo, in modo da inquinare costantemente lo spazio dei nomi. Ed è scarsamente scalabile in quanto il numero di metodi che necessitano di una memoria di memoria aumenta, dal momento che sto allocando molta memoria che viene utilizzata solo una frazione del tempo.
Creare una sorta di pool centrale e allocare gli array di memoria scratch dal pool. Il problema principale con questo è che non vedo un modo semplice per allocare array di dimensioni dinamiche da un pool centrale. Potrei usare un offset iniziale e una lunghezza e disporre che tutta la memoria scratch condivida essenzialmente un unico grande array, ma ho un sacco di codice esistente che assume il doppio [] s. E dovrei fare attenzione a rendere sicuro un thread di questo tipo.
...
Qualcuno ha qualche esperienza con un problema simile? Qualche consiglio/lezione da offrire dall'esperienza?
Intendevi davvero qualche decina di kilobyte? Dato che è una quantità così piccola, non mi preoccuperei della gestione della memoria per questo ... –
Non sembra molto, ma se eseguo 2000 cicli/sec, all'improvviso è qualcosa come 60 MB/sec, e il GC inizia a notare. –
@JayLemmon, penso che ti preoccupi di questi dettagli per motivi di prestazioni, giusto? Se il tuo progetto non è finito, ti suggerisco di non preoccuparti delle prestazioni fino alla sua conclusione. Vedi questo articolo su [Ottimizzazione prematura] (http://c2.com/cgi/wiki?PrematureOptimization). Se il progetto è finito, l'articolo fornisce interessanti osservazioni anche su __ottimizzazione__ in generale. Cito una parte: "Un malinteso comune è che il codice ottimizzato è necessariamente più complicato [...] codice fattorizzato spesso corre più veloce e utilizza anche meno memoria [...]". – jay