2011-12-18 2 views
2

빌드하려는 모든 커널에서 계속해서 액세스 위반 오류가 발생합니다. 책에서 가져 오는 다른 커널은 잘 작동하는 것 같습니다.OpenCL enqueueNDRangeKernel이 액세스 위반 오류를 발생합니다.

https://github.com/ssarangi/VideoCL - 여기가 코드입니다.

여기에 뭔가가없는 것 같습니다. 누군가 나를 도와 줄 수 있을까요?

고마워요.

[James] - 제안에 감사 드리며 귀하가 옳습니다. 나는 AMD Redwood 카드로 Win 7에서이 작업을 수행하고 있습니다. AMD APP SDK 2.5가 설치된 Catalyst 11.7 드라이버가 있습니다. 아래 코드를 게시하고 있습니다.

#include <iostream> 
#include "bmpfuncs.h" 

#include "CLManager.h" 

void main() 
{ 
    float theta = 3.14159f/6.0f; 
    int W ; 
    int H ; 

    const char* inputFile = "input.bmp"; 
    const char* outputFile = "output.bmp"; 

    float* ip = readImage(inputFile, &W, &H); 
    float *op = new float[W*H]; 

    //We assume that the input image is the array “ip” 
    //and the angle of rotation is theta 
    float cos_theta = cos(theta); 
    float sin_theta = sin(theta); 

    try 
    { 
     CLManager* clMgr = new CLManager(); 

     // Build the Source 
     unsigned int pgmID = clMgr->buildSource("rotation.cl"); 

     // Create the kernel 
     cl::Kernel* kernel = clMgr->makeKernel(pgmID, "img_rotate"); 

     // Create the memory Buffers 
     cl::Buffer* clIp = clMgr->createBuffer(CL_MEM_READ_ONLY, W*H*sizeof(float)); 
     cl::Buffer* clOp = clMgr->createBuffer(CL_MEM_READ_WRITE, W*H*sizeof(float)); 

     // Get the command Queue 
     cl::CommandQueue* queue = clMgr->getCmdQueue(); 
     queue->enqueueWriteBuffer(*clIp, CL_TRUE, 0, W*H*sizeof(float), ip); 

     // Set the arguments to the kernel 
     kernel->setArg(0, clOp); 
     kernel->setArg(1, clIp); 
     kernel->setArg(2, W); 
     kernel->setArg(3, H); 
     kernel->setArg(4, sin_theta); 
     kernel->setArg(5, cos_theta); 

     // Run the kernel on specific NDRange 
     cl::NDRange globalws(W, H); 


     queue->enqueueNDRangeKernel(*kernel, cl::NullRange, globalws, cl::NullRange); 

     queue->enqueueReadBuffer(*clOp, CL_TRUE, 0, W*H*sizeof(float), op); 

     storeImage(op, outputFile, H, W, inputFile); 
    } 
    catch(cl::Error error) 
    { 
     std::cout << error.what() << "(" << error.err() << ")" << std::endl; 
    } 
} 

대기열 -> enqueueNDRangeKernel 줄에서 오류가 발생합니다. 대기열과 커널을 클래스에 저장했습니다.

CLManager::CLManager() 
    : m_programIDs(-1) 
{ 
    // Initialize the Platform 
    cl::Platform::get(&m_platforms); 

    // Create a Context 
    cl_context_properties cps[3] = { 
     CL_CONTEXT_PLATFORM, 
     (cl_context_properties)(m_platforms[0])(), 
     0 
    }; 

    m_context = cl::Context(CL_DEVICE_TYPE_GPU, cps); 

    // Get a list of devices on this platform 
    m_devices = m_context.getInfo<CL_CONTEXT_DEVICES>(); 

    cl_int err; 

    m_queue = new cl::CommandQueue(m_context, m_devices[0], 0, &err); 
} 


cl::Kernel* CLManager::makeKernel(unsigned int programID, std::string kernelName) 
{ 
    cl::CommandQueue queue = cl::CommandQueue(m_context, m_devices[0]); 

    cl::Kernel* kernel = new cl::Kernel(*(m_programs[programID]), kernelName.c_str()); 

    m_kernels.push_back(kernel); 

    return kernel; 
} 
+0

안녕, sarangi. 당신은 여기서 진지한 도움을 얻을만큼 언급하지 않았습니다. 플랫폼 및 CL 구현을 알려주고 문제를 해결하기 위해 수행 한 작업을 포함하여 문제가있는 코드를 게시해야합니다. 외부 저장소에 링크하는 것은 좋지 않습니다. 링크가 유효하지 않을 수도 있기 때문입니다. – James

답변

4

코드를 검사했습니다. 나는 리눅스에있다. 런타임에 오류 을 의미하는 -38이 나타납니다. 그래서 나는 가서 당신의 완충기를 확인했습니다.

cl::Buffer* clIp = clMgr->createBuffer(CL_MEM_READ_ONLY, W*H*sizeof(float)); 
cl::Buffer* clOp = clMgr->createBuffer(CL_MEM_READ_WRITE, W*H*sizeof(float)); 

그런 다음 당신은 포인터로 버퍼를 전달합니다

kernel->setArg(0, clOp); 
kernel->setArg(1, clIp); 

그러나setArg가 값을 예상되므로 버퍼 포인터 역 참조해야한다 : 이러한 변경 후

kernel->setArg(0, *clOp); 
kernel->setArg(1, *clIp); 

을 고양이 회전;)

+0

커널 인수로 배열 (하지만 실제로는 첫 번째 값을 가리키는 포인터)을 전달할 때 배열의 추가는 표시된 코드로 잘 수행되었습니다. – rdoubleui

+0

고마워. 이걸 간과하는 것은 어리 석다. 이것은 실제로 문제를 해결했습니다. 다시 한번 감사드립니다. – ssarangi