在多个GPU上运行OpenCL内核

在多个GPU上运行OpenCL内核,opencl,Opencl,我有一个OpenCL内核,我想在不同系统上所有检测到的支持OpenCL的设备(如所有可用的GPU)上运行它,我很高兴知道是否有任何简单的方法。我的意思是为所有设备创建一个命令队列 提前感谢:您不能为所有设备创建单个命令队列;给定的命令队列绑定到单个设备。但是,您可以为每个OpenCL设备创建单独的命令队列,并为它们提供工作,这些工作应该同时执行。正如Dithermaster指出的,您首先为每个设备创建单独的命令队列,例如,您可能有多个GPU。然后,您可以将它们放置在一个数组中,例如,这里有一个指

我有一个OpenCL内核,我想在不同系统上所有检测到的支持OpenCL的设备(如所有可用的GPU)上运行它,我很高兴知道是否有任何简单的方法。我的意思是为所有设备创建一个命令队列


提前感谢:

您不能为所有设备创建单个命令队列;给定的命令队列绑定到单个设备。但是,您可以为每个OpenCL设备创建单独的命令队列,并为它们提供工作,这些工作应该同时执行。

正如Dithermaster指出的,您首先为每个设备创建单独的命令队列,例如,您可能有多个GPU。然后,您可以将它们放置在一个数组中,例如,这里有一个指向可以设置的数组的指针:

cl_command_queue* commandQueues;
然而,根据我的经验,在获取并发执行的各种命令队列时,它并不总是一个“扣篮”,这可以通过使用事件计时信息(检查重叠)进行验证,您可以通过自己的评测或使用第三方评测工具来获得这些信息。无论如何,您都应该执行此步骤,以验证在您的设置中哪些是有效的,哪些是无效的

另一种可以很好地工作的方法是使用OpenMP并发执行命令队列,例如,您可以执行以下操作:

#pragma omp parallel for default(shared)
    for (int i = 0; i < numDevices; ++i) {
            someOpenCLFunction(commandQueues[i], ....);
    }
#默认值为pragma omp parallel(共享)
对于(int i=0;i
假设您有N台设备和100个工作元素(作业)。你应该这样做:

#define SIZE 3

std::vector<cl::Commandqueue> queues(SIZE); //One queue for each device (same context)
std::vector<cl::Kernel> kernels(SIZE); //One kernel for each device (same context)
std::vector<cl::Buffer> buf_in(SIZE), buf_out(SIZE); //One buffer set for each device (same context)

// Initialize the queues, kernels, buffers etc....
//Create the kernel, buffers and queues, then set the kernel[0] args to point to buf_in[0] and buf_out[0], and so on...

// Create the events in a finished state
std::vector<cl::Event> events;
cl::UserEvent ev; ev.setStatus(CL_COMPLETE);
for(int i=0; i<queues.size(); i++)
    events.push_back(ev);

//Run all the elements (a "first empty, first run" scheduler)
for(int i=0; i<jobs.size(); i++){
    bool found = false;
    int x = -1;
    //Try all the queues
    while(!found){
        for(int j=0; j<queue.size(); j++)
            if(events[j].getInfo<CL_EVENT_COMMAND_ EXECUTION_STATUS>() == CL_COMPLETED){
                found = true;
                x = j;
                break;
            }
        if(!found) Sleep(50); //Sleep a while if not all the queues have completed, other options are possible (like asigning the job to a random one)
    }
    //Run it
    events[x] = cl::Event(); //Clean it
    queues[x].enqueueWriteBuffer(...); //Copy buf_in
    queues[x].enqueueNDRangeKernel(kernel[x], .... ); //Launch the kernel
    queues[x].enqueueReadBuffer(... , events[x]); //Read buf_out
}

//Wait for completion
for(int i=0; i<queues.size(); i++)
    queue[i].Finish();
#定义尺寸3
std::向量队列(大小)//每个设备一个队列(相同上下文)
std::向量核(大小)//每个设备一个内核(相同的上下文)
标准::向量buf_输入(大小),buf_输出(大小)//为每个设备设置一个缓冲区(相同上下文)
//初始化队列、内核、缓冲区等。。。。
//创建内核、缓冲区和队列,然后将内核[0]参数设置为指向buf_in[0]和buf_out[0],依此类推。。。
//在完成状态下创建事件
向量事件;
cl::用户事件ev;ev.设置状态(完整的CL_);

对于(int i=0;i为每个设备创建单独的上下文,然后在单独的线程中运行(例如,使用pthreads)。如果多个设备需要运行相同的内核,该怎么办?缓冲区是否会在设备之间隐式共享(隐式复制)那么,我需要为不同的设备提供不同的上下文吗?或者没有隐式副本,并且缓冲区在所有设备中都有实例,并且是独立更改的?我假设所有应用程序都有相同的上下文,这意味着缓冲区会在需要时在设备之间自动复制。每个管道需要一个内核+队列+缓冲区(设备)。因此,如果我需要相同的排序算法,我需要为每个设备编译?谢谢。编译过程很常见,只需同时为所有设备编译。