今天我和我的一个朋友谈话,他告诉我他试图用 GPU 做一些蒙特卡罗模拟。有趣的是,他告诉我他想在不同的处理器上随机抽取数字,并假设存在不相关的数字。但他们不是。
问题是,是否存在一种在多个 GPU 上绘制独立数字集的方法?他认为为他们每个人选择不同的种子可以解决问题,但事实并非如此。
如果需要任何澄清,请告诉我,我会要求他提供更多细节。
今天我和我的一个朋友谈话,他告诉我他试图用 GPU 做一些蒙特卡罗模拟。有趣的是,他告诉我他想在不同的处理器上随机抽取数字,并假设存在不相关的数字。但他们不是。
问题是,是否存在一种在多个 GPU 上绘制独立数字集的方法?他认为为他们每个人选择不同的种子可以解决问题,但事实并非如此。
如果需要任何澄清,请告诉我,我会要求他提供更多细节。
要生成完全独立的随机数,您需要使用并行随机数生成器。本质上,您选择一个种子,它会生成M个独立的随机数流。因此,您可以在M GPU中的每一个上从独立的流中生成随机数。
在处理多个 GPU 时,您需要注意:
事实证明,在每个 GPU 内核上生成随机数是很棘手的(请参阅我不久前提出的这个问题)。当我一直在玩 GPU 和 RN 时,如果你一次生成大量数字,你只会在 GPU 上生成随机数得到加速。
相反,我会在 CPU 上生成随机数,因为:
在评论中回答您的问题:随机数取决于什么?
一个非常基本的随机数生成器是线性同余生成器。尽管这个生成器已经被更新的方法所超越,它应该让你了解它们是如何工作的。基本上,第 i 个随机数取决于 (i-1) 个随机数。正如您所指出的,如果您运行两个流足够长的时间,它们将重叠。最大的问题是,你不知道它们什么时候会重叠。
要生成iid统一变量,您只需使用不同的种子初始化生成器。使用 Cuda,您可以使用实现 Mersenne Twister 生成器的 NVIDIA Curand 库。
例如,以下由 100 个内核并行执行的代码,将绘制 (R^10)-uniform 的 10 个样本
__global__ void setup_kernel(curandState *state,int pseed)
{
int id = blockIdx.x * blockDim.x + threadIdx.x;
int seed = id%10+pseed;
/* 10 differents seed for uncorrelated rv,
a different sequence number, no offset */
curand_init(seed, id, 0, &state[id]);
}
如果你使用任何“好的”生成器(例如 Mersenne Twister 等),具有不同随机种子的两个序列将不相关,无论是在 GPU 上还是在 CPU 上。因此,我不确定您所说的在不同的 GPU 上采用不同的种子是什么意思是不够的。你会详细说明吗?