How should I enable cl_khr_fp64 in OpenCL? - double

I'm trying to get double precision to work in my OpenCL kernel but I'm having problems enabling cl_khr_fp64. If I put #pragma OPENCL EXTENSION cl_khr_fp64 : enable at the top of my kernel file and define a variable double u = 5.0; then it defines it and allows me to +-*/ on u. But if I try to do any math functions, for example double u = exp(5.0); it throws an error that it can't find the overloaded exp function for type double. Something weird I found is that if I check if cl_khr_fp64 is defined via
#ifdef cl_khr_fp64
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#elif defined(cl_amd_fp64)
#pragma OPENCL EXTENSION cl_amd_fp64 : enable
#else
#error "Double precision floating point not supported by OpenCL implementation."
#endif
Then it throws the error that double precision isn't supported. If I just say to enable it then it gets enabled, but if I check to see if it is able to be enabled, then it says it can't.
I've checked the extensions on my card and cl_khr_fp64 is listed and I also checked the CL_DEVICE_DOUBLE_FP_CONFIG using clGetDeviceInfo and it returns 63. I'm using a MacPro on Yosemite with the AMD FirePro D700. I'm wondering if I enabled cl_khr_fp64 in the wrong place or something. The contents of my mykernel.cl file are below. It's just a modification of the Apple 'hello_world' OpenCL Xcode project. The code, as written works just fine, but if I change the line from double u = (5.0); to double u = exp(5.0); it doesn't work. Ultimately I want to use math functions on double variables. Any help would be greatly appreciated!
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
__kernel void square5(global double* input, global double* output, double mul,int nv)
{
size_t i = get_global_id(0);
double u = (5.0);
float left = u/1.2;
if(i==0) {
output[i] = mul*pow((float)u,left)*input[i]*input[i];
} else if (i==nv-1) {
output[i] = mul*u*input[i]*input[i];
} else {
output[i] = 0.25*mul*u*(input[i-1] + input[i+1])*(input[i-1] + input[i+1]);
}
}

Double precision was made a core-optional feature in OpenCL 1.2 (which should be the version that your device supports under OS X). This means that you shouldn't need to enable the extension in order to use it, if it is supported by the device. Enabling the extension shouldn't have any negative effect however.
You are not doing anything wrong, so this is likely a bug in Apple's OpenCL implementation. The same code (with the exp() function) compiles fine on my Macbook for the devices that support double precision. So, if your device definitely reports that it supports double precision, then you should file a bug in Apple's Bug Reporting System.

Related

What is CGFloat.leastNonzeroMagnitude equivalent in Obj-C

What is the equivalent of CGFloat.leastNonzeroMagnitude equivalent in Objective-C?
I googled but could not find any answer.
Note that the documentation of leastNonzeroMagnitude says:
Compares less than or equal to all positive numbers, but greater than zero. If the target supports subnormal values, this is smaller than leastNormalMagnitude; otherwise they are equal.
So the value of this also depends on "if the target supports subnormal values". Looking at the implementation, we can see:
public static var leastNonzeroMagnitude: ${Self} {
#if arch(arm)
// On 32b arm, the default FPCR has subnormals flushed to zero.
return leastNormalMagnitude
#else
return leastNormalMagnitude * ulpOfOne
#endif
}
It turns out that ARM is the target that doesn't "support subnormal values". :)
If you translate the two branches into Objective-C separately, it would be:
CGFLOAT_MIN
and
CGFLOAT_MIN * CGFLOAT_EPSILON
Apple doesn't provide an Objective-C constant equivalent to CGFloat.leastNonzeroMagnitude.
Apple does provide CGFLOAT_MIN, which is the smallest positive normal nonzero value. It's equivalent to CGFloat.leastNormalMagnitude. This is 2.225073858507201e-308 on systems with 64-bit CGFloat.
There are constants (specified by the C11 standard) for the smallest positive non-zero float and double, including subnormals: FLT_TRUE_MIN is 1.401298e-45 and DBL_TRUE_MIN is 4.940656458412465e-324.
Apple provides a constant CGFLOAT_IS_DOUBLE which is 1 if CGFloat is double and zero if it is float. So you can check that to define your own CGFLOAT_TRUE_MIN. You should also guard against Apple adding its own definition in the future.
#ifndef CGFLOAT_TRUE_MIN
#if CGFLOAT_IS_DOUBLE
#define CGFLOAT_TRUE_MIN DBL_TRUE_MIN
#else
#define CGFLOAT_TRUE_MIN FLT_TRUE_MIN
#endif
#endif
But the only supported platform that still uses 32-bit CGFloat is watchOS, and its unlikely that you're targeting watchOS if you're using Objective-C. If you are only targeting 64-bit versions of iOS/macOS/tvOS, you can simplify the definition:
#ifndef CGFLOAT_TRUE_MIN
#define CGFLOAT_TRUE_MIN DBL_TRUE_MIN
#endif

