2017-09-12 138 views
-1

所以我想模擬一個名爲Tasep的一維物理模型。蒙特卡羅與費率,系統模擬與CUDA C++

我寫了一個代碼來模擬C++中的這個系統,但我絕對需要提升性能。

該模型非常簡單(下面的C++代碼) - 10的數組。 1代表顆粒並且0是無顆粒,意思是空的。一個粒子向右移動一個元素,速度爲1,如果該元素爲空。最後一個位置的粒子將以beta(比如0.3)的速度消失。最後,如果第一個位置是空的,則粒子將出現在那裏,速率爲alpha

一個線程很容易,我只是隨機選取一個元素,並按照上面所述的概率1/alpha/beta進行操作。但是這可能需要很長時間。

於是,我就做類似的事情有許多線程,使用GPU,並提出了很多問題:

  1. 使用GPU和CUDA在所有好主意,這樣的事情?

  2. 我應該有多少個線程?我可以爲每個網站有一個線程(10E+6),我應該嗎?

  3. 如何同步不同線程之間的內存訪問?到目前爲止我使用了原子操作。

  4. 生成隨機數據的正確方法是什麼?如果我使用一百萬個線程,可以爲每個線程分配一個隨機生成器嗎?

  5. 我該如何照顧利率?

我對CUDA很新。我設法從CUDA示例和一些教程運行代碼。雖然我有一些上面的代碼(雖然仍然給出了奇怪的結果),但我不把它放在這裏,因爲我認爲這些問題更一般。

因此,這裏是C++它的一個線程版本:

int Tasep() 
{ 
    const int L = 750000; 

    // rates 
    int alpha = 330; 
    int beta = 300; 
    int ProbabilityNormalizer = 1000; 

    bool system[L]; 
    int pos = 0; 
    InitArray(system); // init to 0's and 1's 

    /* Loop */ 
    for (int j = 0; j < 10*L*L; j++) 
    { 
     unsigned long randomNumber = xorshf96(); 
     pos = (randomNumber % (L)); // Pick Random location in the the array 

     if (pos == 0 && system[0] == 0) // First site and empty 
      system[0] = (alpha > (xorshf96() % ProbabilityNormalizer)); // Insert a particle with chance alpha 

     else if (pos == L - 1) // last site 
      system[L - 1] = system[L - 1] && (beta < (xorshf96() % ProbabilityNormalizer)); // Remove a particle if exists with chance beta 

     else if (system[pos] && !system[pos + 1]) // If current location have a particle and the next one is empty - Jump right 
     { 
      system[pos] = false; 
      system[pos + 1] = true; 
     } 
     if ((j % 1000) == 0) // Just do some Loggingg 
      Log(system, j); 
    } 

    getchar(); 
    return 0; 
} 

我會是誰願意幫助非常感激,給他/她的意見。

回答

-1

我認爲你的目標是執行一個叫蒙特卡羅模擬的東西。 但我沒能完全理解你的主要目標(即獲得一個頻率,或丟失平均功率等)

問題01

既然你問到的隨機數據,我相信你可以有多個隨機種子(可能每個線程都有一個),我建議你使用任意僞隨機生成器在GPU中生成種子(甚至可以像CPU一樣使用),將種子存儲在GPU全局內存中並啓動儘可能多的線程你可以使用動態並行。 因此,是的,CUDA是一種合適的方法,但請牢記您需要學習的時間與需要從當前代碼獲取結果所需的時間之間的平衡。 如果您將來會使用這些知識,學習CUDA也許值得,或者如果您可以在許多GPU中升級您的代碼,並且CPU佔用太多時間,並且您經常需要解決這個等式也是值得的。看起來你很接近,但如果這是一個簡單的一次結果,我建議你讓CPU解決它,因爲可能從我的經驗來看,你需要花更多時間學習CUDA,而不是CPU來解決它(恕我直言)。

問題02

線程的數量是非常新秀平常的問題。答案是非常依賴於你的項目,但是把你的代碼作爲一個洞察力,我會盡可能多地使用每個不同種子的線程。 我的建議是使用寄存器就是你所說的「站點」(注意是有很強的侷限性),然後運行多個循環來評估你的粒子,這與汽車輪胎的道路相同(SMEM中的數據)所以你的L被限制在每個循環255次(避免你的項目花費溢出,而更少的寄存器意味着每塊更多的warps)。爲了創建擾動,我會在共享內存中加載矢量,一個用於alpha(短),一個用於beta(短)(我假設不同的分佈),下一個站點(char)中有一個「存在或不存在粒子」,以及另外兩個作爲僞發生器源與threadID,blockID和一些當前時間信息(以幫助您選擇最初的alpha,beta和存在或不存在),所以你可以重複使用這個速率爲塊中的每個線程,並且由於數據不會改變(只有讀取位置發生變化),讀取後只能同步一次,也可以「隨機選取攝動位置並重新使用數據。初始值可以從全局內存中加載,並在特定簡而言之,您將多次共享相同的數據,但由於僞隨機值,每個線程所選的值會在每次交互中發生變化。考慮到您所談論的是大量數字,你可以加載不同的數據每個塊,僞隨機算法應該足夠好。此外,你甚至可以使用存儲在前一次運行的GPU中的結果作爲隨機源,翻轉一個變量並執行一些操作,這樣你就可以將每一位用作粒子。

問題03

對於特定的項目,我會強烈建議,以避免線程合作,使這些完全獨立的。但是,你可以在同一個warp內使用shuffle,而且不需要很高的成本。

問題04

這是很難產生真正的隨機數據,但是你應該多長時間持續的時期擔心(因爲任何產生的週期是隨機的,他們重複)。我建議你使用一個單獨的發生器,它可以與你的內核並行工作,並用它來提供你的內核(你可以使用動態並行)。在你的情況下,因爲你需要一些隨機的,你不應該擔心一致性。我在前面的問題中給出了一個僞隨機數據使用的例子,這可能會有所幫助。請記住,不存在真正的隨機生成器,但也可以選擇互聯網位作爲例子。

問題05

早在問題03所解釋的,但請你記住,你不需要值的完整序列,只有足夠的一部分,採取多種形式使用,給予足夠的時間來你的內核只是處理,然後你可以刷新你的順序,如果你保證不以相同的順序進入塊,它將很難陷入模式。

希望我有幫助,我正在與CUDA合作一年多,開始就像你一樣,而且每個星期我都會改進我的代碼,現在已經足夠好了。現在我看到它完全適合我的統計挑戰:隨機聚類。

祝你好運!