c++ - std::uniform_real_distribution与std::uniform_int_distribution性能

标签 c++ performance random floating-point

我发现我的一个应用程序的性能下降,而我的应用程序恰好是随机数据的生成。我写了一个简单的基准,基本上可以做到这一点:

#include <chrono>
#include <iostream>
#include <random>

std::mt19937 random_engine{std::random_device()()};

// Generate one million random numbers
template <typename T, typename Distribution>
std::vector<T> generate_random(Distribution distribution) {
  std::vector<T> data(1000000);

  std::generate_n(data.begin(), 1000000, [&]() {
    return static_cast<T>(distribution(random_engine));
  });
  return data;
}

template <typename T>
std::vector<T> create_data() {
  if constexpr (std::is_same_v<T, float>)
    return generate_random<float>(
        std::uniform_real_distribution<float>(-127.0f, 127.0f));
  if constexpr (std::is_same_v<T, int8_t>)
    return generate_random<int8_t>(
        std::uniform_int_distribution<int32_t>(-127, 127));
}

int main() {
  auto start = std::chrono::system_clock::now();
  auto float_data = create_data<float>();
  std::cout << "Time (float): " << (std::chrono::system_clock::now() - start).count()
            << '\n';

  start = std::chrono::system_clock::now();
  auto int8_data = create_data<int8_t>();
  std::cout << "Time (int8): " << (std::chrono::system_clock::now() - start).count()
            << '\n';

  return 0;
}
在我的机器上,输出:
〉g++ -v
...
Apple clang version 11.0.3 (clang-1103.0.32.29)
Target: x86_64-apple-darwin19.5.0
...

〉g++ tmp.cpp -std=c++17 -O3 && ./a.out
Time (float): 68033
Time (int8): 172771
为什么从真实分布中采样比从int分布中花费的时间更少?
更新
libc++和libstdc++表现出完全相反的行为。我仍在研究实现上的区别所在。参见libc++libstdc++

最佳答案

回想一下用于随机数分布的C++标准does not specify a particular algorithm,包括uniform_int_distributionuniform_real_distribution
因此,您将必须研究C++标准库的特定实现(对于Clang编译器来说,这通常很容易,因为它倾向于使用开源库libstdc++)。但是,在间隔[a,b)中生成浮点数(例如float)与在相同间隔中生成整数之间存在差异:

  • 浮点数:在大多数实际情况下,给定间隔中的浮点数要多于该间隔中的整数。一个实现可以通过在[0,1)中生成一个统一的随机浮点数来生成某个范围内的统一浮点数(例如,不幸的是,使用generate_canonical,其规范到目前为止是有缺陷的),然后将该数字缩放以适合uniform_real_distribution给出的范围。这可能涉及浮点乘法,除法或其他运算的使用。
  • 整数:生成一个范围内的整数通常涉及生成足够的随机位以适合该范围,然后使用模减少或拒绝采样(后者是无偏的)。该过程将倾向于不使用浮点运算(与整数运算相比,浮点运算相对较慢),这可以解释您发现的性能差异。
  • 关于c++ - std::uniform_real_distribution与std::uniform_int_distribution性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62783133/

    相关文章:

    c++ - boost::any_cast 到我的自定义类

    c++ - 在类定义之外重载运算符

    javascript - 使用 Javascript 从数组中选择随机形状

    Python 获取元组列表的随机样本

    我能否在调试时准确控制函数返回的内容(即 rand())?

    C++ memcpy 错误

    c++ - 如何使用 Boost.Assign 初始化 Boost.PropertyTree

    混淆导致性能损失?

    Javascript - 对于此函数中的每个变量赋值,替代 if/then

    performance - 快速、无分支的 unsigned int 绝对差