Domanda

Attualmente sto lavorando su un ray-tracer in C# come hobby.Io sto cercando di realizzare un rendering decente velocità mediante l'attuazione di alcuni trucchi da una implementazione di c++ e hanno eseguito nei guai.

Gli oggetti in scene in cui il ray-tracer rende sono memorizzati in un KdTree struttura e i nodi della struttura sono, a loro volta, memorizzati in un array.L'ottimizzazione sto avendo problemi con durante il tentativo di inserire il maggior numero di nodi dell'albero in linea di cache.Uno strumento per fare questo è per i nodi a contenere un puntatore a sinistra del nodo figlio solo.È quindi implicito che il diritto del bambino segue direttamente dopo l'uno a sinistra della matrice.

I nodi sono le strutture e durante la costruzione di albero sono ben messi in un array da una memoria statica classe.Quando comincio ad attraversare l'albero, in un primo momento, sembra funzionare bene.Poi a un punto di inizio nel rendering (circa nello stesso posto ogni volta), la sinistra bambino puntatore del nodo radice è improvvisamente indicando un puntatore null.Sono giunto alla conclusione che il garbage raccoglieva ha spostato le strutture come la matrice si trova sul mucchio.

Ho provato diverse cose per pin indirizzi in memoria, ma nessuno di loro sembra durare per l'intero ciclo di vita dell'applicazione di cui ho bisogno.La 'fissa' parola chiave sembra solo aiutare durante la singola chiamate di metodo e dichiarando 'fisso' array può essere fatto solo su tipi semplici che un nodo non è.C'è un buon modo per fare questo, o io sono troppo in basso il percorso di roba in C# non significava per.

Btw, cambiando in c++, mentre forse la scelta migliore per alte prestazioni del programma, non è un'opzione.

È stato utile?

Soluzione

In primo luogo, se si utilizza C#, normalmente, non si può improvvisamente avere un riferimento null, grazie al garbage collector a spostare le cose, perché il garbage collector anche gli aggiornamenti di tutti i riferimenti, quindi non c'è bisogno di preoccuparsi a spostare le cose intorno.

È possibile aggiungere le cose a memoria, ma questo può causare più problemi di quanti ne risolva.Per una cosa, impedisce che il garbage collector di compattazione della memoria correttamente, e può avere un impatto sulle prestazioni in che modo.

Una cosa vorrei dire dal tuo post è che l'utilizzo di strutture non possono fare prestazioni come la speranza.C# non riesce a in linea le chiamate di metodo che coinvolge le strutture, e anche se hanno risolto questo nella loro ultima fase di runtime beta, le strutture spesso non eseguire bene.

Personalmente, vorrei dire C++ trucchi come questo di solito non tendono a portare più troppo bene in C#.Si può imparare a lasciarsi andare un po';ci possono essere altri modi più sottili per migliorare le prestazioni ;)

Altri suggerimenti

Qual è la tua memoria statica manager in realtà fa?A meno che si sta facendo qualcosa di pericoloso (P/Invoke, il codice unsafe), il comportamento che si sta vedendo è un bug nel programma, e non a causa del comportamento di CLR.

In secondo luogo, che cosa si intende per "puntatore", con rispetto per i collegamenti tra le strutture?Avete letteralmente significa sicuri KdTree* puntatore?Non che.Invece, utilizzare un indice in un array.Allora mi aspetto che tutti i nodi di un albero sono memorizzati nella stessa matrice, non avrete bisogno di un distinto riferimento alla matrice.Un solo indice farà.

Infine, se proprio si deve usare KdTree* i puntatori, quindi la tua memoria statica manager deve allocare un grande blocco utilizzando, ad esempio,Il maresciallo.AllocHGlobal o un'altra memoria non gestita di origine;si dovrebbero trattare questo grande blocco come un KdTree array (cioèindice di un KdTree* C-style) e dovrebbe suballocate nodi da questa matrice, con il bumping "libero" puntatore.

Se hai un ridimensionamento di questa matrice, quindi, è necessario aggiornare tutti i puntatori, naturalmente.

La fondamentale lezione qui è che non sicure puntatori e memoria gestita fare non mix al di fuori di 'fisso' isolati, che naturalmente hanno stack frame di affinità (es.quando la funzione ritorna l'appuntato comportamento va via).C'è un modo per pin oggetti arbitrari, come array, utilizzando GCHandle.Alloc(yourArray, GCHandleType.Appuntato), ma quasi certamente non si vuole andare a nanna.

Si otterrà più sensata risposte se si descrivere più in dettaglio che cosa si sta facendo.

Se si davvero voglio fare questo, è possibile utilizzare il GCHandle.Alloc metodo per specificare che un puntatore dovrebbe essere bloccato senza essere automaticamente rilasciato alla fine del campo di applicazione, come l'istruzione fixed.

Ma, come altri hanno detto, per farlo è mettere pressione indebita su garbage collector.Che cosa circa la creazione di una struttura che tiene su un paio di nodi e quindi la gestione di un array di NodePairs piuttosto che un array di nodi?

Se si vuole veramente avere completamente non gestito l'accesso a un blocco di memoria, si sarebbe probabilmente meglio l'allocazione di memoria direttamente dal heap gestito piuttosto che permanentemente bloccare una parte di heap gestito (questo impedisce il cumulo di poter compattare stesso).Un modo rapido e semplice per farlo sarebbe quello di utilizzare il Maresciallo.AllocHGlobal metodo.

È davvero proibitivo per memorizzare la coppia di array di riferimento e l'indice?

Qual è la tua memoria statica manager in realtà fa?A meno che si sta facendo qualcosa di pericoloso (P/Invoke, il codice unsafe), il comportamento che si sta vedendo è un bug nel programma, e non a causa del comportamento di CLR.

Stavo infatti parlando di pericoloso puntatori.Quello che volevo era qualcosa di simile Marshal.AllocHGlobal, anche se con una durata superiore a una singola chiamata di metodo.La riflessione sembra che il solo utilizzo di un indice, è la soluzione giusta, come ho potuto ottenuto troppo presi imitando il codice c++.

Una cosa vorrei dire dal tuo post è che l'utilizzo di strutture non possono fare prestazioni come la speranza.C# non riesce a in linea le chiamate di metodo che coinvolge le strutture, e anche se hanno risolto questo nel suo ultimo run-time beta, le strutture spesso non eseguire bene.

Ho indagato un po ' e vedo sia stato risolto .Rete 3.5SP1;Presumo che la cosa si fa riferimento a come il tempo di esecuzione beta.Infatti, ora capisco che questo cambiamento rappresentato un raddoppio della mia velocità di rendering.Ora, le strutture sono aggressivamente in-foderato, migliorando le loro prestazioni notevolmente su sistemi X86 (X64 era meglio struct prestazioni in anticipo).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top