gerador de números aleatórios uniforme thread-safe
-
03-07-2019 - |
Pergunta
Eu tenho algum código Fortran90 paralelo em que cada thread precisa para gerar a mesma sequência de números aleatórios.
Eu tenho um gerador de números aleatórios que parece ser thread-seguro, uma vez que, para uma determinada semente, eu sou completamente incapaz de repetir os mesmos resultados cada vez que eu executar o programa.
Eu surfei sem sucesso (quase) toda a web à procura de algum código de um RNG thread-safe. Alguém poderia me fornecer (o link para) o código de um?
Agradecemos antecipadamente!
Solução
Um bom Pseudorandom gerador de números para Fortran90 pode ser encontrada no Intel Math Kernel Vector estatística Biblioteca . Eles são thread-safe. Além disso, por que ele precisa ser threadsafe? Se você quiser cada thread para obter a mesma lista, instanciar um novo PRNG para cada segmento com a mesma semente.
Outras dicas
A maioria dos geradores de números aleatórios repetíveis precisa estado de alguma forma. Sem estado, eles não podem fazer o que vem a seguir. Para ser thread-safe, você precisa encontrar uma maneira de agarrar o estado-se (isto é, não pode ser global).
Quando você diz "necessidades para gerar a mesma sequência de números aleatórios" que quer dizer que
- Cada segmento precisa gerar um fluxo de números idênticos para o outro segmento? Isto implica a escolha da semente antes de descascar fios, em seguida, instanciar a um PRNG segmento local em cada segmento com a mesma semente.
ou
- Você quer ser capaz de repetir a mesma sequência de números entre diferentes execuções dos programas, mas cada thread gera a sua própria sequência autónoma? Neste caso, você ainda não pode compartilhar um único PRNG porque a seqüência de operação de rosca é não-determinista. Então semear um único PRNG com uma semente conhecida antes tópicos lançamento, e usá-lo para gerar as sementes iniciais para os fios. seguida Você geradores de segmento local instanciar em cada thread ...
Em cada um desses casos, você deve observar o que Neil Butterworth dizer sobre as estatísticas: a maioria das garantias usuais que o PRNG como a reivindicação são não confiável quando mix córregos gerado desta maneira.
Em ambos os casos você precisa de um PRNG segmento local. Eu não sei o que está disponível no f90 ... mas você também pode escrever você possui (lookup Mersenne Twister , e escrever um routne que leva o estado salvo como um parâmetro ...).
Em Fortran 77, este seria algo parecido
function PRNGthread (state)
double state(statesize)
c stuff happens here which uses and manipulates the state vector...
PRNGthread = result
return
e cada um dos seus segmentos devem manter um vetor de estado separado, embora todos usarão o mesmo valor inicial.
Eu entendo que você precisa cada fio para produzir o mesmo fluxo de números aleatórios.
Um bom Pseudo gerador aleatório que irá gerar um fluxo reproduzível de números e é bastante rápido é o MT19937 . Apenas certifique-se que você gera a semente antes da desova fora dos tópicos, mas gerar uma instância separada do MT em cada thread (fazer a instância do segmento MT local). Dessa forma, será garantido que cada MT irá produzir o mesmo fluxo de números.
Como sobre Sprng ? Eu não tentei me embora.
Eu codificado um Fortran 90 versão thread-safe da Mersenne Twister / MT19973. O estado do PRNG é salvo em um tipo derivado (randomNumberSequence), e você usar procedimentos para semear o gerador ou obter o elemento seguinte na sequência.
http: //code.google.com/p/i3rc-monte-carlo-model/source/browse/trunk/Code/RandomNumbersForMC.f95
As alternativas parecem ser:
- Use um objeto de sincronização (como uma extensão mútua) sobre as sementes do gerador valor. Esta, infelizmente, publicando seu código em acessos gerador
- Use o armazenamento de segmento local no gerador de modo que cada segmento tem sua própria semente - o que pode causar statstical problemas para a sua aplicação
- Se a sua plataforma suporta uma adequada operação atômica, use esse no semente (que provavelmente não vai, no entanto)
Não é uma lista muito encorajador, eu sei. E para adicionar a ele, eu não tenho nenhuma idéia de como implementar qualquer um deles em Fortran!
Este artigo https://www.cmiss.org/openCMISS/wiki/RandomNumberGenerationWithOpenMP não só link para uma implementação Fortran, mas menciona pontos-chave necessários para fazer uma utilizável PRNG com threads. O ponto mais importante é:
A versão Fortran90 de Zigurate tem várias variáveis ??e matrizes com o atributo 'SAVE'. A fim de paralelizar o RNG uniforme, então, parece que as mudanças são necessárias para fazer essas variáveis ??arrays com um valor separado para cada thread (cuidado com o falso compartilhamento). Então, quando a função PRNG é chamado, devemos passar o número do segmento, e usar o valor do estado correspondente.