2016-08-12 2 views
0

Я пытаюсь сделать асинхронные вызовы ядра в GPGPU с использованием CUDAfy .NET.Запуск ядра с CUDAfy .NET с использованием OpenCL асинхронно

Когда я передаю значения ядру и копирую их обратно на хост, я не всегда получаю ожидаемое значение.

У меня есть структура Foo с байтовой Bar:

[Cudafy] 
public struct Foo { 
    public byte Bar; 
} 

И у меня есть ядро, я хочу назвать:

[Cudafy] 
public static void simulation(GThread thread, Foo[] f) 
{ 
    f[0].Bar = 3; 
    thread.SyncThreads(); 
} 

У меня есть один поток с StreamID = 1 (я пробовал используя несколько потоков, и заметил проблему. Сокращение до одного потока, похоже, не устранило проблему).

 //allocate 
     streamID = 1; 
     count = 1; 
     gpu.CreateStream(streamID); 
     Foo[] sF = new Foo[count]; 
     IntPtr hF = gpu.HostAllocate<Foo>(count); 
     Foo[] dF = gpu.Allocate<Foo>(sF); 
     while (true) 
     { 
      //set value 
      sF[0].Bar = 1; 

      byte begin = sF[0].Bar; 

      //host -> pinned 
      GPGPU.CopyOnHost<Foo>(sF, 0, hF, 0, count); 

      sF[0].Bar = 2; 

      lock (gpu) 
      { 
       //pinned -> device 
       gpu.CopyToDeviceAsync<Foo>(hF, 0, dF, 0, count, streamID); 
       //run 
       gpu.Launch().simulation(dF); 
       //device -> pinned 
       gpu.CopyFromDeviceAsync<Foo>(dF, 0, hF, 0, count, streamID); 
      } 
      //WAIT 
      gpu.SynchronizeStream(streamID); 


      //pinned -> host 
      GPGPU.CopyOnHost<Foo>(hF, 0, sF, 0, count); 

      byte end = sF[0].Bar; 
     } 
     //de-allocate 
     gpu.Free(dF); 
     gpu.HostFree(hF); 
     gpu.DestroyStream(streamID); 

Сначала создаю поток на графическом процессоре.

Я создаю регулярную структуру массива Foo размера 1 (sF) и устанавливаю его значение в баре 1. Затем я создаю закрепленную память на хосте (hF) для Foo. Я также создаю память на устройстве для Foo (dF).

Я инициализирую значение бара структуры до 1, затем копирую его в закрепленную память (в качестве проверки я установил значение 2 для структуры после копирования, чтобы зафиксировать ее, вы поймете, почему позже). Затем я использую блокировку, чтобы обеспечить полный доступ к графическому процессору, и я ставлю копию в dF, запуск для ядра и копию из dF. На данный момент я не знаю, когда все это будет выполняться на GPU ... поэтому я могу вызвать SynchronizeStream, чтобы ждать на хосте до тех пор, пока устройство не будет выполнено.

Когда все будет готово, я могу скопировать закрепленную память (hF) в общую память (sF). Когда я получаю значение, обычно это 3 (который был установлен на устройстве) или 1 (что означает, что либо значение не было установлено в ядре, либо новое значение не было скопировано в закрепленную память). Я знаю, что закрепленная память копируется в структуру, потому что структура никогда не имеет значения 2.

В течение многих прогонов небольшое количество пробегов приводит к чему-то другому, кроме begin = 1 и end = 3. Он всегда будет begin = 1, end = 1, и это происходит примерно в 5-10% времени.

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

Зачем мне возникать проблема с этим кодом?

Большое вам спасибо!

-Phil

ответ

0

Я просто понял, что вопрос был встречающийся. Хотя запуск выполнялся асинхронно ... я не включал поток для запуска.

Изменение моего запуска быть:

gpu.Launch (gridsize, размер_блока, StreamID) .simulation (Df);

разрешил проблему. Кажется, что запуски происходили в потоке 0, а потоки 1 и 2 синхронизировались. Поэтому иногда данные устанавливаются, иногда это не так. Состояние гонки.

 Смежные вопросы

  • Нет связанных вопросов^_^