Il y a six mois, je voulais créer le meilleur générateur de nombres pseudo-aléatoires (PRNG) avec une architecture inhabituelle. Je pensais que le début serait facile et que vous travaillez, la tùche deviendra lentement plus complexe. Et j'ai pensé que si je pouvais tout apprendre assez rapidement pour faire face aux plus difficiles.à ma grande surprise, la complexité n'a pas augmenté de façon linéaire. Les tests d'octets chi carré se sont révélés trÚs difficiles! Plus tard, il a été tout aussi difficile de passer des tests inflexibles. J'ai publié les résultats actuels pour comprendre quelles autres difficultés m'attendent. Cependant , le test PractRand a échoué à ce moment-là .Ensuite, il a été trÚs difficile de réussir le test BigCrush .Ensuite, il était trÚs difficile de transférer 32 téraoctets de données lors du passage de PractRand. La vitesse est devenue un problÚme. Il ne suffit pas de créer un design qui génÚre dix mégaoctets par seconde, car passer PractRand prendrait un mois. Mais je dois admettre qu'il était trÚs difficile de passer ce test à une vitesse de gigaoctets par seconde .Lorsque vous montez à une telle hauteur ... vous voulez savoir si vous pouvez vous rendre à la frontiÚre de Pareto. Vous voulez créer le PRNG le plus rapide au monde, qui passera les tests statistiques les plus complexes.J'ai réussi.Dans un article précédent, j'ai parlé de ce que j'ai appris pour atteindre mon objectif. Et ici, je vais vous dire comment fonctionne l'architecture finale.objectif
Commençons par l'Ă©vidence: la vitesse dĂ©pend de la plateforme . Je me suis concentrĂ© sur l'optimisation de l'architecture x86-64 moderne (processeurs Intel et AMD).Pour comparer les performances, la mĂ©trique cpb classique est utilisĂ©e : il s'agit du nombre de cycles de processeur dĂ©pensĂ©s pour gĂ©nĂ©rer un octet. Cette mĂ©trique est calculĂ©e et comparĂ©e dans toutes les Ćuvres cryptographiques. Un cpb lĂ©gĂšrement infĂ©rieur dans le monde du logiciel ou du matĂ©riel peut assurer la victoire dans la compĂ©tition ou l'utilisation sur des sites Web Ă travers le monde.Pour amĂ©liorer cpb, vous pouvez:- GĂ©nĂ©rez plus d'octets avec la mĂȘme quantitĂ© de travail,
- Ou faites moins de travail pour gĂ©nĂ©rer le mĂȘme nombre d'octets,
- Ou parallélisez le travail.
Nous ferons tout ce qui prĂ©cĂšde.Selon le premier point, nous devons produire plus de bits Ă chaque itĂ©ration.J'avais peur qu'on me dise: "S'il ne donne pas de numĂ©ros 32 bits, alors ce n'est pas le DSRP", ou la mĂȘme chose avec des numĂ©ros 64 bits. Ou: "Le PRNG ne devrait ĂȘtre que pour l'architecture x86-64", comme si les instructions comme POPCNT ou les registres comme% xmm7 Ă©taient interdits.Cependant, le PRNG est une ingĂ©nierie: les gĂ©nĂ©rateurs tentent depuis plusieurs dĂ©cennies de tirer tout ce qui est possible des processeurs! Lorsque ROL est apparu, ils ont commencĂ© Ă compter sur lui. Avec l'avĂšnement des processeurs 64 bits, ils ont commencĂ© Ă s'appuyer sur% rax. Bien sĂ»r, sur ARM, ces algorithmes peuvent fonctionner plus lentement (bien que cela reste Ă voir), cependant, les PRN 64 bits Ă©taient activement utilisĂ©s avant mĂȘme que Android ne commence Ă nĂ©cessiter la prise en charge du 64 bits en 2019!Autrement dit, ce domaine se dĂ©veloppe avec le matĂ©riel. Et aujourd'hui, les processeurs Intel et AMD dus Ă AVX2 prennent dĂ©jĂ en charge les opĂ©rations 256 bits. RC4 a produit 1 octet, drand48 pourrait produire 4 octets Ă la fois, pcg64 - 8 octets, et maintenant nous pouvons immĂ©diatement gĂ©nĂ©rer 32 octets.8 octets peuvent ĂȘtre un nombre 64 bits, et la plupart des langages de programmation ont des types intĂ©grĂ©s pour cela. Mais peu de langues fournissent des types pour 16 octets (une exception notable est __uint128_t en C). Encore moins de langues ont du type pour 32 octets (sauf internes).On peut donc dire adieu au prototype habituel de la fonction PRNG (exemple du benchmark Vigny HWD ):static uint64_t next(void);
Au lieu de cela, vous pouvez créer un générateur qui remplit le tampon (exemple de mon benchmark ):void prng_gen(prng_state *s, __uint64_t buf[], __uint64_t size);
Quels sont les inconvĂ©nients de cette solution?Si votre gĂ©nĂ©rateur produit 32 octets Ă la fois, vous devez fournir au consommateur un tableau qui est un multiple de 32 (idĂ©alement alignĂ© sur 32 octets). Bien que vous puissiez vous en passer, nous allons simplement remplir le tampon. Nous allons supprimer les donnĂ©es inutilisĂ©es et les remplir Ă nouveau si nĂ©cessaire. Le dĂ©lai devient imprĂ©visible: certains appels ne feront que lire le tampon. Mais en moyenne, tout sera pareil.Nous gĂ©nĂ©rons maintenant plus d'octets, effectuant la mĂȘme quantitĂ© de travail. Comment la parallĂ©lisons-nous?ParallĂ©lisme
Les processeurs offrent un ensemble incroyable d'outils de parallĂ©lisation Ă tous les niveaux.Tout d'abord, ce sont des instructions SIMD (Single-Instruction, Multiple Data). Par exemple, AVX2 effectue simultanĂ©ment quatre ajouts 64 bits, ou huit ajouts 32 bits, etc.Il est utilisĂ© en cryptographie depuis une quinzaine d'annĂ©es. La concurrence a fourni les performances incroyables du ChaCha20 . Il est utilisĂ© par les primitives les plus importantes qui n'utilisent pas AESNI. Par exemple, NORX et Gimli sont conçus avec le parallĂ©lisme Ă l'esprit.RĂ©cemment, l'intĂ©rĂȘt pour ce sujet a Ă©galement augmentĂ© dans la communautĂ© PRNG non cryptographique. En particulier, les primitives existantes qui n'ont pas Ă©tĂ© conçues pour SIMD peuvent ĂȘtre Ă la base de la crĂ©ation de PRN trĂšs rapides.Lorsque Sebastiano Vigna a fait la promotion de son architecture xoshiro256 ++ dans la bibliothĂšque standard Julia, il a dĂ©couvert que les rĂ©sultats de huit instances PRNG compĂ©titives et initialisĂ©es diffĂ©remment peuvent ĂȘtre concatĂ©nĂ©es trĂšs rapidement si chaque opĂ©ration est effectuĂ©e simultanĂ©ment dans tous les PRNR.SIMD n'est qu'un des niveaux de parallĂ©lisation du processeur. Je recommande de lire l' article prĂ©cĂ©dent sur ce sujet afin d'avoir une meilleure idĂ©e, mais je vais donner quelques explications.Les pipelines de processeurs permettent de traiter plusieurs instructions Ă diffĂ©rentes Ă©tapes. Si vous organisez bien l'ordre de leur exĂ©cution afin de rĂ©duire les dĂ©pendances entre les Ă©tapes, vous pouvez accĂ©lĂ©rer le traitement des instructions.L'exĂ©cution superscalaire vous permet de traiter simultanĂ©ment les parties informatiques des instructions. Mais pour cela, ils ne devraient pas avoir de dĂ©pendances en lecture-Ă©criture. Vous pouvez adapter l'architecture pour rĂ©duire le risque de temps d'arrĂȘt en enregistrant bien avant la lecture.Une exĂ©cution extraordinaire permet au processeur d'exĂ©cuter des instructions non pas dans l'ordre de sĂ©quence, mais lorsqu'elles sont prĂȘtes, mĂȘme si les instructions prĂ©cĂ©dentes ne sont pas encore prĂȘtes. Mais pour cela, il ne devrait pas y avoir de dĂ©pendance en lecture-Ă©criture.Et maintenant, nous passons Ă la mise en Ćuvre!Architecture
Considérons un schéma appelé semi-SHISHUA. La provenance d'un tel nom deviendra progressivement apparente à mesure que vous lirez.Le schéma ressemble à ceci:Considérez sa ligne par ligne.typedef struct prng_state {
__m256i state[2];
__m256i output;
__m256i counter;
} prng_state;
L'Ă©tat est divisĂ© en deux parties, qui sont placĂ©es dans le registre AVX2 (256 bits). Pour augmenter la vitesse, nous gardons le rĂ©sultat proche de l'Ă©tat lui-mĂȘme, mais il ne fait pas partie de l'Ă©tat.Nous avons Ă©galement un compteur 64 bits. Pour simplifier le calcul, c'est aussi un registre AVX2. Le fait est que AVX2 a une petite fonctionnalitĂ©: les registres ordinaires (% rax et similaires) ne peuvent pas ĂȘtre transfĂ©rĂ©s directement vers SIMD via MOV, ils doivent passer par la RAM (le plus souvent via la pile), ce qui augmente le dĂ©lai et coĂ»te deux instructions de processeur (MOV sur la pile, VMOV de la pile).Voyons maintenant la gĂ©nĂ©ration. Commençons par charger, puis parcourons le tampon et remplissons-le avec 32 octets Ă chaque itĂ©ration.inline void prng_gen(prng_state *s, __uint64_t buf[], __uint64_t size) {
__m256i s0 = s->state[0], counter = s->counter,
s1 = s->state[1], o = s->output;
for (__uint64_t i = 0; i < size; i += 4) {
_mm256_storeu_si256((__m256i*)&buf[i], o);
// âŠ
}
s->state[0] = s0; s->counter = counter;
s->state[1] = s1; s->output = o;
}
Puisque la fonction est en ligne, le remplissage immédiat du tampon au démarrage permet au processeur d'exécuter immédiatement les instructions en fonction de cela grùce à un mécanisme d'exécution extraordinaire.à l'intérieur de la boucle, nous effectuons rapidement trois opérations d'état:- SHI ft
- SHU ffle
- Un dd
D'oĂč le nom SHISHUA!Premier quart de travail
u0 = _mm256_srli_epi64(s0, 1); u1 = _mm256_srli_epi64(s1, 3);
Malheureusement, l'AVX2 ne prend pas en charge les révolutions. Mais je veux mélanger les bits d'une position dans un nombre 64 bits avec les bits d'une autre position! Et le changement est le meilleur moyen de réaliser cela. Nous allons décaler d'un nombre impair, de sorte que chaque bit visite toutes les positions 64 bits, et non la moitié d'entre elles.Pendant le quart de travail, des bits sont perdus, ce qui entraßne la suppression d'informations de notre état. C'est mauvais, vous devez minimiser les pertes. Les plus petits nombres impairs sont 1 et 3, nous utiliserons différentes valeurs de décalage pour augmenter l'écart entre les deux parties. Cela aidera à réduire la similitude de leur auto-corrélation.Nous allons déplacer vers la droite, car les bits les plus à droite ont la diffusion la plus faible lors de l'addition: par exemple, le bit le moins significatif dans A + B est juste le XOR des bits les moins significatifs A et B.En remuant
t0 = _mm256_permutevar8x32_epi32(s0, shu0); t1 = _mm256_permutevar8x32_epi32(s1, shu1);
Nous utiliserons le mixage 32 bits, car cela donne une granularité différente par rapport aux opérations 64 bits que nous utilisons partout (l'alignement 64 bits est violé). Il peut également s'agir d'une opération transversale: d'autres shuffles peuvent déplacer des bits dans les 128 bits à gauche s'ils commencent à gauche, ou dans les 128 bits à droite s'ils commencent à droite.Mélange de constantes:__m256i shu0 = _mm256_set_epi32(4, 3, 2, 1, 0, 7, 6, 5),
shu1 = _mm256_set_epi32(2, 1, 0, 7, 6, 5, 4, 3);
Pour que le mĂ©lange amĂ©liore vraiment le rĂ©sultat, nous dĂ©placerons les parties 32 bits faibles (faible dispersion) des ajouts 64 bits vers des positions fortes, de sorte que les ajouts suivants les enrichissent.La partie 32 bits bas de gamme du bloc 64 bits ne se dĂ©place jamais vers le mĂȘme bloc 64 bits que la partie d'ordre supĂ©rieur. Ainsi, les deux parties ne restent pas dans le mĂȘme morceau, ce qui amĂ©liore le mĂ©lange.Au final, chaque partie 32 bits passe par toutes les positions d'un cercle: de A Ă B, de B Ă C, ... de H Ă A.Vous avez peut-ĂȘtre remarquĂ© que le mixage le plus simple qui prend en compte toutes ces exigences est deux 256 bits chiffre d'affaires (tours de 96 bits et 160 bits Ă droite, respectivement).Une addition
Ajoutons des morceaux 64 bits à partir de deux variables temporaires - décalage et mixage.s0 = _mm256_add_epi64(t0, u0); s1 = _mm256_add_epi64(t1, u1);
L'addition est la principale source de dispersion: dans cette opération, les bits sont combinés en combinaisons irréductibles d'expressions XOR et AND réparties sur des positions 64 bits.Le stockage du résultat de l'addition dans un état préserve durablement cette dispersion.Fonction de sortie
D'oĂč tirons-nous la sortie?C'est simple: la structure que nous avons créée nous permet de gĂ©nĂ©rer deux parties indĂ©pendantes de l'Ă©tat s0 et s1, qui ne s'affectent en aucune façon. Appliquez XOR sur eux et obtenez un rĂ©sultat complĂštement alĂ©atoire.Pour renforcer l'indĂ©pendance entre les donnĂ©es auxquelles nous appliquons XOR, nous prenons un rĂ©sultat partiel: la partie dĂ©calĂ©e d'un Ă©tat et la partie mixte d'un autre.o = _mm256_xor_si256(u0, t1);
Cela revient Ă rĂ©duire les dĂ©pendances en lecture-Ă©criture entre les instructions d'un processeur superscalaire, comme si u0 et t1 Ă©taient prĂȘts Ă lire en s0 et s1.Maintenant, discutez du compteur. Nous le traitons au dĂ©but du cycle. Tout d'abord, modifiez l'Ă©tat, puis augmentez la valeur du compteur:s1 = _mm256_add_epi64(s1, counter);
counter = _mm256_add_epi64(counter, increment);
Pourquoi changeons-nous d'abord l'Ă©tat, puis mettons Ă jour le compteur? s1 devient disponible plus tĂŽt, ce qui rĂ©duit la probabilitĂ© que les instructions suivantes qui le lisent s'arrĂȘtent dans le pipeline du processeur. De plus, cette sĂ©quence permet d'Ă©viter la dĂ©pendance directe du compteur de lecture-Ă©criture.Nous appliquons le compteur Ă s1, et non Ă s0, car ils affectent tous les deux la sortie de toute façon, cependant, s1 perd plus de bits en raison du dĂ©calage, de sorte qu'il l'aide à «se remettre sur pied» aprĂšs le dĂ©calage.Le compteur peut ne pas enregistrer le test PractRand. Son seul objectif est de fixer une limite infĂ©rieure de 2 69octets = 512 exbibytes pour la pĂ©riode PRNG: on ne recommence le cycle qu'aprĂšs un millĂ©naire de travail Ă une vitesse de 10 gibytes par seconde. Il est peu probable qu'il soit trop lent pour une utilisation pratique dans les siĂšcles Ă venir.IncrĂ©ment:__m256i increment = _mm256_set_epi64x(1, 3, 5, 7);
Les nombres impairs sont sélectionnés comme incréments, car seuls les nombres premiers de base couvrent tout le cycle du champ fini GF (2 64 ), et tous les nombres impairs sont premiers de 2. En d'autres termes, si vous incrémentez d'un entier pair dans la plage de 0 à 4, revenant à 0 aprÚs 4, il s'avÚre que la séquence 0-2-0-2- ..., qui ne conduira jamais à 1 ou 3. Et l'incrément impair passe par tous les entiers.Pour tous les nombres 64 bits en état, nous utiliserons des nombres impairs différents, ce qui les séparera davantage et augmentera légÚrement le mélange. J'ai choisi les plus petits nombres impairs pour qu'ils n'aient pas l'air magique.C'est ainsi que la transition d'état et la fonction de sortie fonctionnent. Comment les initialiser?Initialisation
Nous initialisons l'état en utilisant les chiffres hexadécimaux Ί, le nombre irrationnel le moins approximé par la fraction.static __uint64_t phi[8] = {
0x9E3779B97F4A7C15, 0xF39CC0605CEDC834, 0x1082276BF3A27251, 0xF86C6A11D0C18E95,
0x2767F0B153D27B7F, 0x0347045B5BF1827F, 0x01886F0928403002, 0xC1D64BA40F335E36,
};
Prenez une graine 256 bits. Cela se fait souvent en cryptographie et ne nuit pas au travail des PRNG non cryptographiques:prng_state prng_init(SEEDTYPE seed[4]) {
prng_state s;
// âŠ
return s;
}
Nous ne voulons pas redéfinir toute la partie de l'état (s0 ou s1) avec ce nombre initial, il suffit d'en affecter la moitié. De cette façon, nous éviterons l'utilisation de nombres initiaux atténuants, qui provoquent accidentellement ou intentionnellement un état initial faible connu.Comme nous ne modifions pas la moitié de chaque état, nous gardons le contrÎle sur 128 bits d'état. Une telle entropie est suffisante pour démarrer et maintenir une position forte.s.state[0] = _mm256_set_epi64x(phi[3], phi[2] ^ seed[1], phi[1], phi[0] ^ seed[0]);
s.state[1] = _mm256_set_epi64x(phi[7], phi[6] ^ seed[3], phi[5], phi[4] ^ seed[2]);
Ensuite, nous répétons ( ROUNDS
) plusieurs fois la séquence suivante:- Exécutez les étapes (
STEPS
) des itérations SHISHUA. - Nous attribuons une partie de l'état à un autre état et l'autre partie à la sortie.
for (char i = 0; i < ROUNDS; i++) {
prng_gen(&s, buf, 4 * STEPS);
s.state[0] = s.state[1];
s.state[1] = s.output;
}
L'attribution d'un résultat de sortie augmente la dispersion des états. Lors de l'initialisation, le travail supplémentaire et la corrélation des états n'ont pas d'importance, car cette série d'opérations est effectuée une seule fois. Nous ne nous intéressons qu'à la dispersion lors de l'initialisation.AprÚs avoir évalué l'effet sur la corrélation des valeurs initiales, j'ai choisi STEPS
2 pour la valeur et ROUNDS
10 pour 10. J'ai calculé la corrélation en calculant les anomalies «inhabituelles» et «suspectes» résultant des outils de contrÎle qualité PRNG dans PractRand.Performance
Il est difficile de mesurer la vitesse pour plusieurs raisons:- La mesure de l'horloge n'est peut-ĂȘtre pas suffisamment prĂ©cise.
- , , - , -, .
- , . .
- : , .
J'utilise l'instruction du processeur RDTSC, qui calcule le nombre de cycles.Pour que tout le monde puisse reproduire mes rĂ©sultats, j'utilise une machine virtuelle basĂ©e sur le cloud. Cela ne change pas le niveau des rĂ©sultats de rĂ©fĂ©rence par rapport aux tests locaux. De plus, vous n'avez pas Ă acheter le mĂȘme ordinateur que le mien. Enfin, il existe de nombreuses situations oĂč le PRNG est lancĂ© dans les nuages.J'ai choisi Google Cloud Platform N2 (processeur Intel) et N2D (processeur AMD). L'avantage de GCP est qu'il propose des serveurs avec des processeurs des deux fabricants. Dans cet article, nous nous concentrerons sur Intel, mais pour AMD, les rĂ©sultats seront dans le mĂȘme ordre.Pour approfondir le sujet, dĂ©barrassons-nous d'abord de l'ancien gĂ©nĂ©rateur cryptographique RC4. Impossible de parallĂ©liser le travail, j'ai7,5 cpb (cycles par octet gĂ©nĂ©rĂ©).Maintenant, exĂ©cutons un MCG trĂšs populaire et rapide: le Lehmer128 PRNG le plus simple , qui rĂ©ussit le test BigCrush, a montrĂ© 0,5 cpb . Wow, super!Ensuite, nous exĂ©cuterons le dernier dĂ©veloppement, qui est utilisĂ© pour les tables de hachage rapides - wyrand . 0,41 cpb , un peu mieux!Certains DSRP ne rĂ©ussissent pas le test PractRand de 32 tĂ©raoctets, mais ils fonctionnent trĂšs rapidement. Xoshiro256 + n'a atteint que 512 mĂ©gaoctets, mais a montrĂ© une vitesse trĂšs Ă©levĂ©e: 0,34 cpb .Un autre dĂ©veloppement rĂ©cent de RomuTrio . Elle prĂ©tend ĂȘtre le PRNG le plus rapide au monde - 0,31 cpb.D'accord, ça suffit. Qu'est-ce que le semi-SHISHUA a montrĂ©?0,14 cpb . Deux fois plus vite que RomuTrio.Cool. Testez maintenant le gĂ©nĂ©rateur cryptographique ChaCha8. Il a atteint ... 0,12 cpb .Oh.SIMD est une vraie magie!Pour la communautĂ© cryptographique, ce n'Ă©tait pas une surprise particuliĂšre . ChaCha8 est extrĂȘmement facile Ă parallĂ©liser. Ceci est juste un compteur bien hachĂ© dans un Ă©tat diffus.Et vous vous souvenez comment l'Ă©quipe linguistique de Julia a essayĂ© de combiner plusieurs instances de l'architecture de Vigny pour crĂ©er un PRNG rapide basĂ© sur SIMD? Regardons leur rĂ©sultat en utilisant cette technique ( 8 piĂšces de Xoshiro256 + ). 0,09 cpb !Techniquement, mon ordinateur portable pourrait affecter les rĂ©sultats. Je ne sais pas pourquoi le dĂ©veloppement de l'Ă©quipe Julia est plus rapide que ChaCha8 dans GCP, mais plus lent lorsqu'il est testĂ© localement. Sur ma machine, semi-SHISHUA tourne plus vite que le dĂ©veloppement de l'Ă©quipe Julia, mais plus lentement que ChaCha8.Il est nĂ©cessaire de vaincre tous les concurrents.Vous vous demandez probablement dĂ©jĂ pourquoi nous avons appelĂ© la version prĂ©cĂ©dente du gĂ©nĂ©rateur semi-SHISHUA? Parce qu'il s'est avĂ©rĂ© facile de doubler la vitesse si vous exĂ©cutez deux copies de semi-SHISHUA.Semblable Ă l'idĂ©e de la commande Julia, nous initialisons sĂ©parĂ©ment deux PRNG (quatre blocs d'un Ă©tat 256 bits), fournissant alternativement la sortie de leur travail.Mais si nous crĂ©ons plus d'Ă©tats, nous pouvons produire encore plus de donnĂ©es, en combinant quatre Ă©tats par paires:o0 = _mm256_xor_si256(u0, t1);
o1 = _mm256_xor_si256(u2, t3);
o2 = _mm256_xor_si256(s0, s3);
o3 = _mm256_xor_si256(s2, s1);
Nous avons donc obtenu SHISHUA, qui a montré une vitesse de 0,06 cpb .C'est deux fois plus rapide que le précédent concurrent le plus rapide au monde qui a réussi le test PractRand de 32 téraoctets. Le résultat est sur le graphique.Je pense que le développement s'est révélé compétitif. Cela fonctionne encore plus rapidement sur mon ordinateur portable - 0,03 cpb, mais je respecterai mes principes concernant le benchmark.J'espÚre que pendant quelques semaines encore mon générateur restera sur le podium des plus rapides du monde (veuillez le faire).Qualité
Le gĂ©nĂ©rateur passe honnĂȘtement BigCrush et le test PractRand de 32 tĂ©raoctets. Et tout cela grĂące Ă quatre flux de sortie.Les inconvĂ©nients de l'architecture incluent son irrĂ©versibilitĂ© . Cela peut ĂȘtre vu en rĂ©duisant Ă un Ă©tat 4 bits avec s0 = [a, b]
et s1 = [c, d]
. Avec un décalage, nous obtenons [0, a]
et [0, d]
, et en remuant, [b, c]
et [d, a]
. De nouveaux s0
Ă©gaux [b, c] + [0, a] = [bâ(aâ§c), aâc]
, mais s1
Ă©gaux [d, a] + [0, c] = [dâ(aâ§c), aâc]
. Si a = ÂŹc
, alors, aâc = 1
et aâ§c = 0
donc, s0 = [b, 1]
et s1 = [d, 1]
. Autrement dit, nous obtenons deux combinaisons de a
et c
, qui nous donnent le mĂȘme Ă©tat final.Dans notre cas, ce n'est pas un problĂšme, car le compteur 64 bits fait Ă©galement partie de l'Ă©tat. Il s'avĂšre que le cycle minimum de 2 71octets (128 octets par transition d'Ă©tat), ce qui est Ă une vitesse de 10 gibytes / sec. durera sept mille ans. Cela Ă©quilibre les Ă©tats perdus.De plus, mĂȘme malgrĂ© l'irrĂ©versibilitĂ©, la pĂ©riode de transition moyenne entre les Ătats est de 2 ^ ((256 + 1) Ă· 2). Cela donne un cycle moyen de 2 135 octets (Ă une vitesse de 10 gibytes / sec. Il durera plus d'un billion de fois plus longtemps que l'univers n'existe). MĂȘme si je crois que les cycles intermĂ©diaires sont surestimĂ©s, car ils ne nous disent rien sur la qualitĂ© du gĂ©nĂ©rateur.Voici les rĂ©sultats de rĂ©fĂ©rence:- Performances : nombre de cycles de processeur passĂ©s sur un octet gĂ©nĂ©rĂ©. Reçu sur les machines cloud N2 GCP et N2D (AMD), la commande est la mĂȘme.
- Qualité : niveau auquel le générateur ne réussit pas le test PractRand. S'il n'échoue pas, il y a un signe>. Si le résultat n'est pas prouvé, il y a un point d'interrogation.
- Corrélation des nombres de graines : Traversée PractRand avec octets alternés de huit flux avec les nombres de graines 0, 1, 2, 4, 8, 16, 32, 64. Nous utilisons PractRand avec une double convolution et des tests avancés.
Plus loin
Bien que dans notre cas il n'y ait aucun problÚme d'irréversibilité, nous pouvons toujours améliorer SHISHUA.à mon avis, le PRNG idéal a les propriétés suivantes:- , 21024. 10 /. 10282 , . «» ( ). , . , 128- NEON ARM? , , .
- . , SHISHUA XOR . , .
- , 2128 ( ). SHISHUA, , . , ( ) (, , . 2).
- L'initialisation d'Ă©tat a une dispersion parfaite : tous les bits du nombre initial affectent tous les bits de l'Ă©tat avec la mĂȘme probabilitĂ©. Je veux en savoir plus sur SHISHUA.
L'un des problÚmes qui freinent le développement des PRNG et de la cryptographie dans son ensemble est le manque de meilleurs outils à usage général. J'ai besoin d'un outil qui puisse me donner immédiatement le résultat de mesure exact afin que je puisse comparer différentes architectures à la volée.PractRand est génial par rapport à ce qu'il était auparavant, cependant:- Il ne permet pas d'évaluer des générateurs de haute qualité, ce qui rend impossible leur comparaison les uns avec les autres. Nous devons dire: "eh bien, aprÚs 32 téraoctets, il n'y a pas d'anomalies ..."
- Cela prend des semaines pour l'exécuter ...
J'espÚre que la situation s'améliorera considérablement bientÎt.