Warum nicht einfach random_device verwenden?

8

Ich bin etwas verwirrt über die zufällige C ++ 11-Bibliothek.

Was ich verstehe: Wir brauchen zwei separate Konzepte:

  • random engine (das kann Pseudo (brauchen Samen) oder real)
  • distribution: Es bildet die von der Engine erhaltenen Zahlen unter Verwendung einer bestimmten Verteilung in ein bestimmtes Intervall ab.

Was ich nicht verstehe, ist, warum nicht einfach das benutzen:

%Vor%

Soweit ich das beurteilen kann, funktioniert das gut.

Stattdessen habe ich das in den meisten Beispielen / Sites / Artikeln gefunden:

%Vor%

Ich spreche nicht über spezielle Verwendung, z.B. Kryptographie, nur Ihre grundlegenden Einstieg Artikel.

Mein Verdacht liegt darin, dass std::mt19937 (oder std::default_random_engine ) einen Seed akzeptiert. Es kann einfacher sein, sie zu debuggen, indem während einer Debug-Sitzung derselbe Seed bereitgestellt wird.

Auch warum nicht einfach:

%Vor%     
bolov 02.09.2016, 09:11
quelle

2 Antworten

8
  

Auch warum nicht einfach:

     

std::mt19937 e{std::random_device{}()};

Es ist vielleicht in Ordnung, wenn du das nur einmal tust, aber wenn du es oft machst, ist es besser, deine std::random_device im Auge zu behalten und sie nicht unnötigerweise zu erstellen / zu zerstören.

Es kann hilfreich sein, den Quellcode von libc ++ für die Implementierung von std::random_device zu betrachten, was ziemlich einfach ist. Es ist nur ein dünner Wrapper über std::fopen("/dev/urandom") . Jedes Mal, wenn Sie ein std::random_device erstellen, erhalten Sie ein anderes Dateisystem-Handle und bezahlen alle damit verbundenen Kosten.

Unter Windows stellt std::random_device , wie ich verstanden habe, einen Aufruf an eine Microsoft Crypto-API dar, sodass Sie jedesmal eine Crypto-Bibliotheksschnittstelle initialisieren und zerstören, wenn Sie dies tun.

Es hängt von Ihrer Anwendung ab, aber für allgemeine Zwecke würde ich diesen Overhead nicht als immer vernachlässigbar betrachten. Manchmal ist es, und dann ist das großartig.

Ich schätze, das hängt mit Ihrer ersten Frage zusammen:

  

Stattdessen habe ich das in den meisten Beispielen / Sites / Artikeln gefunden:

%Vor%

Zumindest denke ich darüber nach:

  • std::mt19937 ist ein sehr einfacher und zuverlässiger Zufallsgenerator. Die Implementierung wird vom Standard mandiert , und zumindest im Boost-Modus wurde überall derselbe Code verwendet, der vom ursprünglichen mt19937 -Papier abgeleitet wurde. Dieser Code ist sehr stabil und plattformübergreifend. Sie können ziemlich sicher sein, dass das Initialisieren, das Abfragen von usw. auf ähnlichem Code auf jeder Plattform kompiliert wird, auf der Sie es kompilieren, und dass Sie ähnliche Leistung erhalten werden.

  • std::random_device ist dagegen ziemlich undurchsichtig. Du weißt nicht genau was es ist, was es tun wird oder wie effizient es sein wird. Sie wissen nicht einmal, ob es tatsächlich erworben werden kann - es könnte eine Ausnahme auslösen, wenn Sie versuchen, es zu erstellen. Sie wissen, dass es keinen Samen benötigt. Normalerweise sollten Sie nicht Tonnen von Daten daraus ziehen, sondern nur Samen erzeugen. Manchmal fungiert es als eine nette Schnittstelle zu kryptografischen APIs, aber das ist nicht unbedingt erforderlich und manchmal leider auch nicht. Es könnte /dev/random auf Unix entsprechen, es könnte /dev/urandom/ entsprechen. Es könnte einer MSVC Crypto API (Visual Studio) entsprechen, oder es könnte nur eine feste Konstante (Mingw) sein. Wenn Sie für ein Telefon cross-kompilieren, wer weiß, was es tun wird. (Und selbst wenn Sie /dev/random erhalten, haben Sie immer noch das Problem, dass die Leistung möglicherweise nicht konsistent ist - es scheint gut zu funktionieren, bis der Entropie-Pool leer ist und dann langsam läuft als Hund.)

Ich denke darüber nach, std::random_device soll wie eine verbesserte Version von Seeding mit time(NULL) sein - das ist ein niedriger Balken, weil time(NULL) alles in allem ein ziemlich beschissener Samen ist. Ich verwende es normalerweise, wo ich time(NULL) verwendet hätte, um einen Samen zu erzeugen, zurück in den Tag. Ich halte das nicht wirklich für nützlich.

    
Chris Beck 02.09.2016, 23:12
quelle
6

Dieser Artikel ist ein guter Anfang.

Ich werde nur ein paar Punkte synthetisieren:

  • Es hat unbekannte Kosten.
      

    Wie teuer ist es, eine Nummer von diesem "Gerät" zu lesen? Das ist nicht spezifiziert. Es könnte zum Beispiel aus / dev / random auf einem Linux-System gelesen werden, das für längere Zeit auf Entropie warten kann (was aus verschiedenen Gründen problematisch ist).

Für meine persönliche Erfahrung habe ich mitgeteilt, dass std::random_device normalerweise langsamer ist als ein einfacher pseudozufälliger Algorithmus. Das kann im Allgemeinen nicht wahr sein, aber normalerweise tut es das. Das kann physische Geräte oder andere Hardware als die einfache CPU umfassen.

  • Es könnte tatsächlich deterministisch sein.
      

    C ++ 11 std :: random_device muss nichtdeterministisch sein! Implementierungen können und implementieren es als einfachen RNG mit einem festen Seed, so dass es für jeden Lauf des Programms die gleiche Ausgabe erzeugt.

Biagio Festa 02.09.2016 09:22
quelle

Tags und Links