Я хотел бы сгенерировать семена для пользовательского PRNG, используя инструкцию rdseed
с несколькими ядрами.
Вот что у меня есть до сих пор, используя OpenMP.
//gcc -Wall -O3 -fopenmp -mrdseed myrand.c
#include <x86intrin.h>
#include <stdio.h>
int main(void) {
#pragma omp parallel
{
unsigned r;
#pragma omp critical
while(!_rdseed32_step(&r));
//prng_init(r);
printf("%d\n", r);
}
}
Является ли это правильным/идеальным способом создания начального числа для каждого потока? Нужен ли мне критический раздел при вызове rdseed
. Встроенная функция _rdseed32_step
возвращает 1, если было сгенерировано случайное значение, и 0 в противном случае.
4.3.1 Рекомендации по повторным попыткам
В отличие от инструкции RDRAND, начальные значения поступают непосредственно из кондиционера энтропии, и вызывающая сторона может вызывать RDSEED быстрее, чем эти значения генерируются. Это означает, что приложения должны быть разработаны надежно и быть готовыми к сбою вызовов RDSEED из-за отсутствия начальных значений (CF=0).
Если только один поток нечасто вызывает RDSEED, очень маловероятно, что случайное начальное число будет недоступно. Только в периоды повышенного спроса, например, когда один поток вызывает RDSEED в быстрой последовательности или несколько потоков одновременно вызывают RDSEED, возможно возникновение потери памяти. Однако, поскольку инструкция RDSEED не имеет встроенного механизма справедливости, нет никаких гарантий относительно того, как часто поток должен повторять выполнение инструкции или сколько повторных попыток может потребоваться для получения случайного начального числа. На практике это зависит от количества аппаратных потоков на ЦП и от того, насколько агрессивно они вызывают RDSEED.
Насколько я понимаю, на каждый процессор приходится только один генератор начальных чисел, поэтому начальные значения не могут генерироваться параллельно, и, поскольку для создания начального числа требуется время, мне кажется, что правильное решение состоит в том, чтобы каждое ядро/гиперпоток запрашивало потока по одному, и пусть поток, вызывающий rdseed
, будет ждать, пока не получит начальное число.
Поскольку мне нужно только одно семя на поток, тогда
#pragma omp critical
while(!_rdseed32_step(&r));
мне кажется правильный подход.