Perché è necessaria la gestione della memoria personalizzata per le risorse?


10

Praticamente tutte le risorse relative alla programmazione dei giochi, in particolare i giochi open world 3D, parlano di come scaricare e ricaricare costantemente risorse da e verso disco, memoria di sistema e memoria video. Posso capirlo su console, in quanto hanno schemi di gestione della memoria molto semplici che non sono in grado di gestire alcun potenziale overflow.

Tuttavia, sul PC, la situazione è molto diversa. C'è memoria virtuale fornita dal sistema operativo per la memoria di sistema e il driver grafico gestisce lo scambio avanti e indietro dalla CPU alla GPU. Quindi perché non è sufficiente caricare tutto in una volta e devono solo occuparsi del prefetching e possibilmente assicurarsi che non ci siano blocchi mentre un asset richiesto viene scambiato?


Questo non vuol dire che tutto viene allocato ingenuamente usando qualcosa di simile malloc. Tutto sarà mantenuto contiguo e coerente con la cache. È senza dubbio più facile rendere efficiente l'accesso alla memoria se non devi preoccuparti di effettuare il pagin in e out manualmente comunque ...


AGGIORNARE:

Dopo aver letto un po 'i trasferimenti di buffer asincroni , mi viene in mente che il modo in cui il driver grafico può automaticamente scorrere la memoria in entrata e in uscita non è ottimale. Questo vale anche per le risorse della CPU; cioè, è meglio gestire sempre manualmente quando una determinata risorsa deve essere caricata e scaricata anche in presenza di memoria virtuale?


1
Si presuppone che il contenuto dell'asset sia archiviato nella memoria di sistema. Gran parte dei dati delle risorse verranno archiviati nella memoria GPU, che è molto più limitata.
Giochi di dadoo,

Dalla lettura della risposta qui ho avuto l'idea che i driver OpenGL mantengano automaticamente anche tutti i buffer / trame sulla CPU. Tuttavia, posso capire perché potrebbe essere utile specificare questi trasferimenti manualmente per sfruttare i caricamenti asincroni .
Jmegaffin,

Sei sicuro che questo sia rilevante per il tuo progetto di gioco? Non sono sicuro di vedere la sfida tecnica, solo la soluzione. Se non stai affrontando una sfida tecnica, è difficile personalizzare una soluzione o capirne una.
AturSams,

Mi chiedo perché i motori di gioco implementino sistemi complessi di memorizzazione nella cache degli asset quando i sistemi / driver operativi dispongono già di sistemi di memoria virtuale disponibili. È rilevante per me perché sto scrivendo un gioco open world in cui queste informazioni sono molto importanti.
Jmegaffin,

Il tuo gioco soffre di problemi di prestazioni e lo strumento di profilazione mostra che è a causa dell'accesso alla memoria? Il problema con i giochi che contengono livelli aperti è che in termini tecnici, ciò si traduce in molti dati. Maggiore è il controllo su tali dati, migliore sarà la prestazione. Perché non implementare il sistema più efficiente per gestire i dati? Lo sviluppo del gioco è molto competitivo e quando hai soldi per gli esperti, non lascerai nulla di intentato, cercando di spremere più dettagli e fps più alti.
AturSams,

Risposte:


16

I moderni giochi open world semplicemente non si adattano alla memoria. Tieni presente che la maggior parte dei giochi è ancora a 32 bit a causa del numero di giocatori con sistemi operativi a 32 bit e che un processo a 32 bit nella migliore delle ipotesi può avere solo 4 GB di memoria indirizzata alla volta (indipendentemente dalla memoria virtuale), ma realisticamente è limitato a 2-3 GB. La frammentazione e la quantità effettiva di oggetti utilizzabili che è possibile avere in una memoria alla volta è leggermente più piccola dei dati totali necessari per un ambiente di grandi dimensioni. Anche su un sistema operativo a 64 bit, spesso è necessario targetizzare macchine con specifiche ridotte con solo 4 GB di memoria per garantire la massima compatibilità per l'utente finale. Non dimentichiamo i dispositivi mobili, l'hardware "sotto-alimentato" come il WiiU, ecc. Gli sviluppatori devono puntare molto di più rispetto alle grandi piattaforme di gioco per PC.

La memoria virtuale non è una soluzione, in primo luogo perché non annulla i limiti di spazio degli indirizzi e anche perché non è ottimale. Il sistema operativo può sfogliare le cose in momenti inopportuni o in modi inopportuni. Questo era un problema affrontato dai sistemi operativi al momento del primo letargo; il paging dei processi su disco e il loro back-in è stato significativamente più lento in alcuni casi rispetto al fatto che l'applicazione riporti esplicitamente il flusso della risorsa. È ancora possibile vedere i problemi oggi quando un sistema sta esaurendo la memoria, le pagine vengono pagate su disco, e il sistema non risponde diventa cose fondamentali necessarie per eseguire il paging di WM / explorer.exe. La memoria virtuale è stata una soluzione ideata un problema decenni fa in cui i sistemi avevano pochissima RAM e il divario tra la memoria e la velocità del disco era molto più piccolo. Anche oggi Gli SSD più veloci sono una piccola frazione della velocità della RAM economica / lenta e cercare di far finta di poter usare il disco come RAM virtuale non è più la migliore idea. Questa è un'epoca in cui alcune persone fanno il contrario e caricano i file system nei dischi RAM; i vincoli che hanno portato alla creazione della memoria virtuale non valgono più.

