4

@H2CO3

this is my main code :

#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;
}   

but although the cl_ulong is the unsigned long , the printf with %lu flag does not act . this is the error code line : (format %lu expects argument of type long unsigned int but argument 2 has type cl_ulong[-Wformat])

so i don't know what is the problem and why printf does't work properly ???

mehdi oraki
  • 49
  • 2
  • 6

5 Answers5

3

On the cl_platform.h header installed on my machine, i found that cl_ulong is define as:

typedef uint64_t  cl_ulong;

So I guess you could try to printf as suggested here.

BTW, I don't know if you use the pragma for something else in your code, but the printf you are using here is the regular C one since it is the host side code. So no need for the pragma in this specific case. Moreover since OpenCL 1.2, the printf is part of the built-in functions making obsolete the extension from AMD and therefore the pragma statement.

Community
  • 1
  • 1
CaptainObvious
  • 2,525
  • 20
  • 26
  • hi, i do your advise but there is still the error message , and printf doesn't work !!! – mehdi oraki Jun 26 '13 at 15:15
  • Which advice? The one asking you to try the solution given in the link? What does it mean it doesn't work? What is the result? – CaptainObvious Jun 26 '13 at 17:27
  • hi , you are right, i know what you saied ,& tried the solution , but it still make the same error !!! i put the error message in the page again – mehdi oraki Jun 26 '13 at 17:41
  • http://stackoverflow.com/questions/17326819/printf-makes-error-and-dont-show-the-result – mehdi oraki Jun 26 '13 at 17:43
  • Unfortunately, it's not guaranteed that `cl_ulong` *always* corresponds to host's `uint64_t`. So I think you should cast those values to a known type first before using in `printf`. – firegurafiku Oct 04 '16 at 10:47
3

AFAIK, OpenCL specification but doesn't define printf format specifiers for it's integer types, but it actually prescribes cl_ulong to be 64-bit integer. This may not match with C type unsigned long which isn't forced by C standard to be that wide and may be just 32-bit. But unsigned long long is guaranteed to being able to hold 64-bit integer.

So, I'd suggest you to either:

  • cast cl_ulong to unsigned long long and use %llu, or;
  • cast cl_ulong to uint64_t and use PRIo64 format specifier.

Bot unsigned long long and uint64_t were introduced by C99, so there're no major difference in portability. In both cases the conversion should be lossless and may only widen value.

Usage is as following:

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

or following:

#include <inttypes.h>
printf("The average time is: %"PRIu64"\n", (uint64_t)read_time); 
firegurafiku
  • 3,017
  • 1
  • 28
  • 37
1

If the nomenclature of OpenCL makes sense, then I'd expect ulong to be a typedef for unsigned long, hence the correct conversion specifier would be %lu.

  • hi , you are right , ulong is the type for unsigned long , but i dont know why %lu does't work !!! when i use fprint with this flag it make this error : (%lu is for unsigned long but you use ulong type in yor code), now what should i do ? – mehdi oraki Jun 26 '13 at 05:33
  • @mehdioraki Have a look at the typedef for `cl_ulong`. If it's not `unsigned long`, then its name is misleading, you should change the format specifier appropriately, and beat the writer of the library with a thick and heavy stick. –  Jun 26 '13 at 05:37
  • i put my code on the page , perhaps u can find the error , thank soo much – mehdi oraki Jun 26 '13 at 09:11
0

If this is a 64bit type, try %lld (long long).

0

As one of the other answers mentioned, the sizes of OpenCL scalar data types are a constant number of bits:

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

However, since you can't assume the size of a long on a given system, using %llu or %lu would be incorrect.


That said, C and C++ have the inttypes.h header, which defines macros for printing fixed-sized integer values.
The printing macros are in the form PRI[format][size]:

  • [format] is one of: d - signed, u - unsigned, o - octal, x - hex
  • [size] is the integer size in bits (8, 16, 32, or 64)

For example: PRIu64 is used to print a 64-bit unsigned integer and PRIx32 is used to print a 32-bit integer in hex.

Note: These macros only define the "specifier" section of a printf variable, not the % marker.
When you use them in a program, it needs to look like printf("X = %" PRIu32 "\n", x);


Putting the above together, we end up with the following:

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

Of course, if you'd rather print the integer in octal you would use o instead of d or u.
Likewise, if you wanted the integer in hex, you would use x instead.

Mr. Llama
  • 20,202
  • 2
  • 62
  • 115
  • “However, since you can't assume the size of a long on a given system, using %llu or %lu would be incorrect.” — that's true that you cannot rely on `unsigned long` being at least 64 bits wide, but that's not so for `unsigned long long`. See [C11 draft](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf), section “5.2.4.2.1 Sizes of integer types ”. – firegurafiku Mar 28 '18 at 07:43