OpenCL segfaults, но выдает другую ошибку с GDB - PullRequest
0 голосов
/ 26 декабря 2018

У меня очень простое ядро ​​OpenCL, которое я пытаюсь запустить

void kernel point_within(global const int* pointsX, global const int* pointsY, global int* center, global int* extents, global bool* output) {
   output[get_global_id(0)] = (abs(pointsX[get_global_id(0)] - center[0]) <= extents[0]) && \
                              (abs(pointsY[get_global_id(0)] - center[1]) < extents[1]);
};

Это то, с чем я пытаюсь запустить его в C ++

///
//  Attempt to create the program object from a cached binary.  Note that
//  on first run this will fail because the binary has not yet been created.
//
inline cl::Program CreateProgramFromBinary(cl::Context context,const std::vector<cl::Device> devices, const char* fileName)
{
    std::ifstream file(fileName, std::ios::binary | std::ios::ate | std::ios::in);

    uint32_t size = file.tellg();
    file.seekg(0, std::ios::beg);
    char* buffer = new char[size];
    file.read(buffer, size);
    file.close();

    cl::Program::Binaries bin{{buffer, size}};

    std::vector<cl_int> binaryStatus;
    cl_int *err;
    cl::Program program = cl::Program{context, devices, bin, &binaryStatus, err};

    if(err != CL_SUCCESS) {
       std::cout<<" Error building: "<<program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0])<<"\n";
        exit(1);
    }

    return program;
}

///
//  Create an OpenCL program from the kernel source file
//
inline cl::Program CreateBinaryFromProgram(const cl::Context context,const std::vector<cl::Device> devices, const char* readFileName, const char* writeFileName)
{
    std::ifstream file(readFileName, std::ios::binary | std::ios::ate | std::ios::in);

    uint32_t size = file.tellg();
    file.seekg(0, std::ios::beg);
    char* buffer = new char[size];

    file.read(buffer, size);
    file.close();

    cl::Program::Sources sources;

    // kernel calculates for each element C=A+B
    std::string kernel_code(buffer);
    sources.push_back({kernel_code.c_str(),kernel_code.length()});
    cl::Program program{context,sources};
    if(program.build(devices)!=CL_SUCCESS){
       std::cout<<" Error building: "<<program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0])<<"\n";
        exit(0);
    }
    std::vector<char*> output = program.getInfo<CL_PROGRAM_BINARIES>();
    std::vector<size_t> output_sizes = program.getInfo<CL_PROGRAM_BINARY_SIZES>();
    std::ofstream outFile (writeFileName, std::ios::out | std::ios::binary);
    outFile.write(output[0], output_sizes[0]);
    outFile.close();
    return program;
}

devices = loadDevices();
context = cl::Context{devices};
cl::Program program = CreateProgramFromBinary(context, devices, "HelloWorld.cl.bin");

cl::Buffer buffer_PointsX(context,CL_MEM_READ_WRITE,sizeof(int)*10);
cl::Buffer buffer_PointsY(context,CL_MEM_READ_WRITE,sizeof(int)*10);
cl::Buffer buffer_Center(context,CL_MEM_READ_WRITE,sizeof(int)*10);
cl::Buffer buffer_Extends(context,CL_MEM_READ_WRITE,sizeof(int)*10);
cl::Buffer buffer_Output(context,CL_MEM_READ_WRITE,sizeof(bool)*10);

int PointsX[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int PointsY[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int Center[] = {0, 0};
int Extends[] = {1, 2};
bool output[]{false, false, false, false, false, false, false, false, false, false};

//create queue to which we will push commands for the device.
cl::CommandQueue queue(context,devices[0]);

//write arrays A and B to the device
queue.enqueueWriteBuffer(buffer_PointsX,CL_TRUE,0,sizeof(int)*10,PointsX);
queue.enqueueWriteBuffer(buffer_PointsY,CL_TRUE,0,sizeof(int)*10,PointsY);
queue.enqueueWriteBuffer(buffer_Center,CL_TRUE,0,sizeof(int)*10,Center);
queue.enqueueWriteBuffer(buffer_Extends,CL_TRUE,0,sizeof(int)*10,Extends);


//run the kernel
cl::Kernel kernel_add=cl::Kernel(program,"point_within");
kernel_add.setArg(0,buffer_PointsX);
kernel_add.setArg(1,buffer_PointsY);
kernel_add.setArg(2,buffer_Center);
kernel_add.setArg(3,buffer_Extends);
kernel_add.setArg(4,buffer_Output);
queue.enqueueNDRangeKernel(kernel_add, cl::NullRange, cl::NDRange(10),  cl::NDRange(2));
queue.finish();

Этовывод, который я получаю

Using platform: Intel(R) OpenCL Using device: Intel(R) Core(TM) i5-4590S CPU @ 3.00GHz Running program... Segmentation fault

Итак, я пропустил его через GDB

3 errors generated. Error building: Compilation started 1:5:1: error: unknown type name 'opt' 1:5:4: error: expected identifier or '(' 1:5:16: error: source file is not valid UTF-8 Compilation failed

Я получаю совсем другой выход, сигнализирующий об ошибкекомпиляция (чего никогда не было при простом запуске программы)

Я не уверен, как отлаживать это дальше.Я удалил компиляцию из GDB и напрямую запустил из двоичного файла, и эта строка доставила мне неприятности

0  0x00000000004034c9 in cl::Program::Program(cl::Context const&, std::vector<cl::Device, std::allocator<cl::Device> > const&, std::vector<std::pair<void const*, unsigned long>, std::allocator<std::pair<void const*, unsigned long> > > const&, std::vector<int, std::allocator<int> >*, int*) ()
1  0x0000000000403c10 in CreateProgramFromBinary(cl::Context, std::vector<cl::Device, std::allocator<cl::Device> >, char const*) ()
2  0x0000000000401ed6 in main ()

Как мне отладить эту проблему / В чем проблема?

1 Ответ

0 голосов
/ 27 декабря 2018

Вы передаете неинициализированный указатель (err) в конструктор cl::Program, и , тогда в своем тесте ошибок вы не разыменовываете его.Или инициализируйте его, разыщите в вашем тесте и удалите его:

cl_int *err = new cl_int; // <-- initialize pointer
cl::Program program = cl::Program{context, devices, bin, &binaryStatus, err};

if(*err != CL_SUCCESS) { // <-- dereference pointer
    // ....
}
delete err; // <-- release memory

или используйте объект без указателя и передайте адрес cl::Program:

cl_int err; // <-- not pointer
cl::Program{context, devices, bin, &binaryStatus, &err}; // <-- pass address

if(err != CL_SUCCESS) {
    // ....
}

Кроме того, buffer необходимо высвобождать как в CreateProgramFromBinary, так и в CreateBinaryFromProgram:

delete[] buffer; // <-- note `[]`

Как правило, добавьте соответствующий delete немедленно при написании new.Гораздо проще найти неправильно размещенный delete, чем найти отсутствующий .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...