2014-01-07 2 views
4

그래서 OpenCL에서 작동하도록 특정 코드를 얻으려고 머리와 꼬리를 만들려고합니다.OpenCL : 이상한 커널 동작

원래 의도 한 결과를 얻지 못했기 때문에 나는 무엇이 잘못되었는지 알아 내려고 다양한 방법을 시도해 왔습니다. 그래서 아래에 첨부 된 코드를 생각해 냈고 성공적인 실행 후에는 의도 한 결과를 내지 못했습니다.

이 코드의 원래 비전은 지정된 수의 스레드를 실행하고 스레드 번호를 배열에 복사하는 것이 었습니다.

Threads: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 

그러나 내가 얻은 결과.

Threads: 0 0 0 3 0 0 0 7 0 0 0 11 0 0 0 15 

나는 그 결과 패턴을 얻고 있습니다. 그럼 모두

(n % 4) 

내 배열에 숫자를 넣는 것 같습니다. 어떤 이유로 코드가 int으로 취급되고 char으로 변환되면 생각하기 시작했습니다.

OS : - (스노우 레오파드)

gcc main.c -o threadsopencl -std=c99 -framework OpenCL 



#ifdef __APPLE__ 
#include <OpenCL/opencl.h> 
#else 
#include <CL/cl.h> 
#endif 

#include <stdlib.h>  // warning: implicit declaration of function ‘malloc’ 
#include <stdio.h>  // error: ‘stderr’ undeclared (first use in this function) 

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

    /* Retrieve Platforms */ 

    cl_uint Platforms = 0; 

    printf("Checking for OpenCL platforms.\n"); 

    if (CL_SUCCESS == clGetPlatformIDs (0, NULL, &Platforms)) 
    { 
     printf("Found %d platform.\n", Platforms); 

     if (Platforms > 0) 
     { 

      /* Retrieve Platform ID */ 

      printf("Retrieving OpenCL platform details.\n"); 

      cl_platform_id *Platform = malloc((sizeof(cl_platform_id) * Platforms)); 

      clGetPlatformIDs(Platforms, Platform, &Platforms); 


      /* Retrieve Devices on Platform */ 

      cl_uint GPUs = 0; 

      printf("Retrieving GPU devices associated with the detected platform.\n"); 

      clGetDeviceIDs(Platform[0], CL_DEVICE_TYPE_GPU, 0, NULL, &GPUs); 

      if (GPUs > 0) 
      { 

       printf("Found %d GPU device(s).\n", GPUs); 

       cl_device_id *GPU = malloc((sizeof(cl_device_id) * GPUs)); 

       clGetDeviceIDs(Platform[0], CL_DEVICE_TYPE_GPU, GPUs, GPU, &GPUs); 


       cl_uint Error; 


       printf("Creating OpenCL context and associating it with the detected GPU device.\n"); 
             //clCreateContext(NULL, 1, &devices[device_no], &pfn_notify, NULL, &_err) 
       cl_context GPUcontext = clCreateContext(NULL, 1, &GPU[0], 0, NULL, &Error); 
       //clCreateContextFromType(NULL, CL_DEVICE_TYPE_GPU, NULL, NULL, &Error); 

       if (Error != CL_SUCCESS) 
       { 
        printf("Failed to create an OpenCL context!\n"); 
        return 1; 
       } 


       const char *program_source[] = { 
        "__kernel void NumberOfThreads(__global uchar *thread)\n", 
        "{\n", 
        "uchar id = convert_uchar(get_global_id(0));\n", 
        "thread[id] = id;\n", 
        "}\n" 
       }; 


       printf("Creating a program for execution on the device.\n"); 

       cl_program AES = clCreateProgramWithSource(GPUcontext, sizeof(program_source)/sizeof(*program_source), program_source, NULL, &Error); 

       if (Error != CL_SUCCESS) 
       { 
        printf("Failed to create a program from source!\n"); 
        return 1; 
       } 


       printf("Attempting compilation!\n"); 

       if (clBuildProgram(AES, GPUs, &GPU[0], "", NULL, NULL) != CL_SUCCESS) { 
        printf("Program compilation failed!\n"); 

        char buffer[10240]; 

        clGetProgramBuildInfo(AES, GPU[0], CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, NULL); 

        fprintf(stderr, "CL Compilation failed:\n%s", buffer); 
        exit(2); // abort(); 
       } 

       /* Since OpenCL compilation failed is due to incomplete code work */ 


       printf("Allocating space for the data to be executed within the context.\n"); 

       cl_mem Threads = clCreateBuffer(GPUcontext, CL_MEM_WRITE_ONLY, 16*sizeof(char), NULL, &Error); 

       if (Error != CL_SUCCESS) 
       { 
        printf("Failed to allocate buffer for State Matrix!\n"); 
        return 1; 
       } 


       printf("Creating an OpenCL kernel!\n"); 

       cl_kernel ThreadsKernel = clCreateKernel(AES, "NumberOfThreads", &Error); 
       clSetKernelArg(ThreadsKernel, 0, sizeof(cl_mem), &Threads); 


       if (Error != CL_SUCCESS) 
       { 
        printf("Failed to create kernel object!\n"); 
        return 1; 
       } 


       printf("Setting up an execution queue.\n"); 

       cl_command_queue ExecutionQueue = clCreateCommandQueue(GPUcontext, GPU[0], 0, &Error); 

       if (Error != CL_SUCCESS) 
       { 
        printf("Failed to create command queue!\n"); 
        return 1; 
       } 


       printf("Commencing with kernel execution!\n"); 

       cl_event ExecutionComplete; 

       size_t global_work_size[1] = { 16 }; 

       if (clEnqueueNDRangeKernel(ExecutionQueue, ThreadsKernel, 1, NULL, global_work_size, NULL, 0, NULL, &ExecutionComplete) != CL_SUCCESS) 
       { 
        //printf("Failed to execute kernel! Error %d\n", (unsigned int)Error); 

        switch(Error) 
        { 
         case CL_INVALID_PROGRAM_EXECUTABLE: 
         printf("CL_INVALID_PROGRAM_EXECUTABLE\n"); 
         break; 
         case CL_INVALID_COMMAND_QUEUE: 
         printf("CL_INVALID_COMMAND_QUEUE\n"); 
         break; 
         case CL_INVALID_KERNEL: 
         printf("CL_INVALID_KERNEL\n"); 
         break; 
         case CL_INVALID_CONTEXT: 
         printf("CL_INVALID_CONTEXT\n"); 
         break; 
         case CL_INVALID_KERNEL_ARGS: 
         printf("CL_INVALID_KERNEL_ARGS\n"); 
         break; 
         case CL_INVALID_WORK_DIMENSION: 
         printf("CL_INVALID_WORK_DIMENSION\n"); 
         break; 
         case CL_INVALID_GLOBAL_WORK_SIZE: 
         printf("CL_INVALID_GLOBAL_WORK_SIZE\n"); 
         break; 
         case CL_INVALID_WORK_GROUP_SIZE: 
         printf("CL_INVALID_WORK_GROUP_SIZE\n"); 
         break; 
         case CL_INVALID_WORK_ITEM_SIZE: 
         printf("CL_INVALID_WORK_ITEM_SIZE\n"); 
         break; 
         case CL_INVALID_GLOBAL_OFFSET: 
         printf("CL_INVALID_GLOBAL_OFFSET\n"); 
         break; 
         case CL_OUT_OF_RESOURCES: 
         printf("CL_OUT_OF_RESOURCES\n"); 
         break; 
         case CL_MEM_OBJECT_ALLOCATION_FAILURE: 
         printf("CL_MEM_OBJECT_ALLOCATION_FAILURE\n"); 
         break; 
         case CL_INVALID_EVENT_WAIT_LIST: 
         printf("CL_INVALID_EVENT_WAIT_LIST\n"); 
         break; 
         case CL_OUT_OF_HOST_MEMORY: 
         printf("CL_OUT_OF_HOST_MEMORY\n"); 
         break; 
         default: 
         printf("Failed to execute kernel! %u\n", (unsigned int)Error); 
        } 

        return 1; 
       } 
       clWaitForEvents(1, &ExecutionComplete); 
       clReleaseEvent(ExecutionComplete); 


       printf("ThreadValue:"); 
       for (char Loop = 0; Loop < 16; Loop++) 
       { 
        unsigned char ThreadValue = 0; 

        if (clEnqueueReadBuffer(ExecutionQueue, Threads, CL_TRUE, Loop, 1, &ThreadValue, 0, NULL, NULL) != CL_SUCCESS) 
        { 
         printf("Failed to copy data back from Device to Host!\n"); 
         return 1; 
        } 

        printf(" %d", ThreadValue); 
       } 

       printf("\n"); 

       printf("Freeing memory and exiting!\n"); 


       clReleaseMemObject(Threads); 

       clReleaseKernel(ThreadsKernel); 
       clReleaseProgram(AES); 
       clReleaseContext(GPUcontext); 


      } 

     } 

    } 

    return 0; 
} 
+0

커널 내부에서 tid * tid를하고있는 것으로 보이므로 예상 결과는 0,1,3,9가되어야합니다. 제 AMD 시스템에서이 결과를 얻고 있습니다. – Meluha

+0

get_global_id (0) -> 스레드 번호를 검색 한 다음 서명되지 않은 char로 변환합니다. 스레드 배열은 원래 커널 호출 중에 인수를 따라 전달 된 스레드 배열에서 선택되어 스레드 번호 *를 곱한 값을 저장합니다. – Nocturnal

+0

(id * id)가 수정되었습니다. 그러나 코드를 실행 했더니 0 0 0 9 0 0 0 49 0 0 0 0 0 0 0 225가 출력되었습니다. 따라서 3 바이트의 NULL 값을 얻은 다음 커널 함수에서 곱셈 연산을 수행합니다. 이 코드는 다음과 같은 결과를 나타 냈습니다. 0 1 4 9 16 25 36 49 64 91 100 121 144 169 196 225 – Nocturnal

답변