clCloneKernel вызывает ошибку сегментации - PullRequest
1 голос
/ 07 февраля 2020

Я экспериментирую с clCloneKernel, чтобы увидеть, как ядро ​​может использоваться несколькими потоками хоста. Спецификация OpenCL заявляет, что установка аргументов ядра (помимо прочего) не является поточно-ориентированной. Поэтому использование clCloneKenrel должно обеспечить обходной путь, если одно и то же ядро ​​должно вызываться несколькими потоками хоста.

Проблема заключается в том, что как только clCloneKernel вызывается для инициализированного объекта cl_kernel (независимо от того, является ли он до или после установка аргументов) вызывает ошибку программы.

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

#ifdef __APPLE__
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif

using namespace std;

const int MAXNUMDEV = 10;

string kernSource = "       \
kernel void hello()   \
{                     \
   int ID = get_global_id(0);  \
   int grID = get_group_id(0);  \
   printf(\"Work item %i from group %i says hello!\\n\", ID, grID); \
}";

//============================================
void cleanUp (cl_context c, cl_command_queue q, cl_program p, cl_kernel k)
{
  if (k != 0)
    clReleaseKernel (k);

  if (p != 0)
    clReleaseProgram (p);

  if (q != 0)
    clReleaseCommandQueue (q);

  if (c != 0)
    clReleaseContext (c);
}
//============================================
int main ()
{
  cl_int errNum;
  cl_uint numPlatforms;
  cl_platform_id firstPlatformId;
  cl_device_id devID[MAXNUMDEV];
  cl_uint numDev;
  cl_context cont = 0;          // initialize for cleanup check
  cl_command_queue q = 0;
  cl_program pr = 0;
  cl_kernel kernel = 0;

  // Get a reference to an object representing a platform 
  errNum = clGetPlatformIDs (1, &firstPlatformId, &numPlatforms);
  if (errNum != CL_SUCCESS || numPlatforms <= 0)
    {
      cerr << "Failed to find any OpenCL platforms." << endl;
      return 1;
    }

  // Get the device IDs matching the CL_DEVICE_TYPE parameter, up to the MAXNUMDEV limit
  errNum = clGetDeviceIDs (firstPlatformId, CL_DEVICE_TYPE_ALL, MAXNUMDEV, devID, &numDev);
  if (errNum != CL_SUCCESS || numDev <= 0)
    {
      cerr << "Failed to find any OpenCL devices." << endl;
      return 2;
    }

  char devName[100];
  size_t nameLen;
  for (int i = 0; i < numDev; i++)
    {
      errNum = clGetDeviceInfo (devID[i], CL_DEVICE_NAME, 100, (void *) devName, &nameLen);
      if (errNum == CL_SUCCESS)
        cout << "Device " << i << " is " << devName << endl;
    }


  cl_context_properties prop[] = {
    CL_CONTEXT_PLATFORM,
    (cl_context_properties) firstPlatformId,
    0                           // termination
  };

  cont = clCreateContext (prop, numDev, devID, NULL,    // no callback function
                          NULL, // no data for callback
                          &errNum);
  if (errNum != CL_SUCCESS)
    {
      cerr << "Failed to create a context." << endl;
      cleanUp (cont, q, pr, kernel);
      return 1;
    }

  cl_queue_properties qprop[] = {
    CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
    0
  };
  q = clCreateCommandQueueWithProperties (cont, devID[0], qprop, &errNum);
  if (errNum != CL_SUCCESS)
    {
      cerr << "Failed to create a command queue" << endl;
      cleanUp (cont, q, pr, kernel);
      return 1;
    }

  const char *src = kernSource.c_str ();
  size_t len = kernSource.size ();
  pr = clCreateProgramWithSource (cont, 1, (const char **) (&src), &len, &errNum);
  if (errNum != CL_SUCCESS)
    {
      cerr << "Failed to create program." << endl;
      cleanUp (cont, q, pr, kernel);
      return 1;
    }

  errNum = clBuildProgram (pr, 1, devID, NULL, NULL, NULL);
  if (errNum != CL_SUCCESS)
    {
      cerr << "Failed to build program" << endl;
      cleanUp (cont, q, pr, kernel);
      return 1;
    }


  kernel = clCreateKernel (pr, "hello", &errNum);
  if (errNum != CL_SUCCESS || kernel == NULL)
    {
      cerr << "Failed to create kernel" << endl;
      cleanUp (cont, q, pr, kernel);
      return 1;
    }

  cl_kernel copyKern = clCloneKernel(kernel, &errNum); // <<<<<<<<<<<<<<<

  // work item index space and group size setup
  size_t idxSpace[] = { 12 };
  size_t localWorkSize[] = { 3 };

  cl_event completeEv;
  errNum = clEnqueueNDRangeKernel (q, kernel, 1, NULL, idxSpace, localWorkSize, 0, NULL, &completeEv);

  // wait for enqueued command to finish
  clWaitForEvents (1, &completeEv);

  cleanUp (cont, q, pr, kernel);
  return 0;
}

1 Ответ

0 голосов
/ 08 февраля 2020

clCloneKernel() был представлен в OpenCL 2.1. Ваша платформа OpenCL реализует эту версию стандарта? Я подозреваю, что это не так, следовательно, cra sh.

...