如何在pyCUDA内核中生成随机数?

如何在pyCUDA内核中生成随机数?,cuda,pycuda,Cuda,Pycuda,我正在使用pyCUDA进行CUDA编程。我需要在核函数中使用随机数。库兰图书馆在里面不工作(pyCUDA)。因为GPU有很多工作要做,在CPU内部生成随机数,然后将其传输到GPU将不起作用,而是消除了使用GPU的动机 补充问题: 是否有一种方法可以使用1个块和1个线程在GPU上分配内存 我使用的内核不止一个。我是否需要使用多个SourceModule块 不管你在问题中怎么说,PyCUDA对CUrand有相当全面的支持。GPUArray模块有一个直接接口,可以使用主机端API填充设备内存(注意,在

我正在使用pyCUDA进行CUDA编程。我需要在核函数中使用随机数。库兰图书馆在里面不工作(pyCUDA)。因为GPU有很多工作要做,在CPU内部生成随机数,然后将其传输到GPU将不起作用,而是消除了使用GPU的动机

补充问题:

  • 是否有一种方法可以使用1个块和1个线程在GPU上分配内存
  • 我使用的内核不止一个。我是否需要使用多个SourceModule块

  • 不管你在问题中怎么说,PyCUDA对CUrand有相当全面的支持。GPUArray模块有一个直接接口,可以使用主机端API填充设备内存(注意,在这种情况下,随机生成器在GPU上运行)

    在PyCUDA内核代码中使用CUrand的设备端API也是完全可能的。在这个用例中,最棘手的部分是为线程生成器状态分配内存。有三种选择——静态地在代码中,动态地使用主机内存端分配,以及动态地使用设备端内存分配。下面的示例(测试非常简单)说明了后一种情况,正如您在问题中所问的:

    import numpy as np
    import pycuda.autoinit
    from pycuda.compiler import SourceModule
    from pycuda import gpuarray
    
    code = """
        #include <curand_kernel.h>
    
        const int nstates = %(NGENERATORS)s;
        __device__ curandState_t* states[nstates];
    
        __global__ void initkernel(int seed)
        {
            int tidx = threadIdx.x + blockIdx.x * blockDim.x;
    
            if (tidx < nstates) {
                curandState_t* s = new curandState_t;
                if (s != 0) {
                    curand_init(seed, tidx, 0, s);
                }
    
                states[tidx] = s;
            }
        }
    
        __global__ void randfillkernel(float *values, int N)
        {
            int tidx = threadIdx.x + blockIdx.x * blockDim.x;
    
            if (tidx < nstates) {
                curandState_t s = *states[tidx];
                for(int i=tidx; i < N; i += blockDim.x * gridDim.x) {
                    values[i] = curand_uniform(&s);
                }
                *states[tidx] = s;
            }
        }
    """
    
    N = 1024
    mod = SourceModule(code % { "NGENERATORS" : N }, no_extern_c=True, arch="sm_52")
    init_func = mod.get_function("_Z10initkerneli")
    fill_func = mod.get_function("_Z14randfillkernelPfi")
    
    seed = np.int32(123456789)
    nvalues = 10 * N
    init_func(seed, block=(N,1,1), grid=(1,1,1))
    gdata = gpuarray.zeros(nvalues, dtype=np.float32)
    fill_func(gdata, np.int32(nvalues), block=(N,1,1), grid=(1,1,1))
    
    将numpy导入为np
    导入pycuda.autoinit
    从pycuda.compiler导入SourceModule
    从pycuda导入gpuarray
    代码=”“
    #包括
    const int nstates=%(n发电机)s;
    __设备管理状态[状态];
    __全局无效初始化内核(int种子)
    {
    int tidx=threadIdx.x+blockIdx.x*blockDim.x;
    如果(tidx

    这里有一个需要运行一次的初始化内核,为生成器状态分配内存并使用种子对其进行初始化,然后是一个使用这些状态的内核。如果要运行大量线程,则需要注意malloc堆大小限制,但这些限制可以通过PyCUDA驱动程序API接口进行操作。

    我对公认的答案有一个问题。 我们有一个名字弄乱了,有点讨厌(这些
    \u Z10initkerneli
    \u Z14randfillkernelPfi
    )。 为了避免这种情况,我们可以手动将代码包装在
    extern“C”{…}
    子句中

    code = """
        #include <curand_kernel.h>
    
        const int nstates = %(NGENERATORS)s;
        __device__ curandState_t* states[nstates];
        extern "C" {
    
        __global__ void initkernel(int seed)
        { .... }
    
        __global__ void randfillkernel(float *values, int N)
        { .... }
        }
    """
    
    这应该与

    init_func = mod.get_function("initkernel")
    fill_func = mod.get_function("randfillkernel")
    

    希望能有帮助。

    我不明白这个问题。PyCUDA有一个curand接口,可以直接用随机值填充设备内存。而且设备端代码可以在内核中使用,我知道。您所说的界面是CUDA中包含的别名。但我需要的随机数只能在存在与#include对应的东西时生成。我没有得到你的第二部分,“设备端代码可以在内核中使用,只需一点努力。”你是说主机吗?不,我说的是设备端接口,你能告诉我你是如何在内核中生成随机数的吗?我在运行LogicError时遇到这个错误:cuModuleLoadDataEx失败:设备内核映像无效-@BhaskarDhariyal:显然你需要在
    SourceModule
    实例中设置构建架构以匹配你的GPU模型。包含我需要的随机数的值数组;用于变量r1,r2,它是语句
    velocity[i]=X*(velocity[i]+c1*r1*(pBestPos[i]-X[i])+c2*r2*(lBestIdx[i%d]-X[i])
    的一部分。根据上面的程序,我不能直接访问它,因为给定的语句位于不同的内核中。如何访问语句内核中的值数组?也许您误解了它的工作原理。你应该问一个问题。当这个问题得到回答时,继续前进。此特定问题/答案不是您自己的个人聊天室或服务台。你关于随机数的问题得到了回答。你现在问的是一个完全不同的问题。有新问题吗?问一个新问题。名字
    \u Z10initkerneli
    \u Z14randfillkernelPfi
    是怎么回事。你是从哪里弄来的,为什么它们和原来的名字不匹配?
    init_func = mod.get_function("initkernel")
    fill_func = mod.get_function("randfillkernel")