C# ManagedCuda:非法地址;在执行内核时 我在C语言项目中使用MauleDeCuDA库来使用GPU,目前我在下面是关于如何在C to +和C++中兼容代码,而不是用OpenCV实现的。

C# ManagedCuda:非法地址;在执行内核时 我在C语言项目中使用MauleDeCuDA库来使用GPU,目前我在下面是关于如何在C to +和C++中兼容代码,而不是用OpenCV实现的。,c#,cuda,C#,Cuda,我的代码似乎一切正常,找到、构建内核并执行方法调用,但我遇到了一个错误: 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 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;
};

从注释来看,抛出的异常似乎是由于运行在不同的线程上。在单线程环境中,示例代码运行良好,返回正确的结果。为了在多线程应用程序中使用Cuda,必须正确同步线程并将Cuda上下文绑定到当前活动的线程。

TL;DR:异常与C#项目中的32/64位设置有关。将平台目标设置为x86,或者如果您在任何CPU上都有平台目标,请确保勾选“首选32位”

我是如何发现的:

根据(与OP相同)在.NET 4.5中生成解决方案 使用NuGet添加ManagedCuda 6.5-独立

很好

备份点A

将.NET版本更改为4.0,使用NuGet删除和添加ManagedCuda 6.5-独立:

引发异常:其他信息:ErrorIllegalAddress:在执行内核时,设备在无效内存地址上遇到加载或存储指令

将.NET版本切换到4.5,使用NuGet删除和添加ManagedCuda 6.5-独立:

抛出异常:同上

清理解决方案、重建解决方案、生成解决方案:

抛出异常:同上

手动删除Visual Studio生成的每个文件/文件夹:

抛出异常:同上

重新打开从点A备份的项目:

很好

手动删除Visual Studio在工作项目和非工作项目中生成的每个文件/文件夹

直观地比较所有文件

每个文件都是相同的,除了:非工作版本在MangedCudaTest.csproj中有额外的
false

删除了带有
false
的行

不工作的版本最终工作正常


在我的主项目中进行了相同的更改,最终工作正常。

我也遇到了同样的问题,解决方案是将.NET项目设置为64位,而不是像aeroson的回答中建议的那样设置为32位。我想这可能是因为我使用的是CUDA SDK 7.5,我在某个地方读到了关于32位被淘汰的消息。

您的示例代码在我的电脑上运行时没有错误,并返回了正确的结果。您能检查一下从正确的文件夹加载了正确的内核文件吗?您使用的网格/块大小是多少?没有定义没有任何“”的CudaDeviceVariable,因此不应编译,因此这不是原因。另外,lambda不会以任何方式影响managedCuda:只要传递给内核的变量a和b是定义良好的int,managedCuda就不关心其余的变量。如果所有这些都没有帮助,试着用NSight调试内核,看看是什么内存访问导致了问题。我想这可能是因为我试图从基于gui的应用程序运行它。相同的代码在控制台应用程序上执行并返回结果。基于GUI的应用程序可能运行在不同的线程中,Cuda上下文总是绑定到一个线程。尽管managedCuda实际上应该抛出InvalidContext异常,但我会尝试在任何Cuda操作之前通过调用ctx.SetCurrent()将当前上下文设置为活动线程。但如果做得不好,这很容易出错;我总是试图让一个线程对所有Cuda操作都是独占的,以避免多个线程在任何时候在同一个上下文上操作。谢谢你,这很有意义。不幸的是,关于如何使用Cuda编写gui应用程序的文档并不是很完整。如果你想把它作为一个答案,我很乐意接受:)另外:我最近在运行64位应用程序时加载一个编译为32位的PTX时遇到了同样的错误。只有Cubin内核抛出ErrorInvalidImage异常,而PTX内核正常加载,然后无法执行,并显示错误消息。谢谢,这对我帮助很大!
__global__ void kernel(int a, int b, int *c)
{
    *c = (a + b)*(a + b);
}