2014-10-11 70 views
0

所以我想利用這個自定義RNG庫針對OpenCL: http://cas.ee.ic.ac.uk/people/dt10/research/rngs-gpu-mwc64x.html最佳方式

庫定義的狀態結構:

//! Represents the state of a particular generator 
typedef struct{ uint x; uint c; } mwc64x_state_t; 

而且爲了產生一個隨機UINT,你的狀態傳遞到下面的函數:

uint MWC64X_NextUint(mwc64x_state_t *s) 

其更新狀態,所以,當你經過我t再次進入函數,序列中的下一個「隨機」數字將被生成。

爲我創造,我需要能夠同時生成隨機數不只是在不同的工作組/項目,但還可以在多個設備,我有麻煩找出最好的方式來設計這個項目。就像我應該創建每個設備/ commandqueue 1 mwc64x_state_t對象並將該狀態作爲全局變量傳遞?或者是否有可能一次爲所有設備創建1個狀態對象? 還是我甚至在把它作爲一個全局變量,每個內核函數內局部聲明一個新的狀態?

圖書館還配備了這一功能:

void MWC64X_SeedStreams(mwc64x_state_t *s, ulong baseOffset, ulong perStreamOffset) 

據稱是應該的RNG分成多個「流」,但包括這在我的內核使得難以置信緩慢。舉例來說,如果我這樣做了以下非常簡單:

__kernel void myKernel() 
{ 
    mwc64x_state_t rng; 
    MWC64X_SeedStreams(&rng, 0, 10000); 
} 

然後內核調用變成40倍左右慢。

庫不來與作爲示例用法,但是示例代碼是一種有限的,似乎沒有是有幫助的一些源代碼。

所以如果有人熟悉OpenCL中的隨機數發生器,或者如果你已經使用了這種特殊的圖書館我以前很欣賞你的建議。

回答

3

的MWC64X_SeedStreams功能確實比較慢,至少在比較 到MWC64X_NextUint呼叫,但這是一個嘗試 一個大的全球流分割成可在 可以使用許多子流大多數並行的RNG的真平行。假設您將在內核中多次調用NextUint (例如,一百或更多),但SeedStreams僅位於頂部。

這是帶有庫(mwc64x/test/estimate_pi.cpp和mwc64x/test/test_mwc64x.cl)的 附帶的EstimatePi示例的註釋版本。

__kernel void EstimatePi(ulong n, ulong baseOffset, __global ulong *acc) 
{ 
    // One RNG state per work-item 
    mwc64x_state_t rng; 

    // This calculates the number of samples that each work-item uses 
    ulong samplesPerStream=n/get_global_size(0); 

    // And then skip each work-item to their part of the stream, which 
    // will from stream offset: 
    // baseOffset+2*samplesPerStream*get_global_id(0) 
    // up to (but not including): 
    // baseOffset+2*samplesPerStream*(get_global_id(0)+1) 
    // 
    MWC64X_SeedStreams(&rng, baseOffset, 2*samplesPerStream); 


    // Now use the numbers 
    uint count=0; 
    for(uint i=0;i<samplesPerStream;i++){ 
     ulong x=MWC64X_NextUint(&rng); 
     ulong y=MWC64X_NextUint(&rng); 
     ulong x2=x*x; 
     ulong y2=y*y; 
     if(x2+y2 >= x2) 
      count++; 
    } 
    acc[get_global_id(0)] = count; 
} 

因此,意圖是,n應是大而成長爲大量的工作項目 生長,從而samplesPerStream仍然圍繞 百人以上。

如果你想在多個設備上的多個內核,那麼你 需要層次的另一個層面增加了流拆分, 因此,例如,如果您有:

  • K:可能是設備數量(上並行機)
  • 寬:編號工作項每個設備
  • C:呼叫數目每工作項到NextUint

ÿ ou最終以N = K W C在所有 工作項目中總共調用NextUint。如果您的設備被確定爲K = 0。(K-1),然後 每個內核中,你會怎麼做:

MWC64X_SeedStreams(&rng, W*C*k, C); 

然後流中的指標是:

[0    .. N) : Parts of stream used across all devices 
[k*(W*C)  .. (k+1)*(W*C)) : Used within device k 
[k*(W*C)+(i*C) .. (k*W*C)+(i+1)*C) : Used by work-item i in device k. 

它如果每個內核使用的C採樣少於C個,那麼可以在必要時過度估計 。

(我是圖書館的作者)。

+0

感謝您的信息和澄清!不幸的是,我的內核工作項目只需要對NextUint()進行大約12次左右的調用,所以它看起來不像彌補調用SeedStreams()的大量開銷。 – user1855952 2014-10-14 20:52:43