cuRAND работает намного хуже, чем тяга при генерации случайных чисел внутри ядер CUDA - PullRequest
0 голосов
/ 18 марта 2020

Я пытаюсь сгенерировать «случайные» числа из равномерного распределения внутри ядра CUDA __global__, используя два разных подхода. Первый использует cuRAND API устройства, а второй - thrust. Для каждого подхода я создал свой класс.

Вот мое cuRAND решение:

template<typename T>
struct RNG1
{
    __device__
    RNG1(unsigned int tid) {
        curand_init(tid, tid, 0, &state);
    }

    __device__ T
    operator ()(void) {
        return curand_uniform(&state);
    }

    curandState state;
};

А вот мое thrust решение:

template<typename T>
struct RNG2
{
    __device__
    RNG2(unsigned int tid)
        : gen(tid)
        , dis(0, 1) { gen.discard(tid); }

    __device__ T
    operator ()(void) {
        return dis(gen);
    }

    thrust::default_random_engine gen;
    thrust::uniform_real_distribution<T> dis;
};

Я использую их следующим образом:

template<typename T> __global__ void
mykernel(/* args here */)
{
    unsigned int tid = blockIdx.x * blockDim.x + threadIdx.x;

    RNG1<T> rng(tid);
    // or
    RNG2<T> rng(tid);

    T a_random_number = rng();  

    // do stuff here
}

Оба они работают, но решение cuRAND намного медленнее (более чем в 3 раза медленнее). Если я установлю второй параметр curand_init (порядковый номер) на 0, то производительность будет такой же, как у решения thrust, но случайные числа будут «плохими». Я вижу шаблоны и артефакты в результате распределения.

Вот мои два вопроса:

  • Может кто-нибудь объяснить мне, почему решение cuRAND с ненулевой последовательностью медленнее?
  • Как можно thrust Быть так же быстро, как cuRAND с нулевой последовательностью, но также генерировать хорошие случайные числа?
  • При поиске в Google я заметил, что большинство людей используют cuRAND, и очень немногие используют thrust для генерации случайные числа внутри кода устройства. Есть ли что-то, о чем я должен знать? Я неправильно использую thrust?

Спасибо.

1 Ответ

3 голосов
/ 18 марта 2020

Возможно, разница в производительности происходит из-за того, что cuRAND и Thrust используют разные алгоритмы PRNG с разными профилями производительности и требованиями к памяти. Обратите внимание, что cuRAND поддерживает пять различных алгоритмов PRNG, и ваш код не дает того, какой из них используется.

Thrust's default_random_engine в настоящее время minstd_rand, но в документации отмечается, что это "может измениться в будущем версия". (Комментарий, написанный после того, как я написал мой, также отметил, что это minstd_rand.) minstd_rand - простой линейный конгруэнтный генератор, который может быть быстрее, чем любой PRNG, используемый cuRAND.

Этот комментарий был преобразован в ответить и отредактировать.

...