opencl给出了双数据类型的错误结果?

时间:2014-02-07 05:25:53

标签: c opencl

我是OpenCl的新手。

问题:我正在Host中初始化一个值为-1的10个元素的数组。我将相同的数组作为输入传递给设备并递增每个元素,然后通过Buffer接收数组作为输出。然后,再次将相同的输出数组作为输入发送回主机并接收增加的输出缓冲区。这是循环完成的。

问题:当我将数组的数据类型设置为float / int时,程序运行正常。但是当我将数据类型设置为数组的两倍时,它并没有给出我想要的结果。 请告诉我失踪的地方?任何帮助/建议/关键字都将是一个很大的帮助。提前谢谢。

数组浮点数据类型的代码:

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


#define MEM_SIZE (10)
#define MAX_SOURCE_SIZE (0x100000)


int main() {
    float input[MEM_SIZE], output[MEM_SIZE];
    int go, i;
    for (i = 0; i < MEM_SIZE; i++) {
        input[i] = -1.0;
        output[i] = -1.0;
    }
    FILE *fp;
    cl_device_id device_id = NULL;
    cl_context context = NULL;
    cl_command_queue command_queue = NULL;
    cl_program program = NULL;
    cl_kernel kernel = NULL;
    cl_platform_id platform_id = NULL;
    cl_uint ret_num_devices;
    cl_uint ret_num_platforms;
    cl_int ret;
    size_t source_size;
    char *source_str;
    fp = fopen("calc_float.cl", "r");
    if (!fp) {
        fprintf(stderr, "Failed to load kernel.\n");
        exit(1);
    }
    source_str = (char*)malloc(MAX_SOURCE_SIZE);
    source_size = fread(source_str, 1, MAX_SOURCE_SIZE, fp);
    fclose(fp);


    /*Initialization*/
    /* Get Platform and Device Info */
    ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);
    ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1, &device_id, &ret_num_devices);

    /* Create OpenCL context */
    context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);

    /* Create Command Queue */
    command_queue = clCreateCommandQueue(context, device_id, 0, &ret);

    /*Initialization complete*/

    cl_mem inputBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, MEM_SIZE * sizeof(float),(void *) input, NULL);
    cl_mem outputBuffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY , MEM_SIZE * sizeof(float), NULL, NULL);


    /* Create Kernel Program from the source */
    program = clCreateProgramWithSource(context, 1, (const char **)&source_str,(const size_t *)&source_size, &ret);

    /* Build Kernel Program */
    ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);

    /* Create OpenCL Kernel */
    kernel = clCreateKernel(program, "calc", &ret);

    /* Set OpenCL Kernel Parameters */
    ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&inputBuffer);
    ret = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&outputBuffer);

    /* Execute OpenCL Kernel */
    ret = clEnqueueTask(command_queue, kernel, 0, NULL,NULL);
    double x = 10, io;
    size_t global_work_size[1] = {MEM_SIZE};
    for (io = 0; io < x; io++) {
        inputBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, MEM_SIZE * sizeof(float),(void *) output, NULL);
        ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&inputBuffer);
        ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, global_work_size, NULL, 0, NULL, NULL);

        ret = clEnqueueReadBuffer(command_queue, outputBuffer, CL_TRUE, 0, MEM_SIZE * sizeof(float), output, 0, NULL, NULL);
        for (go = 0; go < MEM_SIZE; go++) {
            printf("output[%d] = %f\n",io, go, output[go]);
        }
        printf("\n\n");

    }


    /* Finalization */
    ret = clFlush(command_queue);
    ret = clFinish(command_queue);
    ret = clReleaseKernel(kernel);
    ret = clReleaseProgram(program);
    ret = clReleaseMemObject(inputBuffer);
    ret = clReleaseMemObject(outputBuffer);
    ret = clReleaseCommandQueue(command_queue);
    ret = clReleaseContext(context);

    return 1;
}
上面代码的

calc_float.cl文件:

__kernel void calc(__global float* in, __global float* out)
{
    int i;
    for (i = 0; i < 10; i++) {
        out[i] = in[i] + 1;
    }
}

数组的双数据类型代码:

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

#define MEM_SIZE (10)
#define MAX_SOURCE_SIZE (0x100000)


int main() {
    double input[MEM_SIZE], output[MEM_SIZE];
    int go, i;
    for (i = 0; i < MEM_SIZE; i++) {
        input[i] = -1.0;
        output[i] = -1.0;
    }
    FILE *fp;
    cl_device_id device_id = NULL;
    cl_context context = NULL;
    cl_command_queue command_queue = NULL;
    cl_program program = NULL;
    cl_kernel kernel = NULL;
    cl_platform_id platform_id = NULL;
    cl_uint ret_num_devices;
    cl_uint ret_num_platforms;
    cl_int ret;
    size_t source_size;
    char *source_str;
    fp = fopen("calc_double.cl", "r");
    if (!fp) {
        fprintf(stderr, "Failed to load kernel.\n");
        exit(1);
    }
    source_str = (char*)malloc(MAX_SOURCE_SIZE);
    source_size = fread(source_str, 1, MAX_SOURCE_SIZE, fp);
    fclose(fp);


    /*Initialization*/
    /* Get Platform and Device Info */
    ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);
    ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1, &device_id, &ret_num_devices);

    /* Create OpenCL context */
    context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);

    /* Create Command Queue */
    command_queue = clCreateCommandQueue(context, device_id, 0, &ret);

    /*Initialization complete*/

    cl_mem inputBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, MEM_SIZE * sizeof(double),(void *) input, NULL);
    cl_mem outputBuffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY , MEM_SIZE * sizeof(double), NULL, NULL);


    /* Create Kernel Program from the source */
    program = clCreateProgramWithSource(context, 1, (const char **)&source_str,(const size_t *)&source_size, &ret);

    /* Build Kernel Program */
    ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);

    /* Create OpenCL Kernel */
    kernel = clCreateKernel(program, "calc", &ret);

    /* Set OpenCL Kernel Parameters */
    ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&inputBuffer);
    ret = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&outputBuffer);

    /* Execute OpenCL Kernel */
    ret = clEnqueueTask(command_queue, kernel, 0, NULL,NULL);
    double x = 10, io;
    size_t global_work_size[1] = {MEM_SIZE};
    for (io = 0; io < x; io++) {
        inputBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, MEM_SIZE * sizeof(double),(void *) output, NULL);
        ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&inputBuffer);
        ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, global_work_size, NULL, 0, NULL, NULL);

        ret = clEnqueueReadBuffer(command_queue, outputBuffer, CL_TRUE, 0, MEM_SIZE * sizeof(double), output, 0, NULL, NULL);
        for (go = 0; go < MEM_SIZE; go++) {
            printf("output[%d] = %lf\n",io, go, output[go]);
        }
        printf("\n\n");

    }


    /* Finalization */
    ret = clFlush(command_queue);
    ret = clFinish(command_queue);
    ret = clReleaseKernel(kernel);
    ret = clReleaseProgram(program);
    ret = clReleaseMemObject(inputBuffer);
    ret = clReleaseMemObject(outputBuffer);
    ret = clReleaseCommandQueue(command_queue);
    ret = clReleaseContext(context);

    return 1;
}
上面代码的

calc_double.cl文件:

__kernel void calc(__global double* in, __global double* out)
{
    int i;
    for (i = 0; i < 10; i++) {
        out[i] = in[i] + 1;
    }
}

程序汇编:

gcc program.c -o doublesimulation -l OpenCL -I /usr/local/test/AMD-APP-SDK-v2.9-RC-lnx32/include/ -L /usr/local/test/AMD-APP-SDK-v2.9-RC-lnx32/lib/x86

我也尝试添加以下检查,但没有帮助:

#ifdef cl_khr_fp64
    #pragma OPENCL EXTENSION cl_khr_fp64 : enable
#elif defined(cl_amd_fp64)
    #pragma OPENCL EXTENSION cl_amd_fp64 : enable
#else
    #error "Double precision floating point not supported by OpenCL implementation."
#endif

操作系统:采用AMD显卡的Centos5 32位

1 个答案:

答案 0 :(得分:3)

检查您的GPU是否支持双精度:

cl_uint native_double_width;    
clGetDeviceInfo(device_id, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE, sizeof(cl_uint), &native_double_width, NULL);

if(native_double_width == 0){
    printf("No double precision support.\n");
}

如果原生双向量宽度等于0,则不支持双精度(clGetDeviceInfo description