C++ 有没有办法阻止OpenCL内核执行?

C++ 有没有办法阻止OpenCL内核执行?,c++,c,opencl,C++,C,Opencl,有没有办法阻止OpenCL内核执行? 例如,我启动内核,进行一些计算,然后在满足某些条件时停止它,否则,我将等待它完成: clEnqueueNDRange(queue, ...); // start kernel function // do other stuff... // ... if (some condition met) { stopKernel(); } else { clFinish(queue); } 感谢您的帮助否。一旦您将内核排入队列,它将运行到完成

有没有办法阻止OpenCL内核执行? 例如,我启动内核,进行一些计算,然后在满足某些条件时停止它,否则,我将等待它完成:

clEnqueueNDRange(queue, ...); // start kernel function

// do other stuff...
// ...

if (some condition met) {
    stopKernel();
} else { 
    clFinish(queue);
}

感谢您的帮助

否。一旦您将内核排入队列,它将运行到完成

实现上述目标的一种方法是:

while ( data_left_to_process ) {

   clEnqueueNDRangeKernel( ..., NDRange for a portion of the data, ... )

   // other work

   if (condition) {
      break;
   }

   // adjust NDRange for next execution to processes the next part of your data

}

clFinish(queue);
这使得您可以避免处理所有数据,一个明显的折衷是,您现在提交的工作分为更小的块,这可能会对性能产生影响。

可能

  • 在上下文中创建两个命令队列
  • 创建两个内核,一个用于执行工作,另一个用于停止执行。每个内核都可以访问共享的全局缓冲区
  • 将第一个内核加载到queue1中
  • 当您想停止执行时,将第二个内核加载到queue2中
  • 或者,您可以使用无序队列并将第二个内核加载到同一命令队列中以停止执行。您必须更加小心(必要时使用clFinish/clFlush),但是这是一种更自然的方法

    一些伪代码(用于多个队列):

    使用int或float缓冲区作为停止变量,并通过内核中的global_id访问它们,以减少在循环中读取global的成本。缺点是您的状态是不确定的:如果没有更多的变量来计算执行情况等,您将不知道有多少个工作项以及哪些工作项已经执行

    果仁:

    void kernel1( ... ,global int * g_stop)
    {
        int index_from_ids = ...;
        while (g_stop[index_from_ids] == 0) // or 'if' for single pass execution
        {
            // do work here
        }
    }
    
    void kernel2( ... ,global int * g_stop)
    {
        int index_from_ids = ...;
        g_stop[index_from_ids] = 1;
    }
    

    一种方法是分块进行工作加载,因此,如果您有一个10000x1000全局工作者,例如:

    clEnqueueNDRangeKernel(queue, kernel, 2, NDRange(0,0), NDRange(10000,10000),... );
    
    您可以分块进行,如下所示:

    for(int i=0; i<100; i++)
        for(int j=0; j<100; j++)
             if(condition)
                 clEnqueueNDRangeKernel(queue, kernel, 2, NDRange(i*100,j*100),DRange(100,100),... );
    

    for(int i=0;iIs)有没有办法使解决方案100%定义行为,例如使用原子int?
    
    for(int i=0; i<100; i++)
        for(int j=0; j<100; j++)
             if(condition)
                 clEnqueueNDRangeKernel(queue, kernel, 2, NDRange(i*100,j*100),DRange(100,100),... );