std :: random_shuffle threadsafe吗?我认为不是因为常规的rand()不是线程安全的。如果是这种情况,我将如何将rand_r与random_shuffle一起使用,以便为每个线程提供唯一的种子。我已经看到了使用随机随机生成器和random_shuffle的例子,但我仍然不清楚。
感谢。
答案 0 :(得分:4)
要将rand_r
与std::random_shuffle
一起使用,您需要编写一个(相当简单的)包装器。传递给random_shuffle
的随机数生成器需要接受一个参数,该参数指定要生成的数字范围,rand_r
不会。
您的包装器看起来像这样:
class rand_x {
unsigned int seed;
public:
rand_x(int init) : seed(init) {}
int operator()(int limit) {
int divisor = RAND_MAX/(limit+1);
int retval;
do {
retval = rand_r(&seed) / divisor;
} while (retval > limit);
return retval;
}
};
您可以使用random_shuffle
之类的内容:
std::random_shuffle(whatever.begin(), whatever.end(), rand_x(some_seed));
答案 1 :(得分:3)
你需要提供一个随机数生成器函数或functor对象,它接受一个整数值类型,并返回一些积分类型的另一个值,它不会溢出容器的边界,你传递给函数的迭代器正在迭代通过。同样在仿函数对象的情况下,它必须实现operator()
,以便可以像函数一样调用它。因为您需要一个线程安全的随机数生成器,所以使用srand
中的rand
和cstdlib
是一个坏主意...您应该创建一些实现线程安全的仿函数对象随机数生成器,或不实现全局可访问变量的随机数生成器,以便所有内容都保持线程本地存储。
因此,例如,这种方法可行的一种方法是,您从另一个库中获得某种类型的随机数生成器,它只会在固定值范围之间生成随机值,因此您可以定义容器的边界random_shuffle
算法使用的随机访问迭代器。现在,根据您使用的库,您的仿函数可能如下所示:
class my_rand_gen
{
private:
random_gen_type random_range_gen;
int min;
int max;
public:
my_rand_gen(const random_gen_type& gen, int min_range, int max_range):
random_range_gen(gen), min(min_range), max(max_range) {}
int operator()(int value)
{
//ignore the input value and use our own defined range
//returns a value between min and max
return random_range_gen(min, max);
}
};
现在你可以调用算法:
random_shuffle(my_vector_start_iter, my_vector_end_iter,
my_rand_gen(rand_generator_lib,
vector_start_index,
vector_end_index));
它会将开始和结束迭代器之间的向量混合到向量中而不会溢出向量的边界...换句话说,它只会使用vector_start_index
和{{之间的混洗值1}}。
答案 2 :(得分:1)
可能不是。
使用第二版adnrom_shuffle,它为随机数生成器提供模板参数:http://www.sgi.com/tech/stl/random_shuffle.html。生成器必须匹配:http://www.sgi.com/tech/stl/RandomNumberGenerator.html
struct MyRandomNumberGenerator
{
int operator()(int limit) const
{
// get threadsafe random number
}
};
// Stuff
random_shuffle(list.begin(), list.end(), MyRandomNumberGenerator());