我正在使用C#项目中的ManagedCuda库来利用GPU,目前我正在跟随这个tutorial关于如何在使用OpenCV实现它之后编写C#和C ++之间兼容的代码。
我的代码似乎一切正常,内核被发现,构建并执行方法调用但是我收到错误:
An unhandled exception of type 'ManagedCuda.CudaException' occurred in ManagedCuda.dll
Additional information: ErrorIllegalAddress: While executing a kernel, the device
encountered a load or store instruction on an invalid memory address.
The context cannot be used, so it must be destroyed (and a new one should be created).
我知道C#抱怨在尝试将设备指针传递给内核时找不到有效地址,我在代码和引用教程中的帖子之间可以区分的唯一区别是ManagedCuda似乎最近有一个改版,允许用户使用Lambdas,我已经做了一些阅读,并没有找到任何东西来澄清这是否是导致我的问题:
static Func<int, int, int> cudaAdd = (a, b) =>
{
// init output parameters
CudaDeviceVariable<int> result_dev = 0;
int result_host = 0;
// run CUDA method
addWithCuda.Run(a, b, result_dev.DevicePointer); <--- Code throws error here
// copy return to host
result_dev.CopyToHost(ref result_host);
return result_host;
};
在原始教程代码中,OP使用CudaDeviceVariable result_dev = 0;
。这可能是问题吗?我不明白为什么会这样,但也许我的演员是错的?
为了清楚起见,这里是被调用的内核:
__global__ void kernel(int a, int b, int *c)
{
*c = (a + b)*(a + b);
}
答案 0 :(得分:6)
TL; DR:异常与C#项目中的32/64位设置有关。将平台目标设置为x86,或者如果你在任何CPU上都有它,请确保选择首选32位。
我如何发现:
根据https://algoslaves.wordpress.com/2013/08/25/nvidia-cuda-hello-world-in-managed-c-and-f-with-use-of-managedcuda/在.NET 4.5中提供解决方案(与OP相同) 使用NuGet添加ManagedCuda 6.5 - Standalone
工作正常
备用点A.
将.NET版本更改为4.0,使用NuGet删除并添加ManagedCuda 6.5 - Standalone:
抛出异常:附加信息:ErrorIllegalAddress:执行内核时,设备遇到无效内存地址的加载或存储指令。
将.NET版本切换为4.5,使用NuGet删除并添加ManagedCuda 6.5 - Standalone:
抛出异常:与上述相同。
清洁解决方案,重建解决方案,构建解决方案:
抛出异常:与上述相同。
手动删除Visual Studio生成的每个文件/文件夹:
抛出异常:与上述相同。
重新打开从A点备份的项目:
工作得很好。
在工作和不工作项目中手动删除Visual Studio生成的每个文件/文件夹。
直观地比较所有文件。
每个文件都是相同的,除了:不工作的版本在MangedCudaTest.csproj中有额外的<Prefer32Bit>false</Prefer32Bit>
已删除包含<Prefer32Bit>false</Prefer32Bit>
的行。
不工作版本终于工作得很好。
在我的主项目中进行了相同的更改,最终工作得很好。
答案 1 :(得分:2)
从评论看来,抛出的异常似乎是由于在不同的线程上运行。在单线程环境中,示例代码运行正常,返回正确的结果。为了在多线程应用程序中使用Cuda,必须正确同步线程并将cuda上下文绑定到当前活动的线程。
答案 2 :(得分:0)
我有同样的问题,我的解决方案是将.NET项目设置为64位,而不是像aeroson的回答中建议的32位。我想这可能是因为我使用的是CUDA SDK 7.5而且我读到的某个地方大约有32位被淘汰。