Tranferring data of type floats to FPGA

I have been looking into Altera OpenCL for a little while, to improve heavy computation programs by moving the computation part to FPGA. I managed to write the code and it runs fine.
However, I have one problem. The data I’m passing from the host to the device is of float data type. So, say I pass 3.030000 from the host to buffer. But, the device gets the value 3.02999997.
Similar situation is seen when I pass 7.030000 but the device gets 7.03000021. So, basically, the decimal part changes a bit.

Is it possible to avoid this? Is it possible to make sure the device gets exactly the same number as the one passed from the host?


To be certain, have you printed out the bytes for those floats as stored in memory on the host and device to narrow down the differences? Are these single or double floats (as written they are double). The Altera SDK for OpenCL is 1.0 conformant to the embedded profile requirements, which covers single floats. Are you using cl_float or cl_double on the host side, and float or double on the device side, respectively?


No, I didn’t try that yet. How do I do that?

Actually, I’m not sure about this one. Based on the numbers I got (the ones posted in my first post), I think it is double float.

On the host side, I’m using the float data type (not cl_double or cl_float. Just float). I assumed cl_float and float are the same. My assumption may be wrong.
On the device side, I use just float as well.
Would it make a difference if cl_double or cl_float is used on the host side?

Are any other ways to fix this? Please let me know.

To print the raw bytes of a float variable, you could do something like this:

float x = 1.f;
unsigned char *y = (unsigned char *) &x;
printf("%h %h %h %h
", y[0], y[1], y[2], y[3]);

Something to keep in mind is that literal floats are in fact doubles unless specified otherwise with compiler flags, i.e.,
1.f is a single precision floating point number, and 1. is a double precision floating point number. So yes, the number you posted above would all be double, so they may or may not loose accuracy when you cast them to float (single precision floating point).

Shouldn’t be any problem with float or cl_float unless your host was a different endianness than your device. Most likely that is not your problem if you have an x86 based CPU.

Correction, the %h in the printf above should really be %x. Sorry for that lapse.

Thanks! Is there a decimal rounding function in OpenCL? I was able to find only integer rounding function. I’m looking for a function that can round off a double to a certain number of decimal places. Let me know.

No, there is not, but you could create your own iterating over the nextafter built-in function.

gentype nextafter (gentype x, gentype y)

Computes the next representable single-precision floating-point value following x in the direction of y. Thus, if y is less than x, nextafter() returns the largest representable floating-point number less than x.

Only powers of two can be exactly represented by binary floating-point formats such as float or double.

Since 3.03 or 7.03 are not powers of two, they simply cannot be exactly represented.

For example, 3.03 = 1.515x2^1, so it is represented as a float with an exponent of 1 and the (binary) significand nearest to 1.515.

The binary representation of 1.515 with the 24 bits of precision of the significand of a float is 1.10000011110101110000101(000111…). (The figures in brackets are the digits coming next in the binary development).

This significand is rounded to the nearest representable binary number which is 1.10000011110101110000101.
The floating-point value is then 1.10000011110101110000101bx2, which is approximately 3.02999997. This value differs from the exact value 3.03 by less than 1/2ulp.

The next representable value is obviously 1.10000011110101110000110bx2, which is approximately 3.03000021.