【问题标题】:PyCUDA LogicError: cuModuleLoadDataEx failed: an illegal memory access was encounteredPyCUDA LogicError:cuModuleLoadDataEx 失败:遇到非法内存访问
【发布时间】:2021-03-07 16:46:12
【问题描述】:

我正在尝试使用 pycuda 并行化双音排序。为此,我使用 SourceModule 和并行双音排序的 C 代码。对于内存副本管理,我使用 pycuda.driver 的 InOut 来简化一些内存传输

import pycuda.autoinit
import pycuda.driver as drv
from pycuda.compiler import SourceModule
from pycuda import gpuarray
import numpy as np
from time import time

ker = SourceModule(
    """
    __device__ void swap(int & a, int & b){
        int tmp = a;
        a = b;
        b = tmp;
    }

    __global__ void bitonicSort(int * values, int N){
        extern __shared__ int shared[];
        int tid = threadIdx.x + blockDim.x * blockIdx.x;
        // Copy input to shared mem.
        shared[tid] = values[tid];
        __syncthreads();
        // Parallel bitonic sort.
        for (int k = 2; k <= N; k *= 2){
            // Bitonic merge:
            for (int j = k / 2; j>0; j /= 2){
                int ixj = tid ^ j;
                if (ixj > tid){
                    if ((tid & k) == 0){
                        //Sort ascending
                        if (shared[tid] > shared[ixj]){
                            swap(shared[tid], shared[ixj]);
                        }
                    }
                    else{
                        //Sort descending
                        if (shared[tid] < shared[ixj]){
                            swap(shared[tid], shared[ixj]);
                        }
                    }
                }
                __syncthreads();
            }
        }
        values[tid] = shared[tid];
    }
    """
)

N = 8 #lenght of A
A = np.int32(np.random.randint(1, 20, N)) #random numbers in A
BLOCK_SIZE = 256
NUM_BLOCKS = (N + BLOCK_SIZE-1)//BLOCK_SIZE
bitonicSort = ker.get_function("bitonicSort")
t1 = time()
bitonicSort(drv.InOut(A), np.int32(N), block=(BLOCK_SIZE,1,1), grid=(NUM_BLOCKS,1), shared=4*N)
t2 = time()
print("Execution Time {0}".format(t2 - t1))
print(A)

在内核中我使用extern __shared__,在pycuda 中我使用带有相应4*N 的共享参数。也可以尝试在内核中使用__shared__ int shared[N],但它也不起作用(在这里查看:Getting started with shared memory on PyCUDA

在 Google Collab 中运行我收到以下错误:

/usr/local/lib/python3.6/dist-packages/pycuda/compiler.py in __init__(self, source, nvcc, options, keep, no_extern_c, arch, code, cache_dir, include_dirs)
    292 
    293         from pycuda.driver import module_from_buffer
--> 294         self.module = module_from_buffer(cubin)
    295 
    296         self._bind_module()

LogicError: cuModuleLoadDataEx failed: an illegal memory access was encountered

有谁知道是什么导致了这个错误?

【问题讨论】:

    标签: python cuda pycuda


    【解决方案1】:

    您的设备代码未正确考虑数组的大小。

    您将在一个块中启动 256 个线程。这意味着您将有 256 个线程,tid 编号为 0..255,试图执行每一行代码。例如,在这种情况下:

    shared[tid] = values[tid]; 
    

    例如,您将有一个线程尝试执行shared[255] = values[255];

    您的sharedvalues 数组都没有那么大。这就是非法内存访问错误的原因。

    这类琐碎问题的最简单解决方案是让您的数组大小与您的块大小相匹配。

    BLOCK_SIZE = N
    

    根据我的测试,该更改会清除所有错误并生成正确排序的数组。

    它不适用于大于 1024 的 N 或多块使用,但无论如何您的代码都必须修改为多块排序。

    如果您在进行更改后仍然遇到问题,我建议您重新启动您的 python 会话或 colab 会话。

    【讨论】:

    • 虽然您的观察是正确的,但我认为这实际上不是运行时代码问题,而是运行时构建问题。通常,编译器基础设施内部的这种爆炸意味着 PyCUDA 和主机工具包之间存在损坏的工具链/不兼容
    • 你可能是对的。我无法推测在模块加载时会发生该错误的原因,因此我推测它是之前运行的遗留问题,并且由于 python 的某些交互使用而没有被清除。这就是为什么我在回答中做出最后评论的原因。我不知道为什么这个错误会在模块加载时发生,重新运行(似乎不可能)。通过我建议的更改,我至少可以断言它对我来说是正确运行的,所以如果问题仍然存在,我不相信它们与代码有关。
    • 这解决了我的问题,非常感谢。我必须修改代码以使用多块排序,有什么提示吗?
    • 要在 GPU 上对数字进行排序,我会使用库实现。如果您想自己编写代码(不推荐),有一个CUDA sample code 可以进行多块双调排序。
    猜你喜欢
    • 1970-01-01
    • 2019-11-05
    • 2021-11-22
    • 2020-12-27
    • 2021-03-25
    • 2015-05-02
    • 2022-01-18
    • 2015-07-23
    • 2021-08-12
    相关资源
    最近更新 更多