Modo più veloce per generare casualmente un booleano

Così c’è più possibilità di creazione di un casuale bool in C#:

  • Utilizzando Casuale.Next(): rand.Next(2) == 0
  • Utilizzando Casuale.NextDouble(): rand.NextDouble() > 0.5

C’è davvero differenza? Se è così, che in realtà ha la migliore performance? O c’è un altro modo di non vedere, che potrebbe essere ancora più veloce?

  • ericlippert.com/2012/12/17/performance-rant
  • Come molti hai intenzione di creare?
  • È davvero questo il collo di bottiglia?
  • Senza correre (perché ogni metodo sarà ridicolmente veloce), la mia ipotesi sarebbe quella di utilizzare NextBytes di pre-popolare un array di byte, utilizzare BitArray di turno che in un insieme di valori booleani e recuperare quei valori booleani da un Queue fino a quando è svuotato, quindi ripetere il processo. Con questo metodo, si sta utilizzando solo il randomizer una volta, in modo che qualsiasi sovraccarico crea accade solo quando si ricarica la coda. Questo potrebbe essere utile quando si lavora con un sicuro generatore di numeri casuali, anziché il normale Random classe.
  • Ho bisogno di generare fino a 2^a 18 o a 8, dipende dal risultato di quella che la precede.
  • MS incasinato l’attuazione di NextBytes, quindi è sorprendentemente lento
  • Wow, interessante – ho appena guardato in un disassembler per vedere che cosa si fa riferimento a: buffer[i] = (byte)(this.InternalSample() % 256); – sto assumendo che cosa si sta parlando, che avrebbero preso quel numero intero casuale e dividere in 3 byte, popola l’array di byte con circa 1/3 del lavoro. Mi chiedo se c’era una ragione per questo o se è stato solo una svista da parte degli sviluppatori.
  • Non ho mai visto il codice, ma il rendimento è circa così male come chiamare Next per ogni byte, invece di approfittare di tutti i 31 bit. Ma dal momento che System.Random ha la cattiva progettazione e l’attuazione a praticamente ogni livello, questo è uno dei miei più piccole lamentele.

InformationsquelleAutor timedt | 2013-10-04



4 Replies
  1. 64

    Il prima opzionerand.Next(2) esegue dietro le quinte il seguente codice:

    if (maxValue < 0)
    {
        throw new ArgumentOutOfRangeException("maxValue",
            Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", new object[] { "maxValue" }));
    }
    return (int) (this.Sample() * maxValue);

    e per il seconda opzionerand.NextDouble():

    return this.Sample();

    Dal momento che la prima opzione contiene maxValue di convalida, la moltiplicazione e la fusione, la seconda opzione è probabilmente più veloce.

    • Grazie, è tutto quello che volevo sapere.
    • La mia timings dire che la seconda opzione è di circa il 5% più veloce rispetto a prima.
  2. 50

    Piccolo miglioramento per la seconda opzione:

    Secondo MSDN

    public virtual double NextDouble()

    restituisce

    Una doppia precisione in virgola mobile un numero maggiore o uguale a 0.0, e a meno di 1.0.

    Quindi, se volete un’uniforme diffusione casuale bool si dovrebbe usare >= 0.5

    rand.NextDouble() >= 0.5

    Scala 1: [0.0 0.5 … [

    Campo 2: [0.5 1.0 … [

    Gamma |1| = |2|

  3. 5

    Ho eseguito le prove con il cronometro. 100.000 iterazioni:

    System.Random rnd = new System.Random();
    if (rnd.Next(2) == 0)
         trues++;

    Cpu come numeri interi, in modo che il Prossimo(2) il metodo è stato più veloce. 3,700 contro i 7500 ms, che è abbastanza notevole.
    Inoltre: credo di numeri casuali può essere un collo di bottiglia, ho creato circa 50 ogni fotogramma Unità, anche con una piccola scena che ha notevolmente rallentato il mio sistema, in modo che anche io speravo di trovare un metodo per creare un casuale bool.
    Così ho provato anche

    if (System.DateTime.Now.Millisecond % 2 == 0)
           trues++;

    ma la chiamata di una funzione statica è stato ancora più lento con 9,600 ms. Vale la pena un colpo.
    Finalmente ho saltato il confronto e solo ha creato 100.000 valori casuali, per assicurarsi che l’int vs doppio confronto, non influenza il tempo trascorso, ma il risultato è stato praticamente lo stesso.

    • DateTime.Ora è notoriamente lento. Idealmente dipende dall’hardware soluzioni o almeno OS-dipendenti, dovrebbero essere utilizzati per rendere più veloce.
    • Utilizzare DateTime.UtcNow, è molto più veloce DateTime.Now.
  4. 0

    Il più veloce. Chiamare il metodo Casuale.Avanti meno overhead. Il metodo di estensione di seguito viene eseguito il 20% in più rispetto Random.NextDouble() > 0.5, e il 35% più veloce rispetto Random.Next(2) == 0.

    public static bool NextBoolean(this Random random)
    {
        return random.Next() > (Int32.MaxValue / 2);
        //Next() returns an int in the range [0..Int32.MaxValue]
    }

    Più veloce del più veloce. È possibile generare casuale booleane con il Random classe ancora più veloce, utilizzando trucchi. Il 31 bit più significativi di un generati int può essere utilizzato per il 31 successivo boolean produzioni. L’attuazione soffietto è il 40% più veloce di quanto precedentemente dichiarato come il più veloce.

    public class RandomEx : Random
    {
        private uint _boolBits;
    
        public RandomEx() : base() { }
        public RandomEx(int seed) : base(seed) { }
    
        public bool NextBoolean()
        {
            _boolBits >>= 1;
            if (_boolBits <= 1) _boolBits = (uint)~this.Next();
            return (_boolBits & 1) == 0;
        }
    }

Lascia un commento