Random 在openCL中的多个设备中保持RNG状态的最佳方法

Random 在openCL中的多个设备中保持RNG状态的最佳方法,random,opencl,gpu,prng,mersenne-twister,Random,Opencl,Gpu,Prng,Mersenne Twister,因此,我试图利用openCL的这个定制RNG库: 库定义了一个状态结构: //! Represents the state of a particular generator typedef struct{ uint x; uint c; } mwc64x_state_t; 为了生成随机uint,将状态传递到以下函数: uint MWC64X_NextUint(mwc64x_state_t *s) void MWC64X_SeedStreams(mwc64x_state_t *s, ulo

因此,我试图利用openCL的这个定制RNG库:

库定义了一个状态结构:

//! Represents the state of a particular generator
typedef struct{ uint x; uint c; } mwc64x_state_t;
为了生成随机uint,将状态传递到以下函数:

uint MWC64X_NextUint(mwc64x_state_t *s)
void MWC64X_SeedStreams(mwc64x_state_t *s, ulong baseOffset, ulong perStreamOffset)
它更新状态,这样当您再次将其传递到函数中时,将生成序列中的下一个“随机”数

对于我正在创建的项目,我不仅需要能够在不同的工作组/项目中生成随机数,还需要能够同时跨多个设备生成随机数,而我很难找到最佳的设计方法。我是否应该为每个设备/命令队列创建1个mwc64x_state_t对象,并将该状态作为全局变量传入?或者可以一次为所有设备创建一个状态对象吗? 或者我甚至不把它作为一个全局变量传入,并在每个内核函数中局部声明一个新状态

该库还具有以下功能:

uint MWC64X_NextUint(mwc64x_state_t *s)
void MWC64X_SeedStreams(mwc64x_state_t *s, ulong baseOffset, ulong perStreamOffset)
它应该将RNG分割成多个“流”,但在我的内核中包含它会让它的运行速度非常慢。例如,如果我做了如下非常简单的事情:

__kernel void myKernel()
{
    mwc64x_state_t rng;
    MWC64X_SeedStreams(&rng, 0, 10000);
}
然后内核调用会慢40倍左右

该库确实附带了一些用作示例用法的源代码,但示例代码有点有限,似乎没有多大帮助


因此,如果有人熟悉openCL中的RNG,或者您以前使用过这个特定的库,我将非常感谢您的建议。

MWC64X\u SeedStreams函数确实相对较慢,至少相比之下是如此 对于MWC64X_NextUint调用,但对于大多数尝试 将大型全局流拆分为多个子流,这些子流可用于 平行的假设您将多次致电NextUint 在内核中(例如,100个或更多),但SeedStreams仅位于顶部

这是随附的EstimatePi示例的注释版本 使用库(mwc64x/test/estimate_pi.cpp和mwc64x/test/test_mwc64x.cl)

那么流中的索引将是:

[0             .. N ) : Parts of stream used across all devices
[k*(W*C)       .. (k+1)*(W*C) )    : Used within device k
[k*(W*C)+(i*C) .. (k*W*C)+(i+1)*C ) : Used by work-item i in device k.
如果每个内核使用的样本少于C,则可以 如有必要,估计过高


(我是该库的作者)。

MWC64X_SeedStreams函数确实相对较慢,至少与之相比是如此 对于MWC64X_NextUint调用,但对于大多数尝试 将大型全局流拆分为多个子流,这些子流可用于 平行的假设您将多次致电NextUint 在内核中(例如,100个或更多),但SeedStreams仅位于顶部

这是随附的EstimatePi示例的注释版本 使用库(mwc64x/test/estimate_pi.cpp和mwc64x/test/test_mwc64x.cl)

那么流中的索引将是:

[0             .. N ) : Parts of stream used across all devices
[k*(W*C)       .. (k+1)*(W*C) )    : Used within device k
[k*(W*C)+(i*C) .. (k*W*C)+(i+1)*C ) : Used by work-item i in device k.
如果每个内核使用的样本少于C,则可以 如有必要,估计过高


(我是该库的作者)。

MWC64X_SeedStreams函数确实相对较慢,至少与之相比是如此 对于MWC64X_NextUint调用,但对于大多数尝试 将大型全局流拆分为多个子流,这些子流可用于 平行的假设您将多次致电NextUint 在内核中(例如,100个或更多),但SeedStreams仅位于顶部

这是随附的EstimatePi示例的注释版本 使用库(mwc64x/test/estimate_pi.cpp和mwc64x/test/test_mwc64x.cl)

那么流中的索引将是:

[0             .. N ) : Parts of stream used across all devices
[k*(W*C)       .. (k+1)*(W*C) )    : Used within device k
[k*(W*C)+(i*C) .. (k*W*C)+(i+1)*C ) : Used by work-item i in device k.
如果每个内核使用的样本少于C,则可以 如有必要,估计过高


(我是该库的作者)。

MWC64X_SeedStreams函数确实相对较慢,至少与之相比是如此 对于MWC64X_NextUint调用,但对于大多数尝试 将大型全局流拆分为多个子流,这些子流可用于 平行的假设您将多次致电NextUint 在内核中(例如,100个或更多),但SeedStreams仅位于顶部

这是随附的EstimatePi示例的注释版本 使用库(mwc64x/test/estimate_pi.cpp和mwc64x/test/test_mwc64x.cl)

那么流中的索引将是:

[0             .. N ) : Parts of stream used across all devices
[k*(W*C)       .. (k+1)*(W*C) )    : Used within device k
[k*(W*C)+(i*C) .. (k*W*C)+(i+1)*C ) : Used by work-item i in device k.
如果每个内核使用的样本少于C,则可以 如有必要,估计过高


(我是图书馆的作者)。

谢谢您的信息和澄清!不幸的是,我的内核工作项只需要对NextUint()进行大约12次调用,因此它似乎无法弥补调用SeedStreams()的巨大开销。感谢您提供的信息和说明!不幸的是,我的内核工作项只需要对NextUint()进行大约12次调用,因此它似乎无法弥补调用SeedStreams()的巨大开销。感谢您提供的信息和说明!不幸的是,我的内核工作项只需要对NextUint()进行大约12次调用,因此它似乎无法弥补调用SeedStreams()的巨大开销。感谢您提供的信息和说明!不幸的是,我的内核工作项只需要对每个NextUint()进行十几次左右的调用,因此它似乎无法弥补调用SeedStreams()的巨大开销。