蒙特卡罗速率法,CUDA C+系统模拟+;

蒙特卡罗速率法,CUDA C+系统模拟+;,cuda,gpgpu,gpu,Cuda,Gpgpu,Gpu,所以我尝试模拟一个名为Tasep的一维物理模型 我编写了一个代码来模拟这个系统在C++中,但是我确实需要一个性能提升。 模型非常简单(下面的C++代码)-一个代码< > 1 < /COD>和 0 < /COD>的数组。strong>1表示粒子,而0不是粒子,表示为空。如果元素为空,粒子将以1的速率向右移动一个元素。最后一个位置的粒子将以beta(比如0.3)的速率消失。最后,如果第一个位置为空,则粒子将以alpha的速率出现在那里 一个线程很容易,我只是随机选择一个元素,并以概率1/alpha/

所以我尝试模拟一个名为Tasep的一维物理模型

我编写了一个代码来模拟这个系统在C++中,但是我确实需要一个性能提升。

模型非常简单(下面的C++代码)-一个代码< > 1 < /COD>和<代码> 0 < /COD>的数组。strong>

1
表示粒子,而
0
不是粒子,表示为空。如果元素为空,粒子将以
1
的速率向右移动一个元素。最后一个位置的粒子将以
beta
(比如0.3)的速率消失。最后,如果第一个位置为空,则粒子将以
alpha
的速率出现在那里

一个线程很容易,我只是随机选择一个元素,并以概率
1/alpha/beta
行事,如上所述。但这可能需要很多时间

因此,我尝试使用GPU对许多线程执行类似的操作,这引发了很多问题:

  • 使用GPU和CUDA是一个好主意吗

  • 我应该有多少线?我可以为每个站点设置一个线程(
    10E+6
    ),应该吗

  • 如何在不同线程之间同步对内存的访问?到目前为止,我使用了原子操作

  • 生成随机数据的正确方法是什么?如果我使用一百万个线程,每个线程都有一个随机生成器可以吗

  • 我如何处理费率

  • 我是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;
    }
    
    inttasep()
    {
    常数int L=750000;
    //费率
    intα=330;
    intβ=300;
    int-ProbabilityNormalizer=1000;
    布尔系统[L];
    int pos=0;
    初始化数组(系统);//初始化到0和1
    /*环路*/
    对于(int j=0;j<10*L*L;j++)
    {
    无符号长随机数=xorshf96();
    pos=(randomNumber%(L));//在数组中随机选取位置
    if(pos==0&&system[0]==0)//第一个站点为空
    系统[0]=(alpha>(xorshf96()%ProbabilityNormalizer));//插入一个具有alpha概率的粒子
    else如果(pos==L-1)//最后一个站点
    系统[L-1]=系统[L-1]&&(β<(xorshf96()%ProbabilityNormalizer));//如果存在概率β,则移除粒子
    else if(system[pos]&&!system[pos+1])//如果当前位置有一个粒子,而下一个粒子为空,则向右跳
    {
    系统[pos]=错误;
    系统[pos+1]=真;
    }
    如果((j%1000)==0)//只需做一些记录
    日志(系统,j);
    }
    getchar();
    返回0;
    }
    

    如果有人愿意提供帮助和建议,我将不胜感激。

    我认为您的目标是进行蒙特卡罗模拟。 但我未能完全理解您的主要目标(即获得频率或平均功率损失等)

    问题01

    由于您询问了随机数据,我相信您可以有多个随机种子(每个线程可能有一个),我建议您使用任何伪随机生成器在GPU中生成种子(您甚至可以使用与CPU相同的生成器),将种子存储在GPU全局内存中,并使用动态并行启动尽可能多的线程。 因此,是的,CUDA是一种合适的方法,但请记住学习所需的时间与从当前代码中获得结果所需的时间之间的平衡。 如果您将来要使用这些知识,学习CUDA可能是值得的,或者如果您可以在许多GPU中升级您的代码,并且它在CPU中占用了太多的时间,那么您将需要经常解决这个等式,这也是值得的。看起来你很接近,但如果这是一个简单的一次性结果,我建议你让CPU解决它,因为根据我的经验,你学习CUDA的时间可能比CPU解决它所需的时间要长(IMHO)

    问题02

    对于新手来说,线程的数量是一个非常常见的问题。答案非常依赖于您的项目,但将您的代码作为洞察力,我会尽可能多地使用不同种子的每个线程。 我的建议是使用寄存器,即您所称的“站点”(请注意,这些站点有很强的限制),然后运行多个循环来评估您的粒子,就像汽车轮胎坏了一样(SMEM中的数据),因此您的L限制为每个循环255次(避免溢出,您的项目将为此付出代价,更少的寄存器意味着每个块有更多扭曲)。为了创建扰动,我将在共享内存中加载向量,一个用于alpha(短),一个用于beta(短)(我假设不同的分布),一个“存在或不存在粒子”在下一个站点(char),另外两个作为伪生成器源与threadID、blockID和一些当前时间信息相结合(帮助您选择初始alpha、beta和exist或not),以便您可以对块中的每个线程重复使用此速率,并且由于数据不会更改(仅读取位置更改),因此读取后只需同步一次,也可以随机选取扰动位置并重新使用数据。初始值可以从全局内存加载并“刷新”在特定数量的循环后隐藏加载延迟。简言之,您将在共享中多次重用相同的数据,但由于伪随机值,为每个线程选择的值在每次交互时都会发生变化。考虑到您谈论的是大量数据,并且您可以在每个块中加载不同的数据,伪随机值andom算法应该足够好了。此外,你甚至可以将以前运行的结果作为随机源存储在gpu中