Domanda

Sto lavorando a un gioco RTS in C ++ destinato all'hardware portatile (Pandora). Come riferimento, Pandora ha un singolo processore ARM a ~ 600Mhz ed esegue Linux. Stiamo cercando di accontentarci di un buon sistema di trasmissione dei messaggi (sia interno che esterno), e questo è un nuovo territorio per me.

Potrebbe essere utile fornire un esempio di un messaggio che vorremmo trasmettere. Un'unità può effettuare questa chiamata per caricare i suoi modelli in memoria:

sendMessage (" model-loader " ;, " load-model " ;, my_model.path, model_id);

In cambio, l'unità potrebbe aspettarsi una sorta di messaggio contenente un oggetto modello per il particolare model_id, che può quindi essere passato al sistema grafico. Questa funzione sendMessage non è in alcun modo definitiva. Riflette solo la mia attuale comprensione dei sistemi di trasmissione dei messaggi, che probabilmente non è corretta :)

Da quello che posso dire ci sono due scelte piuttosto distinte. Uno è passare i messaggi in memoria e passare attraverso la rete solo quando è necessario parlare con un computer esterno. Mi piace questa idea perché l'overhead sembra basso, ma il grande problema qui è che sembra che tu debba fare un ampio uso del blocco mutex sulle tue code di messaggi. Vorrei davvero evitare il blocco in eccesso, se possibile. Ho letto alcuni modi per implementare semplici code senza blocco (basandomi sulle operazioni atomiche int ) ma queste ipotizzano che ci sia un solo lettore e uno scrittore per una coda. Questo non sembra utile al nostro caso particolare, poiché la coda di un oggetto avrà molti scrittori e un lettore.

L'altra scelta è quella di passare completamente al livello di rete. Questo ha alcuni vantaggi divertenti come far passare i messaggi asincroni gratuitamente. Inoltre, abbiamo la possibilità di passare i messaggi ad altre macchine utilizzando le stesse identiche chiamate del passaggio locale. Tuttavia, questa soluzione mi sfrega nel modo sbagliato, probabilmente perché non lo capisco completamente :) Avremmo bisogno di un socket per ogni oggetto che sta per inviare / ricevere messaggi? Se è così, questo sembra eccessivo. Un determinato gioco avrà migliaia di oggetti. Per un dispositivo un po 'sottodimensionato come Pandora, temo che abusare della rete in quel modo possa finire per essere il nostro collo di bottiglia. Ma non ho ancora eseguito alcun test, quindi questa è solo una speculazione.

L'MPI sembra essere popolare per il passaggio di messaggi, ma sicuramente sembra eccessivo per quello che vogliamo. Questo codice non toccherà mai un cluster né dovrà eseguire calcoli pesanti.

Qualsiasi approfondimento su quali opzioni abbiamo per raggiungere questo obiettivo è molto apprezzato.

È stato utile?

Soluzione

Anche la rete utilizzerà il blocco. Sarà semplicemente dove non puoi vederlo, nel kernel del sistema operativo.

Quello che vorrei fare è creare il proprio oggetto coda messaggi che è possibile riscrivere come necessario. Inizia semplice e rendilo migliore se necessario. In questo modo puoi farlo usare qualsiasi implementazione che ti piace dietro le quinte senza cambiare il resto del tuo codice.

Guarda diverse possibili implementazioni che potresti voler fare in futuro e progetta la tua API in modo da poterle gestire tutte in modo efficiente se decidi di implementarle in questi termini.

Se vuoi un passaggio dei messaggi davvero efficiente, guarda alcuni dei microkernel L4 open source. Quei ragazzi hanno messo un lotto di tempo nel passaggio veloce dei messaggi.

Altri suggerimenti

Dato che si tratta di una piccola piattaforma, potrebbe valere la pena programmare entrambi gli approcci.

Tuttavia, escludendo una sorta di grande problema di velocità, sceglierei sempre un approccio più semplice da codificare. Probabilmente verrà utilizzato lo stack di rete, poiché sarà lo stesso codice indipendentemente da dove si trovi il destinatario e non sarà necessario codificare e debug manualmente le esclusioni reciproche, il buffering dei messaggi, le allocazioni, ecc.

Se scopri che è troppo lento, puoi sempre ricodificare le cose locali usando la memoria in seguito. Ma perché perdere tempo a farlo in anticipo se non dovessi farlo?

Sono d'accordo con la raccomandazione di Zan di trasmettere messaggi in memoria ogni volta che è possibile.

Uno dei motivi è che è possibile passare oggetti complessi C ++ senza la necessità di effettuare il marshalling e il non-marshalling (serializzare e deserializzare).

Il costo della protezione della coda dei messaggi con un semaforo sarà molto probabilmente inferiore al costo delle chiamate in codice di rete.

Se proteggi la tua coda di messaggi con qualche algoritmo senza lock (usando operazioni atomiche come hai fatto allusione a te stesso) puoi evitare molto che un contesto passi dentro e fuori dal kernel.

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