C # P / Invoke на CUDA DLL в конечном итоге вызывает AccessViolationException - PullRequest
2 голосов
/ 10 сентября 2010

Это сводит меня с ума. Я просмотрел все, но не уверен, что точно понимаю, что является причиной этой ошибки.

Я обращаюсь к DLL (которую я кодировал как отдельный проект), которая запускает ядро ​​CUDA для некоторых данных, которые я использую. Хотя я подозреваю, что проблема не в CUDA, так как код был протестирован и работает по крайней мере один раз, и обычно 64-100 раз, прежде чем вызвать AccessViolationException.

Проблема в том, что я передаю три открытых статических массива:

public static float[] neuronInputs;
public static float[] connectionOutputs;
public static int[] calcOrder;

Данные из neuronInputs копируются в GPU, обрабатываются, а затем копируются обратно в connectionOutputs (calcOrder только читается, но не записывается). Я выполняю кучу операций, используя массив connectionOutputs. Затем я переписываю массив neuronInputs и отправляю его обратно в графический процессор. Повторять пока не получится. И это всегда терпит неудачу.

Я вызываю эту функцию:

[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.

EDIT: Вот звонок с неуправляемой стороны

<code>extern "C" __declspec(dllexport) void GenerateSubstrateConnections(<br>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 ]

1 голос
/ 11 сентября 2010

Я не уверен, что даже вы можете сделать простой pInvoke для функций CUDA, так как они не работают на главном процессоре.Лучшим вариантом для непосредственного использования нативного API CUDA может быть использование C ++ / CLI.И nVidia только что выпустила пакет поддержки для этого.Другие более простые варианты включают использование OPENCL с доступной библиотекой .Net под названием OpenTK , которая предоставляет управляемые оболочки для большинства применений.

1 голос
/ 10 сентября 2010

Может быть, проблема безопасности потока.Поскольку вы используете статическую память, вам следует заблокировать объект или использовать какой-либо другой параметр синхронизации, если вы не уверены, что он однопоточный.

...