C++11 并行化:犰狳 set_seed_random() 中的瓶颈
C++11 parallelization: bottleneck in Armadillo's set_seed_random()
在 C++11 中,使用 arma_rng::set_seed_random()
会产生瓶颈。我展示了一种重现它的方法。
考虑这个简单的代码:
#include <armadillo> // Load Armadillo library.
using namespace arma;
int main()
{
bool jj = true;
while ( jj == true ){
arma_rng::set_seed_random(); // Set the seed to generate random numbers.
double rnd_number = randu<double>(); // Generate a random number.
}
}
我用
编译了它
g++ -std=c++11 -Wall -g bayesian_estimation.cpp -o bayesian_estimation -O2 -larmadillo
当我 运行 终端中的可执行文件时,我看到其中一个内核正在以接近 100% 的 CPU% 处理它。如果我 运行 个它的更多实例,每个相应进程的 CPU% 会减少,但不会使用新的(和闲置的!)内核。我在 .
中详细说明了这种行为
为什么会这样?
我假设犰狳从 OS 维护的真实随机数池中获取 set_seed_random()
的种子(例如 /dev/random 在大多数 *NIX OS).由于这需要一个物理的熵源(通常是击键的时间、网络事件、其他中断源被使用),这个池是有限的并且可以比生成新的随机数更快地耗尽。
在您的情况下,我假设一个全速运行的可执行文件 运行 正在以与添加新熵大致相同的速度耗尽池。一旦添加第二个、第三个...,它们就会在等待新随机数进入随机数池时停止。
看看伪随机数生成器的代码,您会发现实例化它 and/or 给它一个新的种子可能是一个相当昂贵的过程。您通常应该只 instantiate/seed 每个线程一个 并在线程的剩余生命周期中使用它。
#include <armadillo> // Load Armadillo library.
using namespace arma;
int main()
{
bool jj = true;
arma_rng::set_seed_random(); // Set the seed to generate random numbers.
while ( jj == true ){
double rnd_number = randu<double>(); // Generate a random number.
}
}
看起来 arma_rng::set_seed_random() 使用了多种回退,除非定义了 ARMA_USE_CXX11
。我的猜测是它在尝试 /dev/urandom
时会很幸运。做 man urandom
了解更多信息。
在 C++11 中,使用 arma_rng::set_seed_random()
会产生瓶颈。我展示了一种重现它的方法。
考虑这个简单的代码:
#include <armadillo> // Load Armadillo library.
using namespace arma;
int main()
{
bool jj = true;
while ( jj == true ){
arma_rng::set_seed_random(); // Set the seed to generate random numbers.
double rnd_number = randu<double>(); // Generate a random number.
}
}
我用
编译了它g++ -std=c++11 -Wall -g bayesian_estimation.cpp -o bayesian_estimation -O2 -larmadillo
当我 运行 终端中的可执行文件时,我看到其中一个内核正在以接近 100% 的 CPU% 处理它。如果我 运行 个它的更多实例,每个相应进程的 CPU% 会减少,但不会使用新的(和闲置的!)内核。我在
为什么会这样?
我假设犰狳从 OS 维护的真实随机数池中获取 set_seed_random()
的种子(例如 /dev/random 在大多数 *NIX OS).由于这需要一个物理的熵源(通常是击键的时间、网络事件、其他中断源被使用),这个池是有限的并且可以比生成新的随机数更快地耗尽。
在您的情况下,我假设一个全速运行的可执行文件 运行 正在以与添加新熵大致相同的速度耗尽池。一旦添加第二个、第三个...,它们就会在等待新随机数进入随机数池时停止。
看看伪随机数生成器的代码,您会发现实例化它 and/or 给它一个新的种子可能是一个相当昂贵的过程。您通常应该只 instantiate/seed 每个线程一个 并在线程的剩余生命周期中使用它。
#include <armadillo> // Load Armadillo library.
using namespace arma;
int main()
{
bool jj = true;
arma_rng::set_seed_random(); // Set the seed to generate random numbers.
while ( jj == true ){
double rnd_number = randu<double>(); // Generate a random number.
}
}
看起来 arma_rng::set_seed_random() 使用了多种回退,除非定义了 ARMA_USE_CXX11
。我的猜测是它在尝试 /dev/urandom
时会很幸运。做 man urandom
了解更多信息。