Измените оператор if на (s >= 1.0 || s == 0.0)
. Еще лучше использовать break
, как показано в следующем примере, для SIMD-генерации гауссовых случайных чисел, возвращающих сложную пару (u, v). При этом используется генератор случайных чисел скручивания Мерсенна dsfmt()
. Если вам нужно только одно реальное случайное число, верните только u
и сохраните v
для следующего прохода.
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;
}
Этот алгоритм удивительно быстр. Время выполнения для вычисления двух случайных чисел (u, v) для четырех разных генераторов гауссовских случайных чисел составляет:
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)
Полиномиальные процедуры fast_sin и fast_cos Чарльза К. Гарретта ускоряют вычисления Бокса-Мюллера в 2,9 раза, используя вложенную полиномиальную реализацию функций cos() и sin(). SIMD Box Muller и полярные алгоритмы, безусловно, конкурентоспособны. Также их можно легко распараллелить. Используя gcc -Ofast -S, дамп ассемблерного кода показывает, что квадратный корень — это SIMD SSE2: sqrt --> sqrtsd %xmm0, %xmm0
Комментарий: получить точные тайминги с помощью gcc5 действительно сложно и неприятно, но я думаю, что это нормально: по состоянию на 03.02.2016: DLW
[1] Ссылка по теме: возврат указателя массива c malloc в cython
[2] Сравнение алгоритмов, но не обязательно для версий SIMD: http://www.doc.ic.ac.uk/~wl/papers/07/csur07dt.pdf
[3] Чарльз К. Гарретт: http://krisgarrett.net/papers/l2приблизительно.pdf
person
W9DKI
schedule
31.01.2016
float
, а неdouble
? Обычно это плохая идея.. - person R.. GitHub STOP HELPING ICE   schedule 13.03.2011float
иdouble
почти наверняка стоит одинаково, плюс вы все равно конвертируете туда и обратно вdouble
, когда вызываетеlog
иsqrt
. - person R.. GitHub STOP HELPING ICE   schedule 13.03.2011