繁体   English   中英

std::uniform_real_distribution 与 std::uniform_int_distribution 性能

[英]std::uniform_real_distribution vs. std::uniform_int_distribution performance

我在一个应用程序中遇到了性能下降,我指出该应用程序是随机数据的生成。 我写了一个基本相同的简单基准:

#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++ 标准没有为随机数分布指定特定算法,包括uniform_int_distributionuniform_real_distribution

因此,您必须研究 C++ 标准库的特定实现(对于 Clang 编译器来说通常很容易,因为它倾向于使用开源库libstdc++ )。 但是,在区间 [a, b) 中生成浮点数(例如float )与在同一区间中生成 integer 之间存在差异:

  • 浮点数:在大多数实际情况下,给定区间内的浮点数比该区间内的整数多。 一个实现可以通过在 [0, 1) 中生成一个统一的随机浮点数(例如通过使用generate_canonical ,遗憾的是其规范目前存在缺陷)来生成一个范围内的统一浮点数,然后缩放该数字以适应uniform_real_distribution给出的范围。 这可能涉及使用浮点乘法、除法或其他操作。
  • 整数:在一个范围内生成整数通常涉及生成足够的随机位以适应该范围,然后使用模减少或拒绝采样(后者是无偏的)。 该过程往往不使用浮点运算(与 integer 运算相比相对较慢),这可以解释您发现的性能差异。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM