Является ли random_shuffle потокобезопасным?и используя rand_r, если это не так - PullRequest
12 голосов
/ 05 июля 2011

Безопасен ли std :: random_shuffle?Я полагаю, нет, так как обычный rand () не является потокобезопасным.Если это так, как бы я использовал rand_r с random_shuffle, чтобы дать каждому потоку уникальное начальное число.Я видел примеры использования пользовательских генераторов случайных чисел с random_shuffle, но мне все еще неясно.

Спасибо.

Ответы [ 3 ]

4 голосов
/ 05 июля 2011

Чтобы использовать 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));
3 голосов
/ 05 июля 2011

Вам необходимо предоставить функцию генератора случайных чисел или объект-функтор, который принимает тип целочисленного значения и возвращает другое значение некоторого целочисленного типа, которое не будет выходить за границы контейнера, который повторяют итераторы, переданные в функцию.через.Также в случае объекта функтора он должен реализовывать 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 и vector_end_index.

1 голос
/ 05 июля 2011

Вероятно, нет.

Используйте вторую версию 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());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...