2013-07-22 3 views
1

Эта программа вылетает, когда я пытаюсь cl :: Program.build(), но я не знаю почему. Он падает на последнюю строку этого блока кода:Что может привести к сбою OpenCL в cl :: Program.build?

#define __NO_STD_VECTOR 
#define __CL_ENABLE_EXCEPTIONS 
#include <CL/cl.hPP> 
#include <iostream> 
#include <fstream> 
#include <string> 
#include <CL/cl.h> 

using namespace std; 
using namespace cl; 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    int tmpSize = 1024; 
    float **my2D = new float*[tmpSize]; 
    for(int i = 0; i < tmpSize; i++) 
    { 
     my2D[i] = new float[tmpSize]; 
     for(int i2 = 0; i2 < tmpSize; i2++) 
     { 
      my2D[i][i2] = 5; 
     } 
    } 
    cl::vector <Platform> platforms; 
    Platform::get(&platforms); 

    cl_context_properties cps[3] = {CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[1]()), 0}; 
    Context context(CL_DEVICE_TYPE_ALL, cps); 

    cl::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>(); 

    CommandQueue queue = CommandQueue(context, devices[0], 0); 

    int W = tmpSize; //i.width(); 
    int H = tmpSize; //i.height(); 

    Buffer d_ip = Buffer(context, CL_MEM_READ_ONLY, W*H*sizeof(float)); 
    Buffer d_op = Buffer(context, CL_MEM_WRITE_ONLY, W*H*sizeof(float)); 

    queue.enqueueWriteBuffer(d_ip, CL_TRUE, 0, W*H*sizeof(float), my2D); 

    std::ifstream sourceFileName("c:\\users\\me\\desktop\\img_rotate_kernel.cl"); 
    std::string sourceFile(istreambuf_iterator<char>(sourceFileName), (istreambuf_iterator<char>())); 

    Program::Sources rotn_source(1,std::make_pair(sourceFile.c_str(), sourceFile.length() + 1)); 
    Program rotn_program(context, rotn_source); 
    rotn_program.build(devices); // <----- CRASHES HERE 
} 

, используя это ядро ​​

__kernel void img_rotate(__global float* dest_data, __global float* src_data, int W, int H, float sinTheta, float cosTheta) 
    const int ix = get_global_id(0); 
    const int iy = get_global_id(1); 
    float x0 = W/2.0f; 
    float y0 = W/2.0f; 
    float xOff = ix-x0; 
    float yOff = iy - y0; 
    int xpos = (int)(xOff*cosTheta + yOff*sinTheta + x0); 
    int ypos = (int)(yOff*cosTheta - yOff*sinTheta + y0); 
    if(((int)xpos>=0) && ((int)xpos < W) && ((int)ypos>=0) && ((int)ypos<H)) 
    { 
     dest_data[iy*W+ix] = src_data[ypos*W+xpos]; 
    } 
} 

Вот диалог исключения я получаю, когда он выходит из строя

enter image description here

ответ

1

От OpenCL C++ wrapper spec :

cl :: Program :: Program возвращает действительный программный объект, а err устанавливается в CL_SUCCESS, если объект программы создан успешно. В противном случае, она возвращает один из следующих значений ошибок, возвращаемых в ERR [...]

Ваш программный объект, скорее всего, не создан должным образом, изменить свою строительную программу вызова использовать параметр err после этой подписи

cl::Program::Program(const Context& context, const Sources& sources, cl_int * err = NULL) 

И удостоверьтесь, что err == CL_SUCCESS перед тем, как делать что-либо еще с вашим программным объектом.

Большинство вызовов OpenCL позволяют передавать указатель на параметр ошибки. Вы действительно должны это сделать и проверить его после ваших звонков (по крайней мере, в отладочных сборках, я думаю), чтобы уменьшить будущие головные боли.

Хорошо, поэтому я немного изменил ваш исходный код. Здесь я объясню свои изменения сразу после.

#define __NO_STD_VECTOR 
#define __CL_ENABLE_EXCEPTIONS 
#include <CL/cl.hpp> 
#include <iostream> 
#include <fstream> 
#include <string> 
#include <CL/cl.h> 

#define ARRAY_SIZE 128 

using namespace std; 
using namespace cl; 

