Sto cercando di capire come devono essere utilizzate le funzionalità di generazione casuale del numero C++ 11. La mia preoccupazione è la prestazione.Generazione di numeri casuali efficiente con C++ 11 <random>
Supponiamo di dover generare una serie di numeri interi casuali tra 0..k
, ma k
modifiche ad ogni passaggio. Qual è il modo migliore di procedere?
Esempio:
for (int i=0; i < n; ++i) {
int k = i; // of course this is more complicated in practice
std::uniform_int_distribution<> dist(0, k);
int random_number = dist(engine);
// do something with random number
}
Le distribuzioni che l'intestazione <random>
fornisce sono molto convenienti. Ma sono opachi per l'utente, quindi non posso facilmente prevedere come si esibiranno. Ad esempio, non è chiaro quanto (eventuale) sovraccarico di runtime sia causato dalla costruzione di dist
precedente.
Invece ho potuto usare qualcosa di simile
std::uniform_real_distribution<> dist(0.0, 1.0);
for (int i=0; i < n; ++i) {
int k = i; // of course this is more complicated in practice
int random_number = std::floor((k+1)*dist(engine));
// do something with random number
}
che evita la costruzione di un nuovo oggetto in ogni iterazione.
I numeri casuali vengono spesso utilizzati in simulazioni numeriche in cui le prestazioni sono importanti. Qual è il modo migliore per utilizzare <random>
in queste situazioni?
Si prega di non rispondere "profilo". La profilatura è parte dell'ottimizzazione efficace, ma lo è anche una buona comprensione di come una libreria è destinata a essere utilizzata e le caratteristiche delle prestazioni di tale libreria. Se la risposta è che dipende dall'implementazione della libreria standard, o che l'unico modo per sapere è profilarlo, allora preferirei non usare affatto le distribuzioni da <random>
. Invece posso usare la mia implementazione che sarà trasparente per me e molto più facile da ottimizzare se/quando necessario.
Un'ulteriore considerazione: una delle cose positive dei generatori come 'std :: mt19937' è che sono portatili e l'implementazione è * obbligatoria * secondo lo standard. L'uso del generatore con un dato seme deve produrre la stessa sequenza casuale di 'uint32_t' su qualsiasi implementazione conforme.Tuttavia, gli adattatori di distribuzione 'std :: uniform_int_distribution' non hanno questa garanzia, quindi se li si usa, si può ottenere una sequenza diversa di interi dalla stessa se si cambiano i compilatori o qualcosa del genere. Questa potrebbe essere una considerazione per le simulazioni numeriche. –
@ChrisBeck Non lo sapevo, grazie per averlo fatto notare! – Szabolcs