MKL/VSL,vRngGaussian:生成高斯分佈隨機數
以產生Gauss分佈隨機數為例,需要的步驟有:
1. 定義type(vsl_stream_state) :: stream。
按照手冊,stream的定義為“Random stream (or stream) is an abstract source of pseudo- and quasi-random sequences of uniform distribution. Users have no direct access to these sequences and operate with stream state descriptors only. A stream state descriptor, which holds state descriptive information for particular BRNG, is a necessary parameter in each routine of a distribution generator. Only the distribution generator routines operate with random streams directly. ”按照字面理解,是一種“流”,隨機數“流”,uniform分佈的隨機數流,VSL裡所有分佈的隨機數都是根據uniform分佈隨機數通過變換產生的,相當於這個“流”是產生隨機數的基礎。不過這裡的stream並不是完整地記錄下整個流(否則會非常大),只是記錄下描述資訊,根據這個描述資訊就能完整的推斷出這個隨機數流(畢竟計算機裡都是偽隨機,不是真隨機嘛)。(p.s. 不懂pseudo- & quasi- random number的區別,不過貌似準隨機數要比偽隨機數在對分佈滿足的性質上更好一點)
產生stream(即給stream賦值)
status=vslNewStream( stream, brng, seed)
brng 是整數型,定義BRNG(Basic Random Number Generator)的方法,即產生初始uniform 隨機數的方法,包括有偽隨機數 和 準隨機數 的不同生成方法。其取值詳見手冊:10. Statistical Functions -> Random Number Generators -> Basic Generators -> BRNG Parameter Definition
Seed ,整數型,提供的種子,相當於指定這個stream的初始值。Stream方法不變,Seed也不變,則每次呼叫生成的隨機數流都是確定的。可以通過獲取系統時間獲取這個seed:call system_clock(count=seed)利用確定的stream,通過變換,產生所需要的高斯分佈隨機數
status = vsrnggaussian( method, stream, n, r, a, sigma )
如 status = vsrnggaussian( VSL_METHOD_SGAUSSIAN_BOXMULLER2, stream, 2000, r, 2.0, 1.0)
method為變換的方法,n為個數, r為接收隨機數的陣列, a為均值, sigma為標準差
前四項(method, stream, n, r)為所有分佈的RNG函式都有的引數,後面2個引數是高斯分佈所特有的。
VSL的函式名也有規範,v代表vsl, s代表single(同理,d代表double, i 代表integer,即返回隨機數的型別;s\d對應的是連續分佈隨機數:如高斯分佈,i對應的是離散分佈隨機數:如二次分佈), 後面跟rng,再跟分佈名稱,即 vrngstatus = vsldeletestream( stream ): 刪除stream,雖然我自己用這個函式老是報錯。。
===========================
給出一個test(注意,utility, vsl_external, inc_common.h 為我個人的程式,有些有些函式、巨集為自定義,這裡程式僅作示範)
Fortran語言: 高亮程式碼由發芽網提供
program vsl_test_gauss
use utility
use mkl_vsl_type
use mkl_vsl
use vsl_external
implicit none
character(len=*), parameter :: PROCEDURE_NAME=”vsl_test_gauss”
integer,parameter :: n=2000
real :: r(n)
type(vsl_stream_state) :: stream
integer :: seed, i
integer :: brng=VSL_BRNG_MCG31
integer :: method=VSL_METHOD_SGAUSSIAN_BOXMULLER2
real :: a = 5.0, sigma = 2.0
call system_clock(count = seed)
print*,seed
VSL_CHECK(vslnewstream(stream, brng, seed))
VSL_CHECK(vsrnggaussian( method, stream, n, r, a, sigma ))
print*, get_average(r)
print*, sqrt(get_cov(r,r))
open(11,file=”gauss_random.txt”)
do i=1, n
write(11, *) r(i)
end do
close(11)
end program vsl_test_gauss