Generating Gaussian random numbers using numpy turns out to be the bottleneck in my monte carlo simulation where I make heavy use of PyOpenCl.
np.random.randn(int(1e9))
Therefore I am looking for a way to generate Gaussian distributed random numbers with PyopenCl too.
I found a 6 years old thread asking a similar question. But I am not sure how to use VexCL library with PyOpenCl: Gaussian distributed random numbers in OpenCL
Any ideas how to implement a good RNG which performs similar as np.random.randn in PyOpenCl?
Seems like pyopencl already includes a random number generator:
https://github.com/inducer/pyopencl/blob/master/pyopencl/clrandom.py
Running a simple test shows, that the mean and standard deviation are comparable to numpy's implementation. Also the histogram corresponds to the normal distribution with negligible mean squared error.
Does anyone know further tests to check the quality of the random number generator?
Edit: According to https://documen.tician.de/pyopencl/array.html
import pytest
from pyopencl.clrandom import RanluxGenerator, PhiloxGenerator
import pyopencl as cl
import pyopencl.array as cl_array
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
def test_compare_to_numpy_rand():
context = cl.create_some_context()
queue = cl.CommandQueue(context)
rng = PhiloxGenerator(context=context)
mu=0
sigma=3
size = (int(1e8))
dtype = np.float32
numbers_cl = cl_array.zeros(queue, size, dtype=dtype)
rng.fill_normal(ary=numbers_cl, mu=mu, sigma=sigma)
numbers_cl_host = numbers_cl.get()
mu_meas = np.mean(numbers_cl_host)
sigma_meas = np.std(numbers_cl_host)
hist_cl, bins_edges = np.histogram(numbers_cl_host, bins=1000, normed=True)
delta = bins_edges[1] - bins_edges[0]
bins_center = bins_edges[:-1]+delta/2
plt.bar(bins_center, hist_cl,width=delta,label='cl')
numbers_np = mu + sigma * np.random.randn(size)
hist_np, bins_edges = np.histogram(numbers_np, bins=bins_edges, normed=True)
plt.bar(bins_center, hist_np, width=delta,alpha=0.8,label='numpy')
p = norm.pdf(bins_center, mu, sigma)
plt.plot(bins_center, p, color='red',label='Exact')
plt.title('Mean squared error: cl={:.5E} np={:.5E}'.format(np.mean(np.abs(p-hist_cl)**2),np.mean(np.abs(p-hist_np)**2)))
plt.legend()
plt.show()
assert pytest.approx(mu_meas, 1e-2) == mu
assert pytest.approx(sigma_meas, 1e-2) == sigma
assert pytest.approx(mu_meas, 1e-2) == numbers_np.mean()
assert pytest.approx(sigma_meas, 1e-2) == numbers_np.std()