Anche a parte il problema del disco, la gestione delle risorse personalizzate è ancora una parte importante dello sviluppo del gioco. Dagli hook di debug alle preoccupazioni di frammentazione allo streaming intelligente di risorse complesse, semplicemente fingere che il mondo intero sia una scatola infinitamente grande di bit non è realistico.


Grazie per la risposta dettagliata Anche se sto ancora cercando alcune informazioni sul modo in cui i driver GPU gestiscono la memoria virtuale (tra VRAM e RAM di sistema).
Jmegaffin,

@Boreal: stessi problemi. Basta sostituire "RAM" con "VRAM" e "disco" con "Memoria CPU
Sean Middleditch

@SeanMiddleditch +1 Bella risposta, "Questa è un'epoca in cui alcune persone fanno il contrario e caricano i file system nei dischi RAM", intendi i file mappati in memoria? Anche quello che ho capito dalla tua risposta è che l'allocatore di memoria personalizzato impedisce al sistema operativo di eseguire il paging della memoria, non è questo il caso poiché la memoria verrà paginata per quanto chiedi memoria al kernel usando brk () per esempio, come il paging su PC viene impedito esattamente utilizzando un allocatore di memoria personalizzato?
concept3d

1
@ concept3d: non mapping di memoria, ma dischi letterali RAM. È possibile creare un'unità supportata dalla memoria e non dal disco. Il gestore della memoria personalizzato non impedisce il paging (alcune altre app potrebbero utilizzare tutta la memoria). Gestire le risorse in modo intelligente (a livello di oggetto / gestione delle risorse) significa semplicemente liberare memoria per gli oggetti che non servono più. Pensa alle cache del disco del sistema operativo che mantiene in memoria
Sean Middleditch il

6

Per un gioco a 32 bit, poiché la maggior parte dei giochi è per una serie di ragioni, anche un gioco che viene fornito su un DVD a una sola faccia (4,3 GB) ha già molti più contenuti che possono essere inseriti in uno spazio di indirizzi a 32 bit. E questo presuppone che il contenuto non sia compresso su disco e, in modo ottimale, caricare tutto in una volta in un approccio allo spazio degli indirizzi contiguo. Molti giochi ora arrivano su più DVD, superando facilmente i 10 GB di contenuto. Nella mia esperienza su PC, una volta che lo spazio degli indirizzi si avvicina a allocazioni da 2 GB inizieranno a fallire e questo diventa un limite rigido, indipendentemente dalla quantità di memoria fisica dell'utente.

Se fai il salto a 64 bit, supponendo che il tuo motore lo supporti, quel limite rigido scompare, solo per essere sostituito da un limite morbido effettivo - non appena inizia lo scambio di memoria virtuale, le prestazioni del gioco diminuiranno inaccettabile. Se il processo principale deve mai attendere il rientro della memoria, la frequenza dei fotogrammi balbetterà e si guasterà. La memoria virtuale potrebbe renderlo trasparente, ma non renderlo performante. Richiede fisicamente tempo per recuperare quella memoria dal disco e, mentre aspetti, il gioco si è bloccato. Sebbene sia possibile aggirare (con il prelievo in background delle pagine di memoria che sai che ti serviranno presto), è un processo difficile e inaffidabile e avrà ancora implicazioni sulle prestazioni.

Gli algoritmi del sistema operativo per decidere quali pagine scambiare su disco non hanno alcuna conoscenza del tuo gioco e di cosa probabilmente avrà bisogno in seguito. Inoltre, il sistema operativo deve ancora supportare altre applicazioni in esecuzione contemporaneamente al gioco, così come il sistema operativo stesso. Dover bloccarsi mentre le pagine vengono restituite dal disco è un enorme successo di prestazioni e non importa se è il tuo gioco, un'altra applicazione o il sistema operativo che lo incorre, le prestazioni del gioco ne risentiranno enormemente.

Quindi, indipendentemente dal fatto che il limite di memoria sia morbido o rigido, la memoria è ancora limitata. Ma anche se potessi semplicemente caricare tutto in una volta, senza colpire un limite di prestazioni, ci sono ancora motivi per cui non vorresti:

  1. Il caricamento del tuo gioco richiede molto più tempo e passa a uno stato interattivo rispetto a quello necessario, perché carica semplicemente tutto all'inizio e lo mantiene residente. È possibile caricare circa 150 MB / sec da un disco rigido e persino l'unità DVD più veloce (24x) viene caricata a 33 MB / sec. Ciò significa che l'esempio di 4,3 GB di contenuto DVD impiegherà almeno 30 secondi per caricare dall'HDD e oltre 133 secondi per caricare dal DVD. Questi sono tempi di caricamento inaccettabilmente lunghi.

  2. Il tuo gioco richiede molta più memoria di quanto sia giustificato. Se è visibile solo il 10% del contenuto alla volta, trattenere il resto del residente è semplicemente uno spreco e impedisce all'utente di utilizzare quella memoria per qualcos'altro. Gli utenti generalmente non perdonano i giochi che richiedono una quantità sproporzionatamente grande di memoria per funzionare correttamente.

