使用openmp+OpenCL,多线程同时启用多个核函数问题

使用的服务器上每个节点有4个dcu,导师要求使用openmp启动4个线程,每个线程在一个dcu上启动一个kernel。写出来的程序一直报段错误,通过不断注释的方法确认是clCreateBuffer的问题,但是我不知道如何解决,部分代码如下,上下文和编译程序是在omp之前完成的,在omp中创建了命令队列和buffer

	omp_set_num_threads(4);
#pragma omp parallel
		{
			resmat res[10];
			tid = omp_get_thread_num();
			CommandQueue = clCreateCommandQueue(Context, deviceIds[tid], CL_QUEUE_PROFILING_ENABLE, &err);
			if (err != CL_SUCCESS)
			{
				cout << "Error: Can not create CommandQueue" << endl;
			}
			//-------------------------7. 创建输入输出内核内存对象--------------------------------
			// 创建内存对象
			r = clCreateBuffer(
				Context,
				CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, // 输入内存为只读,并可以从宿主机内存复制到设备内存
				10 * sizeof(resmat),					  // 输入内存空间大小
				res,
				&err);
			if (err != CL_SUCCESS)
			{
				cout << err << endl;
				cout << "Error creating memory objects" << endl;
			}

 

你好,我对这个问题也十分感兴趣。请问你解决了吗?
个人认为因为多个设备的缘故,但是会话context始终是一个,而一个context生成的时候需要关联设备。你这里有多个opencl设备,直接生成CL_MEM_COPY_HOST_PTR的cl_mem应该会让opencl不知道往哪个设备上拷贝吧。个人认为应该去掉CL_MEM_COPY_HOST_PTR这个标志,然后后序使用clEnqueueWriteBuffer绑定对应的命令队列来进行初始化各自的cl_mem吧。

我在一个拥有三张nvidia的显卡的环境中,改写了你上述代码,发现是能够正常运行的。现在的代码如下所示:

// 进行omp ocl的组合问题实践
/*
进行操作之后
*/
void omp_ocl(cl_platform_id platform)
{
    cl_int err;
    cl_device_id* devices;
    cl_uint num_devices;
    err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &num_devices);
    devices = (cl_device_id*)malloc(sizeof(cl_device_id) * num_devices);
    err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, num_devices, devices, NULL);
    cl_int errcode;
    cl_context Context = clCreateContext(NULL, num_devices, devices, NULL, NULL, &errcode);
    if(errcode != CL_SUCCESS || Context == NULL)
    {
        printf("create context failed(errcode=%d)\n", errcode);
    }
    omp_set_num_threads(num_devices);
    #pragma omp parallel
    {
        int tid = omp_get_thread_num();
        int res[10];
        for(size_t j = 0; j < 10; j++)
            res[j] = tid;
        cl_command_queue CommandQueue = clCreateCommandQueue(Context, devices[tid], CL_QUEUE_PROFILING_ENABLE, &errcode);
        if (errcode != CL_SUCCESS)
        {
            std::cout << "Error: Can not create CommandQueue" << std::endl;
        }
        //-------------------------7. 创建输入输出内核内存对象--------------------------------
        // 创建内存对象
        cl_mem r = clCreateBuffer(
            Context,
            CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, // 输入内存为只读,并可以从宿主机内存复制到设备内存
            10 * sizeof(int),                      // 输入内存空间大小
            res,
            &errcode);
        if (errcode != CL_SUCCESS)
        {
            std::cout << errcode << std::endl;
            std::cout << "Error creating memory objects" << std::endl;
        }
        printf("tid-----%d\n", tid);
        clReleaseMemObject(r);
        clReleaseCommandQueue(CommandQueue);
    }
    clReleaseContext(Context);
    for(size_t i = 0; i < num_devices; i++)
        clReleaseDevice(devices[i]);
    free(devices);
}