这真让我抓狂 . 我看了一遍,但我不确定我究竟究竟是什么导致了这个错误 .
我正在调用一个DLL(我编写为一个单独的项目),它在我正在使用的一些数据上运行CUDA内核 . 虽然,我怀疑这个问题不是由CUDA造成的,因为代码已经过测试并至少运行一次,通常是64到100次,然后才会导致AccessViolationException .
问题是,我传递了三个公共静态数组:
public static float[] neuronInputs;
public static float[] connectionOutputs;
public static int[] calcOrder;
来自neuronInputs的数据被复制到GPU上,然后被操作,然后被复制回connectionOutputs(只读取calcOrder,但不写入) . 我使用connectionOutputs数组执行一系列操作 . 然后我写下了neuronInputs数组,并将其发送回GPU . 重复直到失败 . 它总是失败 .
我正在调用这个函数:
[DllImport("CUDANeural.dll")]
static extern void GenerateSubstrateConnections(
[In, Out] [MarshalAs(UnmanagedType.LPArray)] float[] neuronInputs,
[In, Out] [MarshalAs(UnmanagedType.LPArray)] int[] calcOrder,
[In, Out] [MarshalAs(UnmanagedType.LPArray)] float[] outWeights
);
我只为三个数组分配一次内存,并为每个数组分配一个大块 . 我已经在托管端测试了它,并且我无法在CUDA代码中的数组之外进行索引 .
我想我的问题是,是什么导致了这个AccessViolationException?假设它不是CUDA代码 .
编辑:这是来自非管理方面的电话
extern "C" __declspec(dllexport) void GenerateSubstrateConnections( float* neuronInputs, int* calcOrder, float* outWeights);
看起来我对编程的CUDA方面可能是错的 . 我在对GenerateSubstrateConnections的调用结束时添加了一个cudaExitThread()调用,这似乎纠正了这个问题 . 但是,为了澄清,我称之为不同的功能:
[DllImport("CUDANeural.dll")]
static extern void DebugSubstrateConnections(
[In, Out] IntPtr neuronInputs,
[In, Out] IntPtr calcOrder,
[In, Out] IntPtr outWeights
);
在我在托管代码中调用GenerateSubstrateConnections之前,我将GCHandles固定
SubstrateDescription.inputHandle = GCHandle.Alloc(SubstrateDescription.neuronInputs, GCHandleType.Pinned);
SubstrateDescription.connectionHandle = GCHandle.Alloc(SubstrateDescription.outputConnections, GCHandleType.Pinned);
calcHandle = GCHandle.Alloc(calcOrder, GCHandleType.Pinned);
然后打电话
GenerateSubstrateConnections(
SubstrateDescription.inputHandle.AddrOfPinnedObject(),
calcHandle.AddrOfPinnedObject(),
SubstrateDescription.connectionHandle.AddrOfPinnedObject());
我不完全确定这是否有必要,但我知道它有效(目前) . 感谢您的所有评论,他们帮助我解决了这个问题 .
2 回答
也许是线程安全问题 . 由于您使用的是静态内存,因此您应该锁定对象,或使用其他一些同步选项,除非您完全确定它是单线程的 .
我不确定你是否可以在CUDA函数上做一个简单的pInvoke,因为它们没有在主处理器上运行 . 直接使用本机CUDA API的最佳选择可能是使用C / CLI . nVidia刚刚发布了支持包 . 其他更简单的选项包括使用OPENCL,它具有名为OpenTK的.Net库,它为大多数用途提供托管包装 .