SLURM上与时间有关的随机数种子出现问题

时间:2019-03-17 21:08:11

标签: c++ linux

因此,我从事暑期学生研究工作,并且我有一个C ++代码,可以运行需要随机数的模拟。我必须使用Slurm Scheduler运行大量的这些代码。现在,我的代码花了时间作为我的c ++代码中随机数生成器的种子。但是,如果我同时运行同一代码的多个作业提交,因为每次将它们放入队列时它们都需要大量的时间和资源才能运行,通常情况下,所有作业将在同一时间开始或以较大的组开始,这意味着每次运行将为随机数生成器提供相同的种子时间,这是一个问题,因为每次运行都需要唯一(或使用此方法尽可能接近),是否有办法让每次运行为输入唯一的种子每次运行。 我目前正在尝试在批处理运行的主文件夹中的每个文件夹中运行每个作业,并为每个文件输入一个由脚本生成的随机数,但这似乎效率很低。

1 个答案:

答案 0 :(得分:1)

不要花时间播种。通常最好使用std::random_device从熵池中产生不确定的随机数。

示例:

#include <iostream>
#include <random>

int main() {
    std::random_device rd;
    std::mt19937 generator(rd());
    std::uniform_int_distribution<uint32_t> dist20(1, 20);
    auto d20 = [&](){ return dist20(generator); };

    // generate 100 random numbers [1,20]
    for(int i=0; i<100; ++i)
        std::cout << d20() << "\n";
}

但是,在std:.random_device的某些实现中,即使熵池不为空,也会错误地报告熵为0。在Linux上,您可以尝试直接使用getrandom()从池中提取内容并将其用作种子。这是一种实现方式:

#include <iostream>
#include <random>

// https://github.com/llvm-mirror/libcxx/blob/master/src/random.cpp#L175
#include <errno.h>
#include <sys/random.h>

std::random_device::result_type backup_seed() {
    std::random_device::result_type seed;
    if(getrandom(&seed, sizeof(seed), 0) == sizeof(seed)) errno = 0;
    return seed;
}

std::random_device::result_type seed() {
    errno = EAGAIN;
    static thread_local std::random_device rd;
    if(rd.entropy()) return rd();
    return backup_seed();
}

int main() {
    std::mt19937 generator(seed());
    std::uniform_int_distribution<uint32_t> dist20(1, 20);
    auto d20 = [&]() { return dist20(generator); };

    // generate 100 random numbers [1,20]
    for(int i = 0; i < 100; ++i) std::cout << d20() << "\n";
}

请注意,您应该仅使用getrandom()来提取数字以进行播种,否则当/如果耗尽了熵池,您可能会有非常慢的随机数生成器的风险。