实例化c ++ 11随机设施的正确方法是什么

时间:2014-02-28 02:53:52

标签: c++ c++11 random instantiation

在查看了关于在C ++中使用新的“随机”工具的各种示例之后,我对最佳实践感到有些困惑 - 特别是与各种实例的生命周期相关。

例如,在某些示例中,“random_device”的使用在本地范围(如函数)中是静态的,或者是静态全局变量,或者只是一个本地变量。

--- TU ---

static std::random_device global_source;


void foo()
{
   static std::random_device local_static_source;
   static std::mt19937 gen(local_static_source());
   std::uniform_int_distribution<> dist(0,10);
   ...
   dist(gen);
   ...
}

void boo()
{
   std::mt19937 gen(global_source());
   std::uniform_int_distribution<> dist(0,10);
   ...
   dist(gen);
   ...
}

void roo()
{
   std::random_device local_source;
   std::mt19937 gen(local_source());
   std::uniform_int_distribution<> dist(0,10);
   ...
   dist(gen);
   ...
}

int main()
{
   static std::mt19937 gen(global_source());
   std::uniform_int_distribution<> dist(0,10);
   ...
   dist(gen);
   ...
  return 0;
}

--- TU ---

Q1:如果多个线程可以访问“foo”或“boo”,那么生成器和源是否可以是静态的? - 有没有像shared_ptr中那样的线程安全保证?

Q2:标准中是否有任何措辞可以讨论与实例化相关的假设和问题?

1 个答案:

答案 0 :(得分:1)

一些背景知识:允许多个随机数生成器实例的原因主要是线程安全(不会增加带有线程同步的随机数生成器实现)和可重复性(允许使用相同的种子重复一系列数字)。

  • 前者非常明显 - 在性能关键代码中使用RNG的有效案例。如果有多个实例,则不需要昂贵的互斥锁,并且可以在多个CPU内核上并行生成随机数。

  • 后者通常在随机生成数据集时很有用。作为一个常见的例子,视频游戏可以通过从同一个RNG(甚至可能在不同的网络PC上)推动与游戏世界创建相关的所有决策来重建相同(随机)游戏世界。

因此,C ++ RNG的最佳范围取决于您所写的内容:

如果您正在编写可能在上述方案的上下文中使用的库,那么让调用者为各个方法或类提供RNG可能是个好主意:

// Can be used on multiple CPU cores in parallel or with seed values
template <typename TRandomNumberEngine>
Point2 GetRandomPointInRectangle(
  const Rectangle2 &rect, TRandomNumberEngine &random
) {
  std::uniform_real_distribution<float> horizontal(rect.Min.X, rect.Max.X);
  float x = horizontal(random);

  std::uniform_real_distribution<float> vertical(rect.Min.Y, rect.Max.Y);
  float y = vertical(random);

  return Point2(x, y);
}

如果您正在编写应用程序或在支持角色中使用RNG的库(例如,几何拟合算法),即。您只对不可重复的随机数感兴趣,随机数生成器的最佳范围将是最大可能的范围,不会在模块之间引入不需要的耦合。

这可能是一个简单的私有对象变量,无论什么类都需要随机数,甚至是一个thread_local单例,如果它有很多短命的消费者可以证明这种复杂性,那么就会提供你选择的RNG。


分发(如std::uniform_real_distribution)可以像你想要的那样短暂。它们是简单的仿函数,其中构造函数没有参数或只存储函数执行时的参数。