使用多个线程生成随机数时的瓶颈
Bottleneck at random number generation with multiple threads
我在通过多个线程生成随机数时遇到了性能问题。这是对所有线程使用相同的随机引擎的原因。然后我实现了一个向量,其中包含每个线程的随机引擎(在堆栈溢出的另一篇文章中找到了这个解决方案)。但我希望每秒的迭代次数随着我正在执行的线程数而线性增长。但事实似乎并非如此。
下面是一个最小示例:
#include <random>
#include <omp.h>
const int threads = 4;
int main()
{
std::uniform_int_distribution<uint64_t> uint_dist;
std::vector<std::mt19937_64> random_engines;
std::random_device rd;
for (int i = 0;i < threads;i++)
random_engines.push_back(std::mt19937_64((rd())));
omp_set_num_threads(threads);
int counter = 0;
#pragma omp parallel for
for (int i = 0;i < threads;++i)
{
int thread = omp_get_thread_num();
while (counter < 100)
{
if (uint_dist((random_engines[thread])) < (1ULL << 42))
counter++;
}
}
}
使用一个活动线程执行此代码时,我的 CPU 上的平均执行时间为 ~4 秒。将线程设置为 4 给我的平均执行时间为 ~2 秒,因此线程数得到 4 的乘法器,最终加速为 2。我错过了什么吗?
首先,如果你有两个内核和超线程,它看起来像你的代码有四个处理器,但它不是速度的四倍,如果你幸运的话,它只是比两倍快一点。
其次,如果您使用所有CPU功率,您的计算机将发热,然后降低时钟速度。
第三,你可能使用了一个状态巨大的随机数。其中一个的状态可能适合 L1 缓存,但不适合其中四个的状态。这可能会带来巨大的减速。
第四,你有一个变量"计数器",它在线程之间共享,并在每次迭代时读取。这不会很快。
相关文章:
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 我需要线程函数在不停止实际程序的情况下,每2秒打印一次随机数
- C++ 生成线程安全随机数
- GSL+OMP:C++中的线程安全随机数生成器
- 使用mt19937_64生成随机数,用于多线程蒙特卡罗模拟
- 使用多个线程生成随机数时的瓶颈
- 具有随机数总和的多线程执行时间
- 线程安全随机数
- C++是线程安全的伪随机数生成器
- C++11随机数生成器的线程安全性
- 线程同步打印5个随机数
- 在Intel TBB函数对象中生成线程安全随机数(相同种子/不同种子)
- 在多线程中使用c++ 11随机库生成随机数是否像在多线程中使用rand()一样慢
- 确定性随机数生成器绑定到实例(线程无关)
- 多线程的随机数
- 从多个线程访问随机数引擎