【发布时间】:2013-10-06 20:47:01
【问题描述】:
当我创建一个具有 3 深结构且最深级别具有 2 维数组的结构时,在使用 CUDA 调试器时,在设备上分配内存并访问该数组会导致内存检查器访问冲突错误。这是一个例子:
#include "stdafx.h"
#include <stdio.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <device_launch_parameters.h>
typedef struct {
int value;
} Level3;
typedef struct {
Level3 lvl3ObjArr[10][10];
} Level2;
typedef struct {
Level2 lvl2Obj;
} Level1;
__global__ void AccessViolationKernel(Level1 *_lvl1Ptr)
{
int _value;
_lvl1Ptr->lvl2Obj.lvl3ObjArr[2][5].value = 4;
_value = _lvl1Ptr->lvl2Obj.lvl3ObjArr[2][5].value;
printf("Value = %i\n", _value);
}
int _tmain(int argc, _TCHAR* argv[])
{
Level1 *lvl1Ptr;
cudaMalloc((void **)&lvl1Ptr, sizeof(Level1));
AccessViolationKernel<<<5, 1>>>(lvl1Ptr);
return 0;
}
即使查看内存并添加正确的字节,在使用 CUDA 调试器时,对于 lvl1Ptr 对 lvl3ObjArr[2][5] 的封装引用,一切似乎都正确添加。尽管如此,访问的数据还是不正确的,memchecker 会抛出访问冲突。
Level1 是否在设备上分配不正确?为什么我会遇到访问冲突?
提前致谢!
-- 更新(2013 年 9 月 30 日下午 16:29 CST)--
此代码可以编译(抱歉!)但它没有显示错误。我认为这是因为我使用的是设备 API malloc 而不是 cudaMalloc,并尝试稍后从主机的 CUDA API 访问数据。我需要一段时间来生成代码来重现这个,我很抱歉——我正在减少的源代码是 2800 行长。
【问题讨论】:
-
你能发布可以编译的实际代码吗?
-
只需确认您现在发布的代码似乎有效、运行正确并给出预期的打印输出。
cuda-memcheck没有报告错误。如果您使用的是设备malloc,则无法使用运行时 API 访问以这种方式分配的内存。相反,您首先需要将数据从该区域复制到已经使用例如分配的区域。cudaMalloc,然后将该数据复制到主机。 -
罗伯特,再次感谢您的帮助。我似乎仍然有混合主机 CUDA API 和设备内核 malloc 的潜在问题。奇怪的是,我使用 cudaMalloc 在我的大型代码集中分配了第一级对象,并访问了一个隐藏的 2D 对象数组的值,我得到了一个单一的访问冲突。只有当我访问最深的值时才会发生这种情况,而不是当我访问隐藏结构中引用和取消引用以获取该隐藏值的指针时。当我找到出现相同错误的解决方案或代码的简化版本时,我将重新发布。
-
好的,找到了解决方案。我在内核中将 cudaMalloc 与 malloc/free 混合在一起......当然。这并不直观,因为我使用 cudaMalloc 分配根,然后在使用 malloc 的设备上再次分配它。一些对象仍然从主机分配,因此设备堆在访问期间不知道,并且会引发访问冲突。
-
请提供您的 cmets 作为答案,以便我们将此称为已回答问题。或者删除这个问题 - 它没有任何用途,没有其他人可以回答它,因为您没有提供任何显示错误的代码。谢谢。