2017-09-12 135 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合作一年多,开始就像你一样,而且每个星期我都会改进我的代码,现在已经足够好了。现在我看到它完全适合我的统计挑战:随机聚类。

祝你好运!