Hello. I'm writing a program which I want to be able to switch easily between 32-bit and 64-bit floating point (i.e. float and double), and I'm finding it a bit annoying having my build-log flooded with these warnings:
double-precision constant is represented as single-precision constant because double is not enabled
This warning appears even if I use an explicit cast. So all the below produce the same warning:
float a = 0.1;
float a = (float)(0.1);
float a = as_float(0.1);
Basically, is there some way to avoid the warning, either by disabling it or by doing the casts in some way I havent thought of? It's not a major problem, but it's annoying to get all these non-interesting warnings whenever I'm compiling without double precision support enabled.
pass -w to compiler options.
Thanks for the help. -w would be a good choice when the code is finished I guess, but I don't really want to suppress all the useful warnings (like unused variables and such).
I did however find one compiler option I thought would fix it, namely -cl-single-precision-constant. However that just gives me "Warning: invalid option: -cl-single-precision-constant". The option's description in the specification is:
"Treat double precision floating-point constant as single precision constant."
So if it was supported it would probably do what I want.
I suppose something like this might work? Assuming I remember how the symbol concatenation operator in the C preprocessor works.
#if SUPPORTSDOUBLE
#define REAL double
#define REALCONST(x) (x)
#else
#define REAL float
#define REALCONST(x) (x ## f)
#endif
then declare those things as
REAL a = REALCONST(0.3);
Or, I suppose you could just write your constants as 0.1f if you want to declare the variables as floats. I'm not sure if you want one set of kernels that adapt to double or float or two sets that simply don't have the warning.
Thanks for the suggestion Illusio, that _almost_ solves it. The problem comes when the constant is an integer. REALCONST(1) gives output:
Line 12: warning:
concatenation with "f" in macro "REALCONST" does not create a valid
token
float a = REALCONST(1);
^
Line 12: error: expected a ")"
float a = REALCONST(1);
Since I'm passing these constants in as D= arguments to the compiler, the value will sometimes just be a string "1" (but in general it could be any float).
If that's the only problem it just boils down to being a string formatting issue on the host side doesn't it? If you force a specific number of decimals you'll never see those integers.
sprintf(compilerOptionString,"-D MYCONST=%5.7f", myconst);
If you add an f to the format string when you want floats you can probably just forget about the macros altogether.
Ah indeed, that let's me solve it sufficiently (though I still wish -cl-single-precision-constant would do the trick). Thanks for the help
I solved it using ostringstream like shown in the attached code, since I'm coding in C++.
cl_float a = 1; std::ostringstream oclBuildOptions; oclBuildOptions << std::fixed //Always display the specified number of digits after decimal point for floats << std::setprecision(16) //Specify number of digits after decimal point << " -D a=" << a; //Then pass oclBuildOptions.str().c_str() to program.build().
Try using the flag --single_precision_constant
--single_precision_constant works! But why? It isn't even in the specification. Is this a AMD specific flag or what?
Originally posted by: dravisher --single_precision_constant works! But why? It isn't even in the specification. Is this a AMD specific flag or what?
Apparently. The clc flags seem to be completely undocumented, and none of the ones in the specification seem to work.
I did find this at some point:
http://mahadevangorti.blogspot.com/2010/03/command-line-options-of-clcexe-ati.html
From there it's your best guess as to what each one might do.
Hello;
May I suggest you use this:
float a = 0.1f;
See, 0.1f, 0.345f, or whatever float, when cast to double precision if you are using it, doesn't change the result and should suppress the warning.
This is the most practical way I see.
Casting a float to a double can cause some significant precision problems, so using 0.1f always is not really a safe solution. Basically double a = 0.1f is much less precise than double a = 0.1 (assuming the compiler doesn't optimize away the initial cast to float, which I don't think it should). This is because 0.1 is not exactly representable as a floating point number no matter how many bits you use. Basically much of the added precision of using doubles would be lost, since 0.1f is only accurate to about 7 digits (in base 10), while plain 0.1 is accurate to about 15 digits!
My current solution is to use ostringstream and add an f to the end of the number if I'm in float-mode, and not if I'm in double-mode. Obviously this only works for numbers I pass in as define statements, so it's an imperfect solution. I would much prefer it if -cl-single-precision-constant was working as expected, hopefully it'll be implemented soon. While using --single_precision_constant works, it's non-standard and I want to keep my code as portable as possible.
whether just
float a = 0.1;
does not work, and it must be f at the end? In this case
double a = 0.1 will be fine too ...
float a = 0.1; works fine, the problem is just that it outputs a warning message in the buildlog, so I wind up with tens of warnings I don't care about, which makes it cluttered and difficult to actually find the warnings and errors I am actually interested in.
Interesting, looks like cl-single-precision-constant will make ALWAYS treat 0.1 as float, so no precision increase will happen. Is it what you want?
Yes, basically my code can run with either all floats or all doubles, and in the all floats case (which is the usual case) I want to pass the cl-single-precision argument, while in the double case I wouldn't.
so use that if it work. for development purpose portability is not a issue. just remove it for production code when it does't matter if it there a ton of warnings.
Originally posted by: dravisher --single_precision_constant works! But why? It isn't even in the specification. Is this a AMD specific flag or what?