exponenta event banner

Генерация случайных чисел на графическом процессоре

В этом примере показано, как переключаться между различными генераторами случайных чисел, которые поддерживаются графическим процессором.

Случайные числа составляют ключевую часть многих алгоритмов моделирования или оценки. Как правило, эти числа генерируются с помощью функций rand, randi, и randn. Parallel Computing Toolbox™ предоставляет три соответствующие функции для генерации случайных чисел непосредственно на GPU: rand, randi, и randn. Эти функции могут использовать один из нескольких различных алгоритмов генерации чисел.

d = gpuDevice;
fprintf("This example is run on a " + d.Name + " GPU.")
This example is run on a GeForce GTX 1080 GPU.

Обнаружение генераторов случайных чисел GPU

Функция parallel.gpu.RandStream.list содержит краткое описание доступных генераторов.

parallel.gpu.RandStream.list
 
The following random number generator algorithms are available:
 
MRG32K3A:         Combined multiple recursive generator (supports parallel streams)
Philox4x32_10:    Philox 4x32 generator with 10 rounds (supports parallel streams)
Threefry4x64_20:  Threefry 4x64 generator with 20 rounds (supports parallel streams)

Каждый из этих генераторов был разработан с учетом параллельного использования, обеспечивая множество независимых потоков случайных чисел. Однако каждый из них имеет некоторые преимущества и недостатки:

  • CombRecursive (также известный как MRG32k3aЭтот генератор был введен в действие в 1999 году и широко опробован и используется.

  • Philox (также известный как Philox4x32_10): Новый генератор представлен в 2011 году, специально разработан для высокой производительности в сильно параллельных системах, таких как GPU.

  • Threefry (также известен как Threefry4x64_20): Новый генератор, представленный в 2011 году на основе существующего криптографического алгоритма ThreeFish, который широко тестируется и используется. Этот генератор был разработан для обеспечения хороших рабочих характеристик в сильно параллельных системах, таких как GPU. Это генератор по умолчанию для вычислений графического процессора.

Три генератора, доступные на GPU, также доступны для использования на CPU в MATLAB ®. Генераторы MATLAB имеют одинаковое имя и дают одинаковые результаты при одинаковом исходном состоянии. Это полезно, когда требуется создать одинаковые наборы случайных чисел как на GPU, так и на CPU .

Все эти генераторы проходят стандартный набор тестов TestU01 [1].

Изменение генератора случайных чисел по умолчанию

Функция gpurng может сохранять и сбрасывать состояние генератора для графического процессора. Также можно использовать gpurng для переключения между различными имеющимися генераторами. Перед изменением генератора сохраните существующее состояние, чтобы его можно было восстановить в конце этих тестов.

oldState = gpurng;

gpurng(0, "Philox4x32-10");
disp(gpurng)
     Type: 'philox'
     Seed: 0
    State: [7×1 uint32]

Генерация равномерно распределенных случайных чисел

Равномерно распределенные случайные числа генерируются на GPU с помощью одного rand, или randi. С точки зрения производительности эти две функции ведут себя очень одинаково и только rand измеряется здесь. gputimeit используется для измерения производительности для обеспечения точных результатов синхронизации, автоматического многократного вызова функции и правильного решения проблем синхронизации и других проблем синхронизации.

Для сравнения рабочих характеристик различных генераторов используйте rand для генерации большого количества случайных чисел на GPU с использованием каждого генератора. В следующем коде: rand генерирует 107 случайных чисел и вызывается 100 раз для каждого генератора. Каждый запуск синхронизируется с помощью gputimeit. Генерация больших выборок случайных чисел может занять несколько минут. Результаты показывают сравнение рабочих характеристик между тремя генераторами случайных чисел, доступными на GPU.

generators = ["Philox","Threefry","CombRecursive"];
gputimesU = nan(100,3);
for g=1:numel(generators)
    % Set the generator
    gpurng(0, generators{g});
    % Perform calculation 100 times, timing the generator 
    for rep=1:100
        gputimesU(rep,g) = gputimeit(@() rand(10000,1000,"gpuArray"));
    end
end
% Plot the results
figure
hold on
histogram(gputimesU(:,1),"BinWidth",1e-4);
histogram(gputimesU(:,2),"BinWidth",1e-4);
histogram(gputimesU(:,3),"BinWidth",1e-4)

legend(generators)
xlabel("Time to generate 10^7 random numbers (sec)")
ylabel("Frequency")
title("Generating samples in U(0,1) using " + d.Name)
hold off

Новые генераторы Threefry и Philox имеют схожую производительность. Обе функции быстрее CombRecursive.

Генерация нормально распределенных случайных чисел

Многие моделирования основаны на возмущениях, отобранных из нормального распределения. Аналогично единообразному испытанию, использование randn сравнивать рабочие характеристики трех генераторов при генерации нормально распределенных случайных чисел. Генерация больших выборок случайных чисел может занять несколько минут.

generators = ["Philox","Threefry","CombRecursive"];
gputimesN = nan(100,3);
for g=1:numel(generators)
    % Set the generator
    gpurng(0, generators{g});
    % Perform calculation 100 times, timing the generator 
    for rep=1:100
        gputimesN(rep,g) = gputimeit(@() randn(10000,1000,"gpuArray"));
    end
end
% Plot the results
figure
hold on
histogram(gputimesN(:,1),"BinWidth",1e-4);
histogram(gputimesN(:,2),"BinWidth",1e-4)
histogram(gputimesN(:,3),"BinWidth",1e-4)
legend(generators)
xlabel("Time to generate 10^7 random numbers (sec)")
ylabel("Frequency")
title("Generating samples in N(0,1) using " + d.Name)
hold off

Опять же, результаты показывают, что генераторы Threefry и Philox работают одинаково и оба заметно быстрее, чем CombRecursive. Дополнительная работа, необходимая для получения нормально распределенных значений, уменьшает скорость, с которой значения вырабатываются каждым из генераторов.

Перед окончанием восстановите исходное состояние генератора.

gpurng(oldState);

Заключение

В этом примере сравниваются три генератора случайных чисел GPU. Точные результаты зависят от графического процессора и вычислительной платформы. Каждый генератор обеспечивает некоторые преимущества (+) и имеет некоторые предостережения (-).

Threefry

  • (+) Быстрый

  • (+) На основе хорошо известного и проверенного алгоритма Threefish

  • (-) Относительно новое в реальном использовании

Philox

  • (+) Быстрый

  • (-) Относительно новое в реальном использовании

CombRecursive

  • (+) Долгий послужной список в реальном использовании

  • (-) Медленнее всего

Ссылки

[1] Л'Эквадер, П. и Р. Симард. «TestU01: библиотека C для эмпирического тестирования генераторов случайных чисел». Транзакции ACM на математическом программном обеспечении. Том 33, № 4, 2007, статья 22.

См. также

|

Связанные темы