4

@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 不能正常工作???

4

5 回答 5

3

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

typedef uint64_t  cl_ulong;

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

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

于 2013-06-26T09:08:01.013 回答
3

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

所以,我建议你:

  • 转换cl_ulongunsigned long long并使用%llu,或;
  • 转换cl_ulonguint64_t并使用PRIo64格式说明符。

Botunsigned 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); 
于 2016-04-02T23:16:58.477 回答
1

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

于 2013-06-26T00:44:32.030 回答
0

作为提到的其他答案之一,OpenCL 标量数据类型的大小是恒定的位数:

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

但是,由于您不能long在给定系统上假设 a 的大小,因此使用%lluor%lu将是不正确的。


也就是说,C 和 C++ 有inttypes.hheader,它定义了用于打印固定大小的整数值的宏。打印
宏 的格式为: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

当然,如果您宁愿以八进制打印整数,则可以使用oro代替。 同样,如果您想要十六进制的整数,则可以改用。du
x

于 2017-12-01T17:33:57.650 回答
-1

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

于 2013-09-17T20:53:09.990 回答