Come posso creare un veloce RNG (Generatore di numeri casuali) in C# che supporta il riempimento di una matrice di byte con un valore massimo (e/o un valore minimo)? Ho trovato questo http://www.codeproject.com/KB/cs/fastrandom.aspx ma non ha queste funzionalità.Fast Random Generator
risposta
Il fatto che si sta riempiendo byte con gli interi è abbastanza diverso da il tipico caso d'uso per System.Random che probabilmente puoi batterlo male se davvero ne hai bisogno.
System.Random è realizzato per uso generale. (In realtà, di solito trovo le routine casuali del sistema poco interessanti quando eseguo test di velocità e distribuzione su di esse.) Ci sono casi in cui si vorrebbe qualcos'altro. Ma devi essere molto esplicito riguardo ai tuoi bisogni. Quanto velocemente? Cosa sei disposto a rinunciare?
Se davvero bisogno di "veloce", Marsaglia ha prodotto una serie di generatori di numeri casuali molto veloce che potrebbero essere adattate alle vostre esigenze. Qui ci sono alcuni collegamenti con uno di loro, Xorshift:
- Xorshift (Wikipedia)
- Fastest implementation of Xorshift in C#, and measurements comparing it to System.Random
- Il Diehard tests sono interessanti.
- Agner has C++ code per molti randoms veloci.
- Here's a fast twister che utilizza istruzioni SIMD.
L'ultimo si riferisce al fatto che si stanno indirizzando byte.
ho solo bisogno di super-veloci randoms un paio di volte. Nei giochi per console con processori lenti dove casuale potrebbe fare la differenza tra colpire il bersaglio frame rate e non colpire. Qual è il tuo caso d'uso? Con tutti i mezzi, utilizzare System.Random se potete.
Oppure, adattare la routine si collega alla tua domanda (che rivendicazioni autore è 8x la velocità di System.Random.
L'ultimo collegamento è stato abbastanza interessante da esaminare, +1 –
Grazie per la risposta, l'RNG deve essere il più veloce possibile, ho molti numeri casuali da generare in pochi secondi (10^9 e più). Ho provato ad adattare la routine nel mio collegamento ma non ho avuto successo, puoi aiutarmi? – tazzo
Ci sono molte possibilità. Immagina di aver impostato un buffer di 4k di numeri casuali per un intervallo (ad esempio, 0-100). Usa un generatore di numeri casuali per scegliere un offset e afferrare, diciamo 16 byte dal tuo elenco. Quindi generare un altro offset e afferrare altri 16 byte. Questo non sarà _fantasticamente_ casuale, ma potrebbe essere _sufficientemente_ casuale. Nonostante le mie domande, non mi hai detto cosa sei disposto a rinunciare per ottenere la velocità. Cosa farai con tutti questi numeri? – Nosredna
È possibile utilizzare Reflector per decompilare System.Random in C#. Questo ti darebbe il codice C# di un generatore di numeri casuali veloce che soddisfa i tuoi requisiti.
In realtà, no ... il Framework è precompilato e ottimizzato, non puoi competere con quello (fino alla precompilazione del tuo codice). Almeno questa è l'esperienza che ho fatto (mentre cercavo di superare il framework;)). – Bobby
E perché lo farebbe esattamente? Presumibilmente, dal momento che chiede, Random è troppo lento, altrimenti lo userebbe, no? –
@Bobby: depresso, vero. Precompilare il proprio codice non aiuterà, però. –
System.Random è abbastanza veloce per quasi ogni uso tipico. Se riscontri problemi di prestazioni con il codice che contiene le chiamate System.Random, assicurati di profilare il codice prima del cercando di creare un nuovo casuale. È probabile che i tuoi problemi di prestazioni non siano nel framework, ma piuttosto nel tuo codice.
Se si sta chiamando in Random in un ciclo, assicurarsi di non creare una nuova istanza casuale con ciascuna iterazione, ma invece di riutilizzare un'istanza casuale comune. Ciò migliorerà le prestazioni perché non stai creando nuovi oggetti per il GC da ripulire e migliorerai anche la qualità dei numeri casuali generati.
Il mio codice deve solo generare molti numeri casuali in pochi secondi – tazzo
È incredibile quante risposte SO decidano di discutere sui bisogni del richiedente invece di rispondere alla domanda. – Nosredna
@tazzo: quanti sono molti? quali sono i requisiti specifici che stai cercando? @Nosredna: a volte rispondendo alla domanda e aiutando il richiedente sono due cose diverse. E chi sta discutendo? –
utilizzare i servizi di crittografia ....
RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
byte[] bytes= new byte[5];
crypto.GetBytes(bytes);
naturalmente, questo solo soddisfa il requisito zona di byte ...
Non l'ho cronometrato da solo, ma direi che RNGCryptoServiceProvider, avendo la proprietà extra di essere crittograficamente sicuro, sarebbe più lento di System.Random. – SoftMemes
Ho controllato RNGCryptoServiceProvider ma non si adatta alle mie esigenze, è lento e non consente di generare un massimo di numeri casuali. – tazzo
Se si dispone di un generatore di numeri casuali che restituisce numeri dall'intervallo di unità, come quello nell'articolo Codice progetto menzionato, quindi è possibile generare un valore u
utilizzando quel generatore e quindi restituire a + (b-a)*u
per ottenere valori tra a e b.
La tua formula non è corretta, se scelgo A = 5 e B = 20 e U = 55 ottengo 5+ (20-5) * 55 = 830. La formula corretta è U/(UMAX + 1) * (B-A) + A dove UMAX è il valore massimo del numero casuale. – tazzo
Se il valore casuale u deriva dall'unità * intervallo *, vale a dire tra 0 e 1, la formula è corretta. Nel tuo esempio, u = 55 non è un numero compreso tra 0 e 1. –
System.Random è troppo lento? – driis
Può essere molto bene. Sta riempiendo i byte, che è un caso piuttosto speciale. Il codice che mira a riempire i byte potrebbe probabilmente essere un ordine di grandezza più veloce o più. Ha bisogno di quella velocità? Non lo so. – Nosredna
Sì, System.Random è troppo lento. Ho molti numeri casuali da generare. – tazzo