Error "Cast from pointer to smaller type 'int' loses information" in EAGLView.mm when update Xcode to 5.1 (5B130a)

Yesterday, I updated Xcode to the newest version (5.1 (5B130a)) to compatible with iOS 7.1. Then I build my project, I get the error "Cast from pointer to smaller type 'int' loses information" in EAGLView.mm file (line 408) when 64-bit simulators (e.g.: iPhone Retina 4-inch 64-bit) is selected.
I'm using cocos2d-x-2.2.2. Before I update Xcode, my project still can build and run normally with all devices.
Thanks for all recommendation.
Update: Today, i download the latest version of cocos2d-x (cocos2d-x 2.2.3). But the problem has still happened.
Here is some piece of code where that error occur:
/cocos2d-x-2.2.2/cocos2dx/platform/ios/EAGLView.mm:408:18: Cast from pointer to smaller type 'int' loses information
// Pass the touches to the superview
#pragma mark EAGLView - Touch Delegate
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (isKeyboardShown_)
{
[self handleTouchesAfterKeyboardShow];
return;
}
int ids[IOS_MAX_TOUCHES_COUNT] = {0};
float xs[IOS_MAX_TOUCHES_COUNT] = {0.0f};
float ys[IOS_MAX_TOUCHES_COUNT] = {0.0f};
int i = 0;
for (UITouch *touch in touches) {
ids[i] = (int)touch; // error occur here
xs[i] = [touch locationInView: [touch view]].x * view.contentScaleFactor;;
ys[i] = [touch locationInView: [touch view]].y * view.contentScaleFactor;;
++i;
}
cocos2d::CCEGLView::sharedOpenGLView()->handleTouchesBegin(i, ids, xs, ys);
}
Apparently the clang version in Xcode 5.1 and above is more strict about potential 32bit vs. 64 bit incompatibilities in source code than older clang versions have been.
To be honest, I think, clang is too restrictive here. A sane compiler may throw a warning on lines like this but by no way it should throw an error, because this code is NOT wrong, it is just potentially error-prone, but can be perfectly valid.
The original code is
ids[i] = (int)touch;
with ids being an array of ints and touch being a pointer.
In a 64bit build a pointer is 64bit (contrary to a 32bit build, where it is 32bit), while an int is 32bit, so this assignment stores a 64bit value in a 32bit storage, which may result in a loss of information.
Therefore it is perfectly valid for the compiler to throw an error for a line like
ids[i] = touch;
However the actual code in question contains an explicit c-style cast to int. This explicit cast clearly tells the compiler "Shut up, I know that this code does not look correct, but I do know what I am doing".
So the compiler is very picky here and the correct solution to make the code compile again and still let it show the exact same behavior like in Xcode 5.0 is to first cast to an integer type with a size that matches the one of a pointer and to then do a second cast to the int that we actually want:
ids[i] = (int)(size_t)touch;
I am using size_t here, because it is always having the same size as a pointer, no matter the platform. A long long would not work for 32bit systems and a long would not work for 64 bit Windows (while 64bit Unix and Unix-like systems like OS X use the LP64 data model, in which a long is 64bit, 64bit Windows uses the LLP64 data model, in which a long has a size of 32bit (http://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models)).
I meet this problem too.
ids[i] = (int)touch; // error occur here => I change this to below.
ids[i] = (uintptr_t)touch;
Then i can continue compiling. Maybe you can try this too.
XCode 5.1 is change all architecture to 64 bit.
you can just change architecture to support 32 bit compilation by all below in in Build Settings
use $(ARCHS_STANDARD_32_BIT) at Architecture instead of $(ARCHS_STANDARD)
remove arm64 at Valid Architectures
Hope it helps.
You can fix this error by replacing this line of code.
ids[i] = (uint64_t)touch;
You should perform type conversion based on 64bit build system because the type "int" supports only -32768 ~ 32768.
Surely the solution is to change the type of ids from int to type that is sufficiently large to hold a pointer.
I'm unfamiliar with XCode, but the solution should be something like follows:
Change the declaration of ids to:
intptr_t ids[IOS_MAX_TOUCHES_COUNT];
and the line producing the error to:
ids[i] = (intptr_t)touch;
Most of the "solutions" above can lose part of the pointer address when casting to a smaller type. If the value is ever used as pointer again that will prove to be an extremely bad idea.
ids[i] = (int)touch; put * and check it.
ids[i] = *(int *)touch;

Unsequenced modification and access to parameter

I'm using open source project (NSBKeyframeAnimation) for some of animations in my p roject. Here are example of methods that i'm using:
double NSBKeyframeAnimationFunctionEaseInQuad(double t,double b, double c, double d)
{
return c*(t/=d)*t + b;
}
I have updated my Xcode to 5.0, and every method from this project started to show me warnings like this: "Unsequenced modification and access to 't' ". Should i rewrite all methods to objective-c or there's another approach to get rid of all these warnings?
The behavior of the expression c*(t/=d)*t + b is undefined, and you should fix it,
e.g. to
t /= d;
return c*t*t + b;
See for example Undefined behavior and sequence points for a detailed explanation.
those warnings can be disabled
put this before the code triggering the warning
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsequenced"
and this after that code
#pragma clang diagnostic pop
however, nothing guarantees that compilers will always handle this case gracefully.
i came to this page because i got 50 of those warnings, in exactly the same source file.
i'm grateful for those functions, but the programmer should realize that trying to write everything on one line is very "1980's", when the compilers weren't nearly as optimized as today.
and when it actually matter to win a few processor cycles, we only had a few million, not the billions we have now.
i would always put readability first.
The error you are referring to appears in all versions of Xcode, seeing as it is not Xcode that is the source of the warning, but the programmer; and, it is not Xcode that generates the warning, it is the GCC compiler it uses to debug your code that is responsible for identifying the potential issue the warning raises.
While it may be that rewriting the expression will resolve the error, you do not have to do that in this case (or, technically, any other case like this). You can leave it as is.
The answer is to add sequence (or order) to the modification of the variable (i.e., to the assignment of a new value) and to its expression (i.e., to the return of its new value), and that only takes a few extra characters to achieve, namely, a pair of braces ensconced in parentheses and a semicolon (see Statements and Declarations in Expressions).
double NSBKeyframeAnimationFunctionEaseInQuad(double t,double b, double c, double d)
{
return c*({(t/=d);})*t + b;
}
Here are before-and-after screenshots that demonstrate the solution:

Simulink generate code with unsupported istruction (ceil)

Generating code by Simulink (Matlab R2011A on MacOS 64bit)
I got a problem: it uses ceil function inside the code, but it isn't supported on my target platform.
I'm generating using ERT, for Arm Cortex processor (on a Cypress PSoC).
Is it possible to solve this problem?
I tried the solution without success.
Also in Code Generation - Interface, I tried to disable floating-point or not-finite numbers... but in this way every signal of my project raises some errors (same behaviour also changing it data-type).
Really thanks to anyone suggests me what I can try to do
You could write your own ceil function and include it in whatever your output code is for your target device. Assuming you are generating C-code, the function would look something like:
int ceil (double number) {
if (number == 0)
return 0;
if (number > 0) {
if (number - (int) number > 0)
return (int) number + 1;
else
return (int) number;
}
else {
if (number - (int) number < 0)
return (int) number - 1;
else
return (int) number;
}
}
With a prototype in your header file like:
int ceil (double);
Now your C-code can call integerValuedNumber = ceil(doubleValuedNumber) and it should work. You can also do this with macros in the C-file (see nintendo's answer).
EDIT: I corrected my code to use proper type casting syntax for C. Basically what you are doing with the (int) number syntax is taking the double-valued number variable and forcing it to be an integer. You can find more information about data types in C here, or Google "type casting C" or "data types C" for more information.
Also, some additional parenthesis might be needed, like return ((int) number) + 1; and similar. I am a little rusty on my C-programming, but hopefully this gets you going toward a viable solution.
EDIT 2: I corrected the return data type of our self-defined ceil function. You would want this to return an int, or maybe long. Again, check out documentation on data types in C if you are not sure what data type is appropriate for your application. If the values you are applying ceil to are not very large (less than +/- 2^15 for instance) then int is probably fine.
Ok... I solved.
The problem was in the destination environment (PSoC Creator).
As explained here http://www.cypress.com/?id=4&rID=42838 :
Go to Project -> Build Settings -> Linker -> General -> Additional Libraries. Type m in the Additional Libraries field.
If you are not adding this Additional Library then you will get the following Build error "undefined reference to `sqrt'" where sqrt is a math function.
Nothing changes if the problem is with sqrt() or ceil(), because they are in the same library (math.h).
PS: thank you Engineero... your solution is very useful, and can be apprecied from other people with my problem (but in other environments).

Porting Issue: Pointer with offset in VC++

Ok, this compiles fine in GCC under Linux.
char * _v3_get_msg_string(void *offset, uint16_t *len) {/*{{{*/
char *s;
memcpy(len, offset, 2);
*len = ntohs(*len);
s = malloc(*len+1);
memset(s, 0, *len+1);
memcpy(s, offset+2, *len);
s[*len] = '\0';
*len+=2;
return s;
}/*}}}*/
However, I'm having a problem porting it to Windows, due to the line...
memcpy(s, offset+2, *len);
Being a void pointer, VC++ doesn't want to offset the pointer. The usual caveat that CPP doesn't allow pointer offsets SHOULD be moot, as the whole project is being built under extern "C".
Now, this is only 1 function in many, and finding the answer to this will allow them all to be fixed. I would really prefer not having to rewrite the library project from the ground up, and I don't want to build under MinGW. There has to be a way to do this that I'm missing, and not finding in Google.
Well, you cannot do pointer arithmetics with void*, it is ridiculous that this compiles under GCC. try memcpy(s, ((char*)offset)+2,*len);