Lo streaming di risorse dal disco in modo dinamico, sia in background che in modo sincrono durante una schermata di caricamento, ti consente di essere molto più efficiente nell'uso della memoria, con uno sforzo trascurabile e solo un piccolo inconveniente per l'utente. Ma è un'ottimizzazione e, come qualsiasi altra ottimizzazione, ha rendimenti decrescenti più si tenta di applicarla. Ad un certo punto l'aumento dell'ingombro della memoria per mantenere qualcosa di residente è compensato dai vantaggi ottenuti dal fatto di averlo lì senza la necessità di caricare. Ma fino a quando non viene raggiunto quel punto, è meglio caricare solo ciò di cui hai bisogno, quando ne hai bisogno.


1

Parlando in modo molto generico e semplicistico, e senza considerare i dettagli delle implementazioni di memoria virtuale, lo sviluppatore ha sempre conoscenza in previsione della mancanza dell'implementazione della VM.

Lo sviluppatore può sempre dire: "Non ho bisogno di caricare questo file audio in questo momento. La musica all'interno viene utilizzata solo per il gioco sullo schermo." E subito dopo il gioco sullo schermo, lo sviluppatore può dire: "Non ho più bisogno di questo clip audio nella memoria fisica. È usato solo per questo gioco sullo schermo."

Il sistema operativo non ha tale lungimiranza. Potrebbe essere in grado di capire, molti errori di pagina in seguito, che alcuni clip audio non sono più necessari nella memoria fisica poiché non sono stati raggiunti da un bel po '. Ma trasformare la lungimiranza in senno di poi si traduce in molti errori di pagina, e molti errori di pagina si traducono in singhiozzi nella frequenza dei fotogrammi in un software così critico come un videogioco. Lì la lungimiranza dello sviluppatore aiuta davvero se si desidera evitare tali singhiozzi.

E questo vale concettualmente indipendentemente dall'hardware e dal software. Supponendo che il paging in memoria sia costoso, la lungimiranza dello sviluppatore aiuterà sempre a ridurre tale spesa.

Parlando ancora più in generale, c'è un ciclo infinito tra progettista hardware, progettista di compilatori, progettista di sistemi operativi / driver e sviluppatore di applicazioni. Gli sviluppatori di hardware / compilatore / sistema operativo / driver spesso cercano di implementare ottimizzazioni per accelerare l'applicazione media in base ai soliti schemi di accesso alla memoria, e forse a volte con la speranza come "Le persone dovrebbero essere in grado di scrivere il codice come vogliono e dovrebbe essere veloce. "Ma se si pensasse a quel tipo in corso, di solito fallisce per i campi critici per le prestazioni, perché quindi gli sviluppatori critici per le prestazioni iniziano ad apprendere i dettagli intricati del loro compilatore, hardware, sistema operativo, driver, ecc. E iniziano a scrivere codice in modo specifico progettato per sfruttare il più possibile la scrittura del codice più veloce possibile (come prefetch, divisione di campi caldi / freddi, SoA, ecc. per codici compatibili con la cache). Ed è come un gioco che non finisce mai. Queste cose non sono mai trattate come scatole nere in campi critici per le prestazioni, poiché gli sviluppatori sono in competizione per le prestazioni.

Personalmente vorrei che la memoria virtuale non esistesse poiché aggiunge un ulteriore livello di imprevedibilità delle prestazioni in modi che tendono ad essere troppo estremi e comportano un modo, troppo di una penalità di prestazione quando le cose vanno davvero a sud fino al punto di inusabilità. A volte mi sono imbattuto in casi in cui ho usato alcune applicazioni in cui ho digitato accidentalmente una o due cifre extra quando sono stato ubriaco in un campo di input che poi ha causato l'esaurimento della memoria fisica così rapidamente in modi che hanno portato il sistema operativo a una scansione in cui non ho potuto ' ho anche fatto più clic sul pulsante Annulla sulla barra di avanzamento e ho dovuto attendere 10 minuti durante l'inceppamento di Ctrl + Alt + Canc per terminare un processo e imprecare contro di me mentre versavo il mio drink per tornare a un punto in cui le cose sono di nuovo utilizzabili, e che era nonostante il file di paging fosse archiviato su un SSD. In quei casi avrei preferito preferire un errore di "memoria insufficiente" o qualcosa del genere, a quel punto potrei chiudere alcune delle mie 17 schede di porno (va bene, aggiungo comunque i miei preferiti) per liberare un po 'di memoria e quindi andare immediatamente in giro riprendendo la mia attività.

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.