Changez votre instruction if en (s >= 1.0 || s == 0.0)
. Mieux encore, utilisez un break
comme indiqué dans l'exemple suivant pour un nombre aléatoire SIMD gaussien générant le renvoi d'une paire complexe (u, v). Ceci utilise le générateur de nombres aléatoires Mersennedsfmt()
. Si vous ne voulez qu'un seul nombre aléatoire réel, renvoyez uniquement u
et enregistrez le v
pour la prochaine passe.
inline static void randn(double *u, double *v)
{
double s, x, y; // SIMD Marsaglia polar version for complex u and v
while (1){
x = dsfmt_genrand_close_open(&dsfmt) - 1.;
y = dsfmt_genrand_close_open(&dsfmt) - 1.;
s = x*x + y*y;
if (s < 1) break;
}
s = sqrt(-2.0*log(s)/s);
*u = x*s; *v = y*s;
return;
}
Cet algorithme est étonnamment rapide. Les temps d'exécution pour le calcul de deux nombres aléatoires (u, v) pour quatre générateurs de nombres aléatoires gaussiennes sont:
Times for delivering two Gaussian numbers (u + iv)
i7-2600K @ 4GHz, gcc -Wall -Ofast -msse2 ..
gsl_ziggurat = 20.3 (ns)
Box-Muller = 78.8 (ns)
Box-Muller with fast_sin fast_cos = 28.1 (ns)
SIMD Marsaglia polar = 35.0 (ns)
Les routines polynomiales fast_sin et fast_cos de Charles K. Garrett accélérer le calcul de Box-Muller d'un facteur 2,9 en utilisant une implémentation polynomiale imbriquée de cos() et sin(). Le SIMD Box Muller et les algorithmes polaires sont certainement compétitifs. En outre, ils peuvent être parallélisés facilement. En utilisant gcc -Ofast -S, le vidage du code d'assemblage montre que la racine carrée est la SIMD SSE2: sqrt -> sqrtsd% xmm0,% xmm0
Commentaire: il est vraiment difficile et frustrant d'obtenir des synchronisations précises avec gcc5, mais je pense que ce sont ok: au 03.02.2016: DLW
[1] lien connexe: c malloc array pointer return in cython
[2] Une comparaison des algorithmes, mais pas nécessairement pour les versions SIMD: http://www.doc.ic.ac.uk/~wl/papers/07/csur07dt.pdf
[3] Charles K. Garrett: http://krisgarrett.net/papers/l2approx.pdf
Un gaussien est illimité. Est-ce que je manque quelque chose? –
il y a une variance et une moyenne, je prends la moyenne comme 0 et la variance^2 comme 1, la distribution normale normale qui est. –
@nvm: Une distribution normale standard peut prendre n'importe quelle valeur entre -infinity et infinity avec une certaine probabilité; il n'y a pas de limite de portée sur le résultat. –