Инструкция rdseed с несколькими потоками
Я хотел бы создать семена для пользовательских 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
int возвращает значение 1, если было сгенерировано случайное значение, и 0 в противном случае.
4.3.1 Рекомендации по повторным попыткам
В отличие от инструкции RDRAND, начальные значения поступают непосредственно из кондиционера энтропии, и вызывающие могут вызывать RDSEED быстрее, чем генерируются эти значения. Это означает, что приложения должны быть надежно спроектированы и подготовлены к сбоям вызовов RDSEED, поскольку начальные числа недоступны (CF=0).
Если только один поток вызывает RDSEED нечасто, очень маловероятно, что случайное начальное число не будет доступно. Только в периоды высокой нагрузки, например, когда один поток вызывает RDSEED в быстрой последовательности или несколько потоков одновременно вызывают RDSEED, возможны неполадки. Поскольку команда RDSEED не имеет встроенного механизма обеспечения справедливости, тем не менее, нет никаких гарантий относительно того, как часто поток должен повторять инструкцию, или сколько повторных попыток может потребоваться для получения случайного начального числа. На практике это зависит от количества аппаратных потоков на процессоре и от того, насколько агрессивно они вызывают RDSEED.
Насколько я понимаю, существует только один генератор начальных чисел на процессор, поэтому начальные числа не могут быть сгенерированы параллельно, и, поскольку для создания начального уровня требуется время, правильное решение, как мне кажется, состоит в том, чтобы каждое ядро / гиперпоток запрашивало нить по одному и иметь поток, который вызывает rdseed
подождите, пока оно не получит семя.
Так как мне нужно только одно семя на нить, то
#pragma omp critical
while(!_rdseed32_step(&r));
кажется, правильный подход ко мне.
1 ответ
Это будет работать. В очень маловероятном случае, если ГСЧ сломается в середине выполнения этого кода, он заблокируется в жестком цикле, но в реалистичных сценариях он даст вам случайное число, и все будет в порядке.
_rdseed16_step (), _rdseed32_step () и _rdseed64_step () следуют семантике инструкции RdSeed, которая должна возвращать бит успеха в CF и случайное число в целевом регистре. Таким образом, его можно запускать в цикле, чтобы получить столько случайных битов, сколько требуется.