直接从数组中读取时的超出地址

时间:2013-04-08 23:43:14

标签: c++ memory memory-management cuda

我正在开发一个CUDA应用程序,它有一些用于在共享内存中分配和释放数组的例程。

在这个应用程序中(我很抱歉,我无法提供),我有一个类将一块内存封装为一个数组。此类有一个count方法,用于计算与特定值匹配的元素数。

所以,想象一下(这是整个班级的实际部分)

template <class Type>
struct Array {
    // ...

    Type &operator[](int i) { return data_[i]; }
    Type operator[](int i) const { return data_[i]; }

    size_t count(const Type &val) const {
        size_t c = 0;
        for (size_t i = 0; i < len_; ++i)
            if (data_[i] == val)
                ++c;
        return c;
    }

    void print(const char *fmt, const char *sep, const char *end) const {
        for (size_t i = 0; i < len_ - 1; ++i) {
            printf(fmt, data_[i]);
            printf(sep);
        }
        printf(fmt, _data[len_ - 1]);
        printf(end);
    }
private:
    Type *data_;
    size_t len_;
};

假设我正在访问的内存被正确分配(在运行时分配的共享内存,将维度传递给内核),这足以包含数据并且data_指向一个对齐的(wrt {{ 1}})region inside 共享内存。我多次检查过这些假设,这些假设是有效的(但可以随意询问更多检查)。

现在,在测试代码时,我发现了一些非常奇怪的东西:

  • 使用Type明确分配值并使用operator[]阅读时,不会出现任何问题。
  • 使用operator[] const阅读数据时,不会出现任何问题。
  • 调用print时,程序崩溃并由count()(x = sizeof(Type))引起cuda-memcheck报告Address ADDR is out of bounds。 ADDR位于共享内存缓冲区内,因此它应该有效。
  • 如果在Invalid __global__ read of size x内,我将count替换为data_[i],程序运行正常,不会发生崩溃。

现在,我完全不知道这可能会发生,而且我不知道要检查什么以查看幕后发生的事情......为什么直接读取崩溃?为什么不使用(*this)[i]?为什么在operator[]内阅读(直接?)不会崩溃?

我知道这个问题很难,我很抱歉提供关于代码的这些小信息...但是随时可以询问详细信息,我会尽可能多地回答。任何想法或建议都是受欢迎的,因为这是我试图解决的日子,这是我能得到的。

我正在使用两个不同的GPU来测试这个代码,一个具有2.1的功能,另一个具有3.5的功能(后者提供了有关此崩溃的详细信息,而第一个没有)。 CUDA 5.0

编辑:我找到了一个发生此错误的最小示例。奇怪的是,在使用sm_20和sm_35进行编译时会出现错误,但不会出现在sm_30上。我使用的GPU有上限3.5

print
编辑:使用CUDA 4.2测试,问题仍然存在。

2 个答案:

答案 0 :(得分:1)

我能够通过以下方式重现您的问题:

RHEL 5.5,驱动程序304.54,CUDA 5.0,Quadro 5000 GPU。

我无法通过以下方式重现该问题:

RHEL 5.5,驱动程序319.72,CUDA 5.5,Quadro 5000 GPU。

请将您的CUDA安装更新至CUDA 5.5,将您的驱动程序更新至319.72或更新版本。

答案 1 :(得分:0)

在您尝试查明崩溃时,最好在X.fill(0);调用中将隐式转换从0移除到0.0。它是有效的C ++,但是CUDA可能会在函数调用运算符中分配临时值。事实上,略读他们的文档我无法找到关于这些临时工作分配的答案 - 全球?设备? 可能这不是问题,但是......确定。