【问题标题】:what is printf format specifier for cl_ulong什么是 cl_ulong 的 printf 格式说明符
【发布时间】:2013-06-22 23:40:29
【问题描述】:

@H2CO3

这是我的主要代码:

#pragma OPENCL EXTENSION cl_ amd_ printf : enable
#define PROGRAM_FILE "matvec.cl"
#define KERNEL_FUNC "matvec_mult"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#ifdef MAC
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif
int main() {
cl_platform_id platform;
cl_device_id device;
cl_context context;
cl_command_queue queue;
cl_int i,err;
cl_int length = 512;
cl_program program;
FILE *program_handle;
char *program_buffer;
size_t program_size;
cl_kernel kernel;
size_t work_units_per_kernel;
float mat_a[length], mat_b[length];
cl_mem mat_a_buff, mat_b_buff, res_buff;
cl_event timing_event;
cl_ulong time_start, time_end , read_time;

//********************************************************************
//           making matrix a & b

for(i=0; i<length; i++) {
mat_a[i] = i ;
mat_b[i] = i +1;
}
//********************************************************************

clGetPlatformIDs(2, &platform, NULL);
clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1 , &device, NULL);
context = clCreateContext(NULL, 1, &device, NULL,NULL, &err);
program_handle = fopen(PROGRAM_FILE, "r");
fseek(program_handle, 0, SEEK_END);
program_size = ftell(program_handle);
rewind(program_handle);
program_buffer = (char*)malloc(program_size + 1);
program_buffer[program_size] = '\0';

//*******************************************************************
// !!!!!!!!!   reading buffer  :    
fread(program_buffer, sizeof(char), program_size,program_handle);
//*******************************************************************   
fclose(program_handle);
program = clCreateProgramWithSource(context, 1,(const char**)&program_buffer,&program_size,&err);
free(program_buffer);

clBuildProgram(program, 0 , NULL , NULL , NULL , NULL);

// !!!    Creating & Queueing Kernel  :
//*********************************************************************************

kernel = clCreateKernel(program , KERNEL_FUNC , &err);
queue = clCreateCommandQueue(context, device , CL_QUEUE_PROFILING_ENABLE , &err);

//*********************************************************************************
mat_a_buff = clCreateBuffer(context, CL_MEM_READ_ONLY |CL_MEM_COPY_HOST_PTR,
sizeof(float)*4,  mat_a, &err);
mat_b_buff = clCreateBuffer(context, CL_MEM_READ_ONLY |CL_MEM_COPY_HOST_PTR,
sizeof(float)*4 , mat_b, &err);
res_buff = clCreateBuffer(context, CL_MEM_WRITE_ONLY,sizeof(float)*4, NULL, &err);

// !!!   Setting Kernel Arguments   :   


clSetKernelArg(kernel, 0, sizeof(cl_mem), &mat_a_buff);
clSetKernelArg(kernel, 0, sizeof(cl_mem), &mat_b_buff);
clSetKernelArg(kernel, 1, sizeof(cl_mem), &res_buff);


work_units_per_kernel = 512;

//   !!!  Parallelism with clEnqueueNDRangekernel structure 
//**********************************************************************************************    
clEnqueueNDRangeKernel(queue, kernel, 1, NULL,&work_units_per_kernel,
NULL, 0, NULL, &timing_event);
//**********************************************************************************************    

//********************  Profilling :  *****************************

clGetEventProfilingInfo(timing_event, CL_PROFILING_COMMAND_START,
sizeof(time_start), &time_start, NULL);
clGetEventProfilingInfo(timing_event, CL_PROFILING_COMMAND_END,
sizeof(time_end), &time_end, NULL);
read_time = time_end - time_start;
printf("The average time is :  %lu\n", read_time);                  
//********************************************************************************************* 
clReleaseMemObject(mat_a_buff);
clReleaseMemObject(mat_b_buff);
clReleaseMemObject(res_buff);
clReleaseKernel(kernel);
clReleaseCommandQueue(queue);
clReleaseProgram(program);
clReleaseContext(context);
return 0;
}   

但是虽然 cl_ulong 是 unsigned long ,但带有 %lu 标志的 printf 不会起作用。这是错误代码行: (格式 %lu 需要 long unsigned int 类型的参数,但参数 2 的类型为 cl_ulong[-Wformat])

所以我不知道是什么问题以及为什么 printf 不能正常工作???

