是否有使用时间来播种随机数生成的替代方案?

CHP*_*CHP 30 c random random-seed

我试图在计算集群中同时运行一段代码(2000个实例左右)的几个实例.它的工作方式是我提交作业,集群将在节点每隔一段时间打开时运行它们,每个节点有几个作业.对于使用时间种子的随机数生成中的大量实例,这似乎产生相同的值.

我可以使用一个简单的替代方案吗?重复性和安全性并不重要,快速生成独特的种子.什么是最简单的方法,如果可能的话,跨平台方法会很好.

Mys*_*ial 26

rdtsc指令是一个非常可靠(和随机)的种子.

在Windows中,它可以通过__rdtsc()内在访问.

在GNU C中,可通过以下方式访问:

unsigned long long rdtsc(){
    unsigned int lo,hi;
    __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
    return ((unsigned long long)hi << 32) | lo;
}
Run Code Online (Sandbox Code Playgroud)

该指令测量自处理器通电以来的总伪周期.鉴于当今机器的频率很高,即使它们同时启动并且时钟速度相同,两个处理器也不太可能返回相同的值.

  • 您可以在同一个处理器甚至同一个内核上同时调用它。从技术上讲,同一处理器上的内核会有些同步,但这仍然不会成为问题,因为正常的抖动会使两个线程在同一周期内调用它的概率几乎为零。(即使它们在同一个周期被调用,也有充分的理由相信处理器会阻塞一个直到另一个完成 - 所以它甚至可能阻止它们向两个线程返回相同的值) (2认同)

Bri*_*edy 5

我假设您有一些流程启动其他流程.让它通过种子使用.然后,您可以让主进程只为每个进程传入一个随机数,以用作其种子.那种方式实际上只选择了一个任意种子......你可以用它来做时间.

如果您没有主进程启动其他进程,那么如果每个进程至少有一个唯一索引,那么您可以做的是让一个进程在内存中生成一系列随机数(如果共享内存)或在文件中(如果是共享磁盘)然后让每个进程将索引的随机数拉出来用作它们的种子.

没有什么能比单个种子的一系列随机数更均匀地分配种子.


Ada*_*eld 5

PID和时间的组合应该足以获得唯一的种子.它不是100%跨平台,但getpid(3)在*nix平台和GetProcessIdWindows上将获得99.9%的平台.这样的事情应该有效:

srand((time(NULL) & 0xFFFF) | (getpid() << 16));
Run Code Online (Sandbox Code Playgroud)

您也可以从/dev/urandom*nix系统上读取数据,但是在Windows上没有相同的数据.


Dig*_*oss 5

unsigned seed;

read(open("/dev/urandom", O_RDONLY), &seed, sizeof seed);
srand(seed); // IRL, check for errors, close the fd, etc...
Run Code Online (Sandbox Code Playgroud)

我还建议使用更好的随机数发生器.


Utk*_*waj 5

如果可以使用 C++11 则考虑std::random_device. 我建议您观看链接以获取全面的指南。

视频链接中提取基本信息:您永远不应该使用& ,而应该使用and - 在大多数情况下,以下内容就是您想要的:srandrandstd::random_devicestd::mt19937

#include <iostream>
#include <random>
int main() {
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_int_distribution<int> dist(0,99);
    for (int i = 0; i < 16; i++) {
        std::cout << dist(mt) << " ";
    }
    std::cout << std::endl;
}
Run Code Online (Sandbox Code Playgroud)