int main(int, char**) 
{ 
    int err; 

    float my2D[ARRAY_SIZE * ARRAY_SIZE] = { 0 }; 
    for(int i = 0; i < ARRAY_SIZE * ARRAY_SIZE; i++) 
    { 
     my2D[i] = 5; 
    } 

    cl::vector <Platform> platforms; 
    err = Platform::get(&platforms); 

    if(err != CL_SUCCESS) { 
     std::cout << "Platform::get failed - " << err << std::endl; 
     std::cin.get(); 
    } 

    cl_context_properties cps[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0]()), 0 }; 
    Context context(CL_DEVICE_TYPE_ALL, cps, nullptr, nullptr, &err); 

    if(err != CL_SUCCESS) { 
     std::cout << "Context::Context failed - " << err << std::endl; 
     std::cin.get(); 
    } 

    cl::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>(&err); 

    if(err != CL_SUCCESS) { 
     std::cout << "Context::getInfo failed - " << err << std::endl; 
     std::cin.get(); 
    } 

    CommandQueue queue = CommandQueue(context, devices[0], 0, &err); 

    if(err != CL_SUCCESS) { 
     std::cout << "CommandQueue::CommandQueue failed - " << err << std::endl; 
     std::cin.get(); 
    } 

    int W = ARRAY_SIZE; //i.width(); 
    int H = ARRAY_SIZE; //i.height(); 

    Buffer d_ip = Buffer(context, CL_MEM_READ_ONLY, W*H*sizeof(float), nullptr, &err); 

    if(err != CL_SUCCESS) { 
     std::cout << "Buffer::Buffer 1 failed - " << err << std::endl; 
     std::cin.get(); 
    } 

    Buffer d_op = Buffer(context, CL_MEM_WRITE_ONLY, W*H*sizeof(float), nullptr, &err); 

    if(err != CL_SUCCESS) { 
     std::cout << "Buffer::Buffer 2 failed - " << err << std::endl; 
     std::cin.get(); 
    } 

    err = queue.enqueueWriteBuffer(d_ip, CL_TRUE, 0, W*H*sizeof(float), &my2D[0]); 

    if(err != CL_SUCCESS) { 
     std::cout << "Queue::enqueueWriteBuffer failed - " << err << std::endl; 
     std::cin.get(); 
    } 

    std::ifstream sourceFileName("so_question.cl"); 
    std::string sourceFile(std::istreambuf_iterator<char>(sourceFileName), (std::istreambuf_iterator<char>())); 

    Program::Sources rotn_source(1,std::make_pair(sourceFile.c_str(), sourceFile.length() + 1)); 
    Program rotn_program(context, rotn_source, &err); 

    if(err != CL_SUCCESS) { 
     std::cout << "Program::Program failed - " << err << std::endl; 
     std::cin.get(); 
    } 

    err = rotn_program.build(devices); 

    if(err != CL_SUCCESS) { 
     std::cout << "Program::build failed - " << err << std::endl; 
     std::cin.get(); 
    } 
} 

Вы заметите, что я добавил намного больше проверок ошибок. Это позволило мне узнать, что звонок Context::Context фактически сделал сбой в вашей первоначальной программе. Вероятно, проблема заключалась в том, что platforms[1] не существовало (в векторе было 1 элемент), поэтому я переключил его на platforms[0].

Как только это было исправлено, я получил нарушение доступа на вызов queue.enqueueWriteBuffer();. Проблема заключалась в том, что ваш 2-мерный массив был фактически массивом массивов, распределенных по кучам. Это проблема, потому что OpenCL ожидает, что сможет считывать данные из непрерывной памяти, что не относится к распределению с помощью нового в цикле, как вы это делали. На самом деле не было никакой гарантии, что ваши массивы будут рядом друг с другом в памяти.

Чтобы решить эту задачу, я выделил одномерный массив в стеке (см. Цикл в начале). Вызов затем становится

queue.enqueueWriteBuffer(d_ip, CL_TRUE, 0, W*H*sizeof(float), &my2D[0]); 

Однако, вы, вероятно, не будете в состоянии сделать это с 1024 х 1024 массивом float, потому что вы будете бюстом пространства стека. Если вам нужен массив, который большой, вы, вероятно, захотите new один одномерный массив, достаточно большой, чтобы содержать ваши данные и выполнять арифметику индекса самостоятельно. Это гарантирует, что вы получите все пространство для хранения как один непрерывный кусок.

Код ошибки в коде CL_BUILD_PROGRAM_FAILURE на вызов err = rotn_program.build(), что означает, что в вашем программном коде CL есть ошибка. Поскольку это совершенно другая проблема, я позволю вам понять это.

+0

спасибо, что показал мне, как это сделать. к сожалению, он все еще терпит крах. ----> int e = -1; Программа rotn_program (контекст, rotn_source, &e); \t если (е == CL_SUCCESS) \t \t е = rotn_program.build (устройства);.! – user1873073

+0

@ user1873073 Я обновил свой ответ, дайте мне знать, если это помогло –

+0

еще раз спасибо платформа был установлен на 1 по назначению, но я понятия не имел о других вещах. Что касается ядра, ему не хватало открытия {. – user1873073

Смежные вопросы