【问题讨论】:

    标签: printf opencl


    【解决方案1】:

    AFAIK,OpenCL 规范,但没有为它的整数类型定义 printf 格式说明符,但它 actually prescribes cl_ulong 是 64 位整数。这可能与 C 类型 unsigned long 不匹配,C 标准没有强制要求它那么宽,可能只是 32 位。但unsigned long long 保证能够容纳 64 位整数。

    所以,我建议你:

    • cl_ulong 转换为unsigned long long 并使用%llu,或者;
    • cl_ulong 转换为uint64_t 并使用PRIo64 格式说明符。

    Bot unsigned long longuint64_t 是由 C99 引入的,因此在可移植性上没有太大区别。在这两种情况下,转换都应该是无损的,并且可能只会扩大价值。

    用法如下:

    printf("The average time is: %llu\n", (unsigned long long)read_time); 
    

    或以下:

    #include <inttypes.h>
    printf("The average time is: %"PRIu64"\n", (uint64_t)read_time); 
    

    【讨论】:

      【解决方案2】:

      作为提到的其他答案之一,sizes of OpenCL scalar data types 是恒定位数:

      DATA TYPE            | BITS
      ===========================
      cl_char  / cl_uchar  |    8
      cl_short / cl_ushort |   16
      cl_int   / cl_uint   |   32
      cl_long  / cl_ulong  |   64
      

      但是,由于您在给定系统上can't assume the size of a long,因此使用%llu%lu不正确


      也就是说,C 和 C++ 有 inttypes.h header,它定义了用于打印固定大小整数值的宏。
      printing 宏的格式为 PRI[format][size]:

      • [format] 是以下之一:d - 有符号,u - 无符号,o - 八进制,x - 十六进制
      • [size] 是以位为单位的整数大小(8163264

      例如:PRIu64 用于打印 64 位无符号整数,PRIx32 用于打印 32 位十六进制整数。

      注意:这些宏只定义printf 变量的“说明符”部分,而不是% 标记。
      当你在程序中使用它们时,它需要看起来像printf("X = %" PRIu32 "\n", x);


      综上所述,我们最终得到以下结果:

      DATA TYPE  | FORMAT
      ===================
      cl_char    | PRId8
      cl_uchar   | PRIu8
      cl_short   | PRId16
      cl_ushort  | PRIu16
      cl_int     | PRId32
      cl_uint    | PRIu32
      cl_long    | PRId64
      cl_ulong   | PRIu64
      

      当然,如果您希望以八进制打印整数,您可以使用o 而不是du
      同样,如果您想要十六进制整数,您可以使用x

      【讨论】:

      • “但是,由于在给定系统上不能假设 long 的大小,因此使用 %llu 或 %lu 是不正确的。” — 确实,您不能依赖 unsigned long 至少为 64 位宽,但 unsigned long long 并非如此。请参阅C11 draft,“5.2.4.2.1 整数类型的大小 ”部分。
      【解决方案3】:

      如果这是 64 位类型,请尝试 %lld (long long)。

      【讨论】:

        【解决方案4】:

        在我机器上安装的 cl_platform.h 头文件中,我发现 cl_ulong 定义为:

        typedef uint64_t  cl_ulong;
        

        所以我想你可以按照here 的建议尝试 printf。

        顺便说一句,我不知道您是否将编译指示用于代码中的其他内容,但您在这里使用的 printf 是常规的 C 语言,因为它是主机端代码。因此,在这种特定情况下不需要编译指示。此外,从 OpenCL 1.2 开始,printf 是内置函数的一部分,使得 AMD 的扩展和 pragma 语句过时。

        【讨论】:

        • 嗨,我听你的建议,但仍然有错误消息,并且 printf 不起作用!!!
        • 有什么建议?要求您尝试链接中给出的解决方案的那个?它不起作用是什么意思?结果如何?
        • 嗨,你是对的,我知道你说什么,并尝试了解决方案,但它仍然犯同样的错误!我把错误信息再次放到页面中
        • 很遗憾,不能保证cl_ulong 总是 对应于主机的uint64_t。所以我认为你应该先将这些值转换为已知类型,然后再用于printf
        【解决方案5】:

        如果 OpenCL 的命名有意义,那么我希望 ulongunsigned long 的 typedef,因此正确的转换说明符是 %lu

        【讨论】:

        • 嗨,你是对的,ulong 是 unsigned long 的类型,但我不知道为什么 %lu 不起作用!当我使用带有这个标志的 fprint 时,它会出现这个错误:(%lu 是 unsigned long 但你在你的代码中使用 ulong 类型),现在我该怎么办?
        • @mehdioraki 查看cl_ulong 的 typedef。如果不是unsigned long,那么它的名字有误导性,你应该适当地改变格式说明符,然后狠狠地揍这个库的作者。
        • 我把我的代码放在页面上,也许你能找到错误,非常感谢
        猜你喜欢
        • 2013-06-22
        • 2018-11-22
        • 1970-01-01
        • 2020-12-04
        • 1970-01-01
        • 2017-11-16
        • 2012-05-17
        • 2012-05-17
        • 1970-01-01
        相关资源
        最近更新 更多