6

intel ハードウェア prng (rdrand) を numpy プログラムで使用して乱数のバッファを埋めることができる既製のライブラリはありますか?

これに失敗すると、誰かが私が適応または使用できるいくつかのCコードの正しい方向に私を向けることができます(私はnumpyでCPythonとCythonを使用しているため、最低限のラッパーshdで十分です)。

私が望む乱数発生器は、[0,1) の間の一様乱数です。

4

3 に答える 3

6

このコードは /dev/urandom (Unix) または CryptGenRandom API (Windows) を使用します。ハードウェアとソフトウェアのどちらの RNG を使用するかは、オペレーティング システムによって異なります。

どのジェネレーターを使用するかを正確に制御したい場合は、そのハードウェア ドライバーまたはライブラリーを介して照会する必要があります。ランダムなビットを文字列として持っている場合は、np.fromstring を使用して、このコードと同様に進みます。

通常、オペレーティング システムは、ランダム ビット ジェネレーターなどの暗号化サービスに最適なエントロピー ソースを使用することを信頼できます。ハードウェア RNG がある場合は、通常は他のエントロピー ソースと組み合わせて使用​​される可能性があります。

import os
import numpy as np

def cryptorand(n):
    a = np.fromstring(os.urandom(n*4), dtype=np.uint32) >> 5
    b = np.fromstring(os.urandom(n*4), dtype=np.uint32) >> 6
    return (a * 67108864.0 + b) / 9007199254740992.0

Mac OS X でこの方法を使用して生成された 1,000,000 個のランダム偏差の分布を次に示します。ご覧のとおり、[0,1) で非常に均一です。

ここに画像の説明を入力

非常に強力な暗号ランダム偏差が必要な場合は、/dev/urandom の代わりに /dev/random を使用できます。これは Unix ライクなシステムにのみ適用され、Windows には適用されません。

import numpy as np

def cryptorand(n):
    with open('/dev/random','rb') as rnd:
        a = np.fromstring(rnd.read(n*4), dtype=np.uint32) >> 5
        b = np.fromstring(rnd.read(n*4), dtype=np.uint32) >> 6
        return (a * 67108864.0 + b) / 9007199254740992.0

エントロピー ソースとして os.urandom を使用するバージョンとは異なり、この関数はブロックされる可能性があることに注意してください。

(Edit1: NumPy と同等になるように正規化を更新)

編集 2: コメントは、質問の理由が速度であり、暗号強度ではないことを示しています。ハードウェア RNG の目的は速度ではなく強度であるため、質問を無効にします。ただし、Mersenne Twister の代替となる高速で優れた PRNG は、George Marsaglia のキャリー付き乗算ジェネレーターです。Cython での簡単な実装を次に示します。

import numpy as np
cimport numpy as cnp

cdef cnp.uint32_t gw = 152315241 # any number except 0 or 0x464fffff
cdef cnp.uint32_t gz = 273283728 # any number except 0 or 0x9068ffff

def rand(cnp.intp_t n):
    """Generate n random numbers using George Marsaglia's 
    multiply-with-carry method."""
    global gw, gz
    cdef cnp.uint32_t w, z, a, b
    cdef cnp.intp_t i
    cdef cnp.ndarray x = cnp.PyArray_SimpleNew(1, &n, cnp.NPY_FLOAT64)
    cdef cnp.float64_t *r = <cnp.float64_t*> cnp.PyArray_DATA(x)
    w,z = gw,gz
    for i in range(n): 
        z = 36969 * (z & 65535) + (z >> 16)
        w = 18000 * (w & 65535) + (w >> 16)
        a = (z << 16) + w
        z = 36969 * (z & 65535) + (z >> 16)
        w = 18000 * (w & 65535) + (w >> 16)
        b = (z << 16) + w
        r[i] = (a * 67108864.0 + b) / 9007199254740992.0
    gw,gz = w,z
    return x

メルセンヌ ツイスターもキャリー付き乗算も暗号強度を持たないことに注意してください。

于 2014-03-27T12:44:04.543 に答える
2

はい。 rdrand モジュールがあります。

于 2015-12-28T10:36:21.547 に答える