beignet上的OpenCL超时未引发错误?

beignet上的OpenCL超时未引发错误?,opencl,intel,Opencl,Intel,我运行以下(简化的)代码,它运行简化的内核几秒钟,然后检查结果。前400000个左右的结果是正确的,然后下一个结果都是零。内核应该将相同的值(4228)放入450万个元素的输出数组的每个元素中。看起来不知何故,某个地方,某个东西超时了,或者没有同步,但我有点困惑,因为我: 甚至打电话给clFinish只是为了确定 我正在检查所有错误,没有返回错误 结果如下: user@pear:~/git/machinelearning/prototyping/build$ ./testcltimeout

我运行以下(简化的)代码,它运行简化的内核几秒钟,然后检查结果。前400000个左右的结果是正确的,然后下一个结果都是零。内核应该将相同的值(4228)放入450万个元素的输出数组的每个元素中。看起来不知何故,某个地方,某个东西超时了,或者没有同步,但我有点困惑,因为我:

  • 甚至打电话给clFinish只是为了确定
  • 我正在检查所有错误,没有返回错误
结果如下:

user@pear:~/git/machinelearning/prototyping/build$ ./testcltimeout 
out[442496] != 4228: 0
我期望发生的是:代码应该运行到完成,没有错误

上下文:运行在:

  • 贝涅特,OpenCL 1.2
  • 英特尔高清4000集成图形
内核是:

kernel void test_read( const int one,  const int two, global int *out) {
    const int globalid = get_global_id(0);
    int sum = 0;
    int n = 0;
    while( n < 100000 ) {
        sum = (sum + one ) % 1357 * two;
        n++;
    }
    out[globalid] = sum;
}
kernelvoid test_read(常量int one,常量int two,全局int*out){
const int globalid=get_global_id(0);
整数和=0;
int n=0;
而(n<100000){
总和=(总和+1)%1357*2;
n++;
}
out[globalid]=总和;
}
测试代码(我已经尽可能地简化了它…)

#包括
#包括
#包括
使用名称空间std;
#包括“CL/CL.hpp”
模板
std::字符串到字符串(T val){
std::ostringstream myostringstream;

myostringstream你的内核看起来很长。我怀疑你正在超时,Linux(Beignet)比Windows更安静地处理这个问题。因此,我有一些想法

  • 查看
    dmesg
    查看TDR消息。我没有使用Beignet或Linux OpenCL实现,但页面(在“已知问题”下)表明您可以通过
    dmesg
    进行检查
要检查GPU是否挂起,可以执行dmesg并检查 它有以下信息:[17909.175965][drm:i915_hangcheck_hang] 错误Hangcheck计时器已过…如果是,则是GPU挂起。通常,这意味着内核中出现错误,因为它表明 OCL内核已经有6秒甚至更长的时间没有完成了

文档接着说,如果您确实知道内核需要更长的时间才能完成,那么可以禁用超时检查,但警告您可能会出现机器挂起的风险

  • 在Windows上的Intel HD 4000 Graphics上尝试。如果内核占用的时间超过几秒钟,它将超时,驱动程序实际上会崩溃(但会自动重新启动)

  • 尝试使用Intel OpenCL CPU实现的内核(或任何其他没有TRD限制的内核)。检查其正确性和运行时间(10秒?10分钟?)。我认为CPU实现不会超时


您是否碰巧在系统用于显示的设备上运行此内核?某些系统在内核执行“太长”时会中断内核(用于设备共享).同意,是的,我是,我认为这也是很有可能的,但是,我如何检查我的代码中是否发生了这种情况?我需要在代码中做些什么,以便我可以信任内核的结果,或者知道它被中断了?您需要使用运行时错误检查,您已经这样做了。但是,没有针对内核的特定代码超时条件,因为运行时无法控制或跟踪操作系统终止进程并重置设备。因此,运行时将报告一些通用错误代码。只要所有API调用返回成功状态,内核就不会被操作系统杀死。dmesg上的公平点,好消息是,如果内核运行时间少于6秒,我们可以n确保没有被打断。将你的答案标记为“已接受”。
#include <iostream>
#include <sstream>
#include <stdexcept>
using namespace std;

#include "CL/cl.hpp"

template<typename T>
std::string toString(T val ) {
   std::ostringstream myostringstream;
   myostringstream << val;
   return myostringstream.str();
}

void checkError( cl_int error ) {
    if (error != CL_SUCCESS) {
       throw std::runtime_error( "Error: " + toString(error) );
    }
}

int main( int argc, char *argv[] ) {

     cl_int error;  

    cl_device_id *device_ids;

    cl_uint num_platforms;
    cl_uint num_devices;

    cl_platform_id platform_id;
    cl_device_id device;

    cl_context context;
    cl_command_queue queue;
    cl_program program;

    checkError( clGetPlatformIDs(1, &platform_id, &num_platforms) );
    checkError(  clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, 1, &device, &num_devices) );
    device_ids = new cl_device_id[num_devices];
    checkError( clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, num_devices, device_ids, &num_devices) );
    device = device_ids[0];
    context = clCreateContext(0, 1, &device, NULL, NULL, &error);
    checkError(error);
    queue = clCreateCommandQueue(context, device, 0, &error);
    checkError(error);

    string kernel_source = string( "kernel void test_read( const int one,  const int two, global int *out) {\n" ) +
    "    const int globalid = get_global_id(0);\n" +
    "    int sum = 0;\n" +
    "    int n = 0;\n" +
    "    while( n < 100000 ) {\n" +
    "        sum = (sum + one ) % 1357 * two;\n" +
    "        n++;\n" +
    "    }\n" +
    "    out[globalid] = sum;\n" +
    "}\n";
    const char *source_char = kernel_source.c_str();
    size_t src_size = strlen( source_char );
    program = clCreateProgramWithSource(context, 1, &source_char, &src_size, &error);
    checkError(error);

    checkError( clBuildProgram(program, 1, &device, 0, NULL, NULL) );

    cl_kernel kernel = clCreateKernel(program, "test_read", &error);
    checkError(error);

    const int N = 4500000;
    int *out = new int[N];
    if( out == 0 ) throw runtime_error("couldnt allocate array");

    int c1 = 3;
    int c2 = 7;
    checkError( clSetKernelArg(kernel, 0, sizeof(int), &c1 ) );
    checkError( clSetKernelArg(kernel, 1, sizeof(int), &c2 ) );
    cl_mem outbuffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(int) * N, 0, &error);
    checkError(error);
    checkError( clSetKernelArg(kernel, 2, sizeof(cl_mem), &outbuffer) );

    size_t globalSize = N;
    size_t workgroupsize = 512;
    globalSize = ( ( globalSize + workgroupsize - 1 ) / workgroupsize ) * workgroupsize;
    checkError( clEnqueueNDRangeKernel( queue, kernel, 1, NULL, &globalSize, &workgroupsize, 0, NULL, NULL) );
    checkError( clFinish( queue ) );
    checkError( clEnqueueReadBuffer( queue, outbuffer, CL_TRUE, 0, sizeof(int) * N, out, 0, NULL, NULL) );    
    checkError( clFinish( queue ) );

    for( int i = 0; i < N; i++ ) {
       if( out[i] != 4228 ) {
           cout << "out[" << i << "] != 4228: " << out[i] << endl;
           exit(-1);
       }
    }

    return 0;
}