我有一个OpenCL内核,我希望在不同系统上检测到的所有支持OpenCL的设备(如所有可用的GPU)上运行它,我很感激知道是否有任何简单的方法。我的意思是为所有设备创建一个命令队列。
提前致谢:]
答案 0 :(得分:3)
您无法为所有设备创建单个命令队列;给定的命令队列绑定到单个设备。但是,您可以为每个OpenCL设备创建单独的命令队列,并为它们提供工作,这应该同时执行。
答案 1 :(得分:2)
正如Dithermaster指出你首先为每个设备创建一个单独的命令队列,例如你可能有多个GPU。然后,您可以将它们放在一个数组中,例如,这是一个指向您可以设置的数组的指针:
cl_command_queue* commandQueues;
但是根据我的经验,并不总是在同时执行各种命令队列时“猛烈扣篮”,因为可以使用事件计时信息(检查重叠)进行验证,您可以通过自己的分析或使用第三方分析工具。无论如何,您应该执行此步骤以验证您的设置有效或无效。
另一种可以很好地工作的方法是使用OpenMP同时执行命令队列,例如,你执行以下操作:
#pragma omp parallel for default(shared)
for (int i = 0; i < numDevices; ++i) {
someOpenCLFunction(commandQueues[i], ....);
}
答案 2 :(得分:2)
假设您有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();