Tuesday, 31 August 2021

Why do I get an illegal memory access when I'm calling a kernel in pycuda?

I'm trying to implement a neuron model with Hodgkin and Huxley formalism on my RTX 2080 Ti with PyCuda. The code is quite large so I wont put all of it here. the first part of my class is to set the number of neurons, create all variables in the GPU and get the block and grid size according on the number of neurons (1 neuron by thread)

class Inter_PC:
    def __init__(self, ):

        self.NbODEs = 25
        self.NbCells = int(1024 * 1)
        self.init_vector()
        self.init_vector_param()
        self.Create_GPU_SourceModule()

        BLOCK_SIZE = 1024
        self.grid = (int(self.NbCells / BLOCK_SIZE), 1)
        self.block = (BLOCK_SIZE, 1, 1)

In the function init_vector and init_vector_param, I put vectors to compute ODE results in the GPU

def init_vector(self):
    self.Vs_PC_dydx1 = self.put_vect_on_GPU(np.zeros((self.NbCells), dtype=np.float32))
    self.Vs_PC_dydx2 = self.put_vect_on_GPU(np.zeros((self.NbCells), dtype=np.float32))
    self.Vs_PC_dydx3 = self.put_vect_on_GPU(np.zeros((self.NbCells), dtype=np.float32))
    self.Vs_PC_dydx4 = self.put_vect_on_GPU(np.zeros((self.NbCells), dtype=np.float32))
    self.Vs_PC_y = self.put_vect_on_GPU(np.zeros((self.NbCells), dtype=np.float32))
    self.Vs_PC_yt = self.put_vect_on_GPU(np.zeros((self.NbCells), dtype=np.float32))
    ...
def init_vector_param(self):
    self.E_leak = self.put_vect_on_GPU(np.ones((self.NbCells), dtype=np.float32) * -65)
    self.E_Na = self.put_vect_on_GPU(np.ones((self.NbCells), dtype=np.float32) * 55)
    ...
def put_vect_on_GPU(self, Variable):
    Variable_gpu = cuda.mem_alloc(Variable.nbytes)
    cuda.memcpy_htod(Variable_gpu, Variable)
    return Variable_gpu

In the function Create_GPU_SourceModule, I create kernels to use on the GPU.

def Create_GPU_SourceModule(self):
    self.mod = SourceModule("""
    #include <math.h>
      __global__ void m_inf_PC(float *V_PC, float *res)
      {
        int idx = threadIdx.x + blockDim.x * blockIdx.x; 
        res[idx] = 1.0 / ( 1. * exp(-(V_PC[idx] + 40.) / 3.));
      }
      __global__ void h_inf_PC(float *V_PC, float *res)
      {
        int idx = threadIdx.x + blockDim.x * blockIdx.x; 
        res[idx] = 1.0 / ( 1. * exp((V_PC[idx] + 45.) / 3.)); 
      }
      ...

I have the a function to update all my variables in a RK4 solver updateParameters

def setParameters(self):
    func = self.mod.get_function("set_vect_val")
    func(self.Vs_PC_y, self.E_leak, block=self.block, grid=self.grid)
    func = self.mod.get_function("set_vect_val")
    func(self.Vd_PC_y, self.E_leak, block=self.block, grid=self.grid)
    func = self.mod.get_function("h_inf_PC")
    func(self.Vs_PC_y, self.h_s_PC_y, block=self.block, grid=self.grid)
    func = self.mod.get_function("m_KDR_inf_PC")
    func(self.Vs_PC_y, self.m_KDR_s_PC_y, block=self.block, grid=self.grid)
    func = self.mod.get_function("m_m_inf_PC")
    func(self.Vs_PC_y, self.m_s_PC_y, block=self.block, grid=self.grid)
    func = self.mod.get_function("m_m_inf_PC")
    func(self.Vd_PC_y, self.m_d_PC_y, block=self.block, grid=self.grid)
    func = self.mod.get_function("h_inf_PC")
    func(self.Vd_PC_y, self.h_d_PC_y, block=self.block, grid=self.grid)

When I run the code I get this error:

Traceback (most recent call last):
 File "C:/Users/maxime/Desktop/SESAME/PycharmProjects/Modele_Micro3/Class_PyrCell_GPU.py", line 1668, in <module>
    Vm = PC.rk4_Time(30000)
 File "C:/Users/maxime/Desktop/SESAME/PycharmProjects/Modele_Micro3/Class_PyrCell_GPU.py", line 1637, in rk4_Time
    self.updateParameters()
  File "C:/Users/maxime/Desktop/SESAME/PycharmProjects/Modele_Micro3/Class_PyrCell_GPU.py", line 998, in updateParameters
    func = self.mod.get_function("h_inf_PC")
  File "C:\Python389\lib\site-packages\pycuda\compiler.py", line 326, in get_function
    return self.module.get_function(name)
pycuda._driver.LogicError: cuModuleGetFunction failed: an illegal memory access was encountered
PyCUDA WARNING: a clean-up operation failed (dead context maybe?)
cuMemFree failed: an illegal memory access was encountered

What I'm not understanding is that the error does not occur the first time I use the kernel h_inf_PC, it happens on the 13th line of the function setParameters but I already calling the same kernel in line 5 of the same function. If I comment out the calling to the kernel (h_inf_PC) that causes the issue, the error switched on another calling to a kernel but not necessarily the next one.



from Why do I get an illegal memory access when I'm calling a kernel in pycuda?

No comments:

Post a Comment