Сбой чтения буфера нескольких графических процессоров OpenCL

Я пытаюсь заставить 2 графических процессора Nvidia работать бок о бок для моделирования n-тел (источник). Я делаю правильное обнаружение и храню все материалы OpenCL в одной структуре:

struct ocl_wrap {
  cl_event event;
  cl_program program;
  cl_kernel kernel;
  cl_command_queue command_queue;
  cl_device_id device_id;
  cl_context context;

  cl_mem masses;
  cl_mem bodies;
  cl_mem speeds;
  cl_mem newBodies;

  cl_int ret;
};

Итак, теперь каждое устройство назначает свою собственную структуру (свой собственный контекст, очередь и т. д.), и на каждом этапе я запускаю эти 2 функции:

void writeGPU() {
      clCreateBuffer() //4* 
      clSetKernelArg() //5*
      clEnqueueNDRangeKernel()
}
void readGPU() {
      clEnqueueReadBuffer() //2*
      clFlush()
      clReleaseMemObject() //4*
}

И один шаг выглядит так:

void step() {
  for each gpu
    writeGPU();
  runCPU();
  for each gpu
    readGPU();
}

Где каждому устройству дается подмножество проблем, которые необходимо решить.

У меня проблема, что первые 64 (иногда 128) выплывают из одного или другого GPU, которые я пытаюсь скопировать обратно в CPU, на самом деле не копируются. В остальном все работает корректно, первый GPU работает без нареканий. Иногда это просто работает, но просто случайным образом появляется ошибка, и она не исчезает. Какие-либо предложения?


person Ozbolt    schedule 02.01.2014    source источник


Ответы (2)


На данный момент я предполагаю, что вы, вероятно, не используете систему событий OpenCL и, возможно, даже барьеры/заборы памяти OpenCL, чтобы получать уведомления о чтении-записи ввода-вывода. достигли места назначения и координировать вашу программу, устанавливая точки останова и списки ожидания. Если дистрибутив OpenCL у вас в системе работает как надо и вы используете систему событий, то представленная выше последовательность программ должна напоминать

// setup global event objects
// setup global markers/barriers
void writeGPU() {
      // hook event listeners to APIs
      clCreateBuffer() //4* 
      clSetKernelArg() //5*
      clEnqueueNDRangeKernel()
      // place appropriate markers/barriers
}
void readGPU() {
      // Many OpenCL APIs listen to events and proceed only 
      // when the `wait` condition is satisfied or 
      // barrier conditions are met.
      clEnqueueReadBuffer() //2*
      clFlush()
      clReleaseMemObject() //4*
}
person Raymond Tay    schedule 02.01.2014

Вероятно, вы просматриваете данные до завершения чтения. clFlush только гарантирует, что команда покинула хост, а не то, что команда завершилась на устройстве. Решение: используйте чтение с блокировкой, или используйте clFinish вместо clFlush, или используйте события OpenCL.

person Dithermaster    schedule 04.01.2014