2012-07-20 2 views
0

저는 OpenCL의 초보자입니다. 다음 커널을 작동 시키려고합니다. 구조체 배열을 커널에 전달하고 그 값을 수정하려고합니다. 내 구조체 선언은이 구조체를 전달하는 버퍼를 생성하는OpenCL에서 구조체의 배열에 의한 가비지 출력

#define LIST_SIZE 10 
#pragma pack(push, 1) 

typedef struct pairt { 
    int a; 
    int b; 
} pairt; 

#pragma pack(pop) 

내 호스트 코드는 다음과 같습니다

pairt p[LIST_SIZE]; 
p_mem_obj = clCreateBuffer(context, CL_MEM_READ_WRITE, LIST_SIZE*sizeof(struct pairt), NULL, &ret); 
ret = clEnqueueWriteBuffer(command_queue, p_mem_obj, CL_TRUE, 0, LIST_SIZE*sizeof(struct pairt), &p, 0, NULL, NULL); 

커널 인수를 설정하는 내 코드는 다음과 같습니다

ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&p_mem_obj); 
size_t global_item_size = LIST_SIZE; 
size_t local_item_size = 2; 
ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, &events[0]); 
ret = clWaitForEvents(1, &events[0]); 
ret = clReleaseEvent(events[0]); 
ret = clEnqueueReadBuffer(command_queue, p_mem_obj, CL_TRUE, 0, LIST_SIZE*sizeof(struct pairt), p, 0, NULL, &events[1]); 
ret = clWaitForEvents(1, &events[1]); 

내 커널입니다 :

struct __attribute__ ((packed)) pairt { 
    int a; 
    int b; 
}; 

__kernel void simple_diff(__global struct pairt* p) 
{ 
    int i = get_global_id(0); 
    __global struct pairt *tmp = &p[i]; 

    tmp->a = tmp->a * -1; 
    tmp->b = tmp->b * -1; 

} 
1 2 
3 4 
5 6 
7 8 
9 10 
11 12 
13 14 
15 16 
17 18 
19 20 

하지만 커널에 의해 반환되는 값은 다음과 같습니다 :

-298660672 -32767 
0 0 
-4198172 0 
-298660832 -32767 
-4200052 0 
-1 -2 
-3 -4 
-5 -6 
-7 -8 
-9 -10 

나는 이런 일이 왜 아무 생각이 없다 (10) 나는 다음과 같은 값으로 배열을 초기화?

+1

를 사용하려고하면'의 주소를 가지고 가면 안된다 p. 그냥'p'를 패스하십시오. – James

+0

감사합니다, 그것은 도움이 :) –

답변

0

그럼 아래 코드를 Vs2010과 AMD APP SDK를 사용하여 4 코어 CPU에서 AMD 6950 GPU를 32 비트 및 64 비트 빌드를 사용하여 모두 사용해 보았습니다. 나를 위해 그 작품은 ...

기본 포장에 프라 그마 팩 1에서 구조체를 변경하거나 clEnqueueWriteBuffer``에 전화에서 INT2 벡터

/* 
Copyright (C) Tim Child 2012 
All rights reserved 

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
THE SOFTWARE. 

*/ 

#include <stdio.h> 
#include <stddef.h> 
#include <stdint.h> 
#include <memory.h> 
#include <malloc.h> 

#include "CL\cl.h" 

#define LIST_SIZE 10 
#pragma pack(push, 1) 

typedef struct pairt 
{ 
    int a; 
    int b; 
} pairt; 

#pragma pack(pop) 

typedef struct pair32 
{ 
    int32_t a; 
    int32_t b; 
} pair32; 

void printAligment(char * msg, size_t a, size_t b) 
{ 
    printf("%s\n", msg); 
    printf("\t%d\t%d\n", a, b); 
} 

/** 
    OpenCLEnvironment An OpenCl Environment structure 
**/ 

typedef struct OpenCLEnvironment 
{ 
    cl_platform_id * platformId; 
    cl_uint    platformCount; 
    cl_device_id *  deviceId; 
    cl_uint  *  deviceCount;  
    cl_uint    deviceTotal; 
    cl_context   context; 
    cl_command_queue queue; 
    cl_uint    currentPlatform; 
    cl_uint    currentDevice; 

} OpenCLEnvironment; 

typedef struct OpenCLKernel 
{ 
     char *  name; 
     cl_program program; 
     cl_kernel kernel; 
     char *  sourceCode; 
     char *  compilerOptions; 
     char *  compilerErrors; 

} OpenCLKernel; 

/** 
    NewOpenCLEnvironment Create a new OpenCL Environment 
    @param[in] currentPlatform Index of the platform Id to use 
    @param[in] currentDevice Index of the Device Id to use 

    @returns OpenCL Environment 
**/ 
OpenCLEnvironment * NewOpenCLEnvironment(cl_uint  currentPlatform, cl_uint currentDevice) 
{ 
    OpenCLEnvironment * environment = NULL; 
    cl_int  error = 0; 
    cl_uint  i = 0; 
    cl_uint  sum; 
    cl_uint  offset = 0; 
    static cl_context_properties properties[] = { CL_CONTEXT_PLATFORM, 0, 0}; 

    if ((environment = (OpenCLEnvironment *)malloc(sizeof (OpenCLEnvironment ))) != NULL) 
    { 
     memset(environment, 0, sizeof(OpenCLEnvironment)); 

     if ((error = clGetPlatformIDs(0, NULL, &environment->platformCount)) == CL_SUCCESS) 
     { 
      environment->deviceCount = (cl_uint*)malloc(sizeof(cl_uint) * environment->platformCount ) ; 
      environment->platformId = (cl_platform_id *)malloc(sizeof(cl_platform_id) * environment->platformCount ) ; 
      if (environment->platformId && 
       environment->platformCount > 0 && 
       (error = clGetPlatformIDs(environment->platformCount, environment->platformId, 0)) == CL_SUCCESS) 
      { 
       sum = 0; 
       for(i = 0; i < environment->platformCount; i++) 
       { 
        if ((error = clGetDeviceIDs(environment->platformId[i], CL_DEVICE_TYPE_ALL, 0, NULL, &sum)) == CL_SUCCESS) 
        { 
         environment->deviceCount[i] = sum; 
         environment->deviceTotal += sum; 
        } 
       } 

       environment->deviceId = (cl_device_id *) malloc(sizeof(cl_device_id) * environment->deviceTotal); 
       offset = 0; 
       for(i = 0; i < environment->platformCount && environment->deviceId; i++) 
       { 
        if ( (error = clGetDeviceIDs(environment->platformId[i], CL_DEVICE_TYPE_ALL, environment->deviceCount[i], 
             &environment->deviceId[offset], &sum)) == CL_SUCCESS) 
        { 
         offset += sum; 
        } 
       } 
      } 
     } 

     if (currentPlatform < environment->platformCount && currentDevice < environment->deviceTotal) 
     { 
      environment->currentPlatform = currentPlatform; 
      environment->currentDevice = currentDevice; 
      properties[ 1] = (cl_context_properties)environment->platformId[ environment->currentPlatform ]; 
      environment->context = clCreateContext(properties, 1, &environment->deviceId[ environment->currentDevice ], 
       NULL, NULL, &error); 

      if (error == CL_SUCCESS) 
      { 
       environment->queue = clCreateCommandQueue(environment->context,environment->deviceId[ environment->currentDevice ], 0, &error); 
      } 
     } 
    } 

    return environment; 
} 

/** 
    NewOpenCLKernel Create a new OpenCL Kernel from Source code 
    @param[in] environment OpenC;l Environment 
    @param[in] name Kernel Name 
    @param[in] sourceCode Kernel source code 
    @param[in] compilerOptions command line option used to compile the kernel 

    @returns a New OpenCL Kernel structure 
**/ 
OpenCLKernel * NewOpenCLKernel(OpenCLEnvironment * environment, char * name, char * sourceCode, char * compilerOptions) 
{ 
    OpenCLKernel * kernel = NULL; 
    size_t   size = 0; 
    cl_int   error = CL_SUCCESS; 
    cl_int   error2 = CL_SUCCESS; 

    if ( (kernel = (OpenCLKernel *) malloc(sizeof (OpenCLKernel) )) != NULL) 
    { 
     memset(kernel, 0, sizeof(OpenCLKernel)); 
     kernel->sourceCode = sourceCode; 
     kernel->name = name; 
     kernel->compilerOptions = compilerOptions; 

     kernel->program = clCreateProgramWithSource(environment->context, 1, &kernel->sourceCode, NULL, &error); 

     error = clBuildProgram(kernel->program, 1, &environment->deviceId[ environment->currentDevice], kernel->compilerOptions, 
      NULL, NULL); 

     if (error == CL_BUILD_SUCCESS) 
     { 
      kernel->kernel = clCreateKernel(kernel->program, name, &error); 
     } 
     else if (error != CL_SUCCESS) 
     { 
      error2 = clGetProgramBuildInfo(kernel->program, environment->deviceId[ environment->currentDevice], 
       CL_PROGRAM_BUILD_LOG, (size_t)NULL, NULL, &size); 
      kernel->compilerErrors = (char*)malloc(size +1); 

      error2 = clGetProgramBuildInfo(kernel->program, environment->deviceId[ environment->currentDevice], 
       CL_PROGRAM_BUILD_LOG, size, kernel->compilerErrors , &size); 

     } 

    } 

    return kernel; 
} 


void PrintPair(char * msg, pairt * p, int n) 
{ 
    int i = 0; 

    printf("%s\n", msg); 
    for (i = 0; i < n; i++) 
    { 
     printf ("\t%d\t%d\n", p[i].a, p[i].b); 
    } 
    printf(" \n"); 
} 

int main (int argc, char ** argv) 
{ 
    cl_int  error = CL_SUCCESS; 
    cl_mem  p_mem_obj; 
    size_t  global_item_size = LIST_SIZE; 
    size_t  local_item_size = 2; 
    cl_event events[2]; 

    static pairt unaligned[] = { 
     1, 2, 
     3, 4, 
     5, 6, 
     7, 8, 
     9, 10, 
     11, 12, 
     13, 14, 
     15, 16, 
     17, 18, 
     19, 20,}; 

    pair32 aligned[] = { 
     1, 2, 
     3, 4, 
     5, 6, 
     7, 8, 
     9, 10, 
     11, 12, 
     13, 14, 
     15, 16, 
     17, 18, 
     19, 20,}; 

    cl_int2 vector[] = { 

     1, 2, 
     3, 4, 
     5, 6, 
     7, 8, 
     9, 10, 
     11, 12, 
     13, 14, 
     15, 16, 
     17, 18, 
     19, 20,}; 

    OpenCLEnvironment * environment = NewOpenCLEnvironment(0, 1); 



    static char * simple_diff = "struct __attribute__ ((packed)) pairt { \ 
    int a; \ 
    int b; \ 
}; \ 
\ 
__kernel void simple_diff(__global struct pairt* p) \ 
{             \ 
    int i = get_global_id(0); \ 
    __global struct pairt *tmp = &p[i]; \ 
    \ 
    tmp->a = tmp->a * -1; \ 
    tmp->b = tmp->b * -1; \ 
\ 
}"; 

    OpenCLKernel * simpleDiff; 

    printAligment("Pack 1 aligned", offsetof(pairt, a), offsetof(pairt, b)); 
    printAligment("Default aligned", offsetof(pair32, a), offsetof(pair32, b)); 
    printAligment("Vector aligned", offsetof(cl_int2, s[0]), offsetof(cl_int2, s[1])); 

    simpleDiff = NewOpenCLKernel(environment, "simple_diff", simple_diff, ""); 

    p_mem_obj = clCreateBuffer(environment->context, CL_MEM_READ_WRITE, LIST_SIZE*sizeof(struct pairt), NULL, &error); 
    error = clEnqueueWriteBuffer(environment->queue, p_mem_obj, CL_TRUE, 0, LIST_SIZE*sizeof(struct pairt), &unaligned, 0, NULL, NULL); 

    error = clSetKernelArg(simpleDiff->kernel, 0, sizeof(cl_mem), (void *)&p_mem_obj); 

    error = clEnqueueNDRangeKernel(environment->queue, simpleDiff->kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, &events[0]); 
    error = clWaitForEvents(1, &events[0]); 
    error = clReleaseEvent(events[0]); 
    error = clEnqueueReadBuffer(environment->queue, p_mem_obj, CL_TRUE, 0, LIST_SIZE*sizeof(struct pairt), unaligned, 0, NULL, &events[1]); 
    error = clWaitForEvents(1, &events[1]); 
    error = clReleaseEvent(events[1]); 


    PrintPair("Pack 1", unaligned, sizeof(unaligned)/sizeof(unaligned[0])) 
} 
관련 문제