In my OpenCL code (which is not coded by myself, it's just an example code from internet), there is the following sentence to use the function of clamp.
return clamp(color,0,1);
However it seems that this makes error during compilation, so I got the error info message by using CL_PROGRAM_BUILD_LOG from clGetProgramBuildInfo.
Error during compilation! (-11)
4483
build log
:211:9: error: call to 'clamp' is ambiguous
return clamp(color,0,1);
^~~~~
<built-in>:3558:26: note: candidate function
float4 __OVERLOADABLE__ clamp(float4 x, float min, float max) ;
^
<built-in>:3577:25: note: candidate function
float4 __OVERLOADABLE__ clamp(float4, float4, float4);
^
<built-in>:3556:26: note: candidate function
float3 __OVERLOADABLE__ clamp(float3 x, float min, float max) ;
^
<built-in>:3575:25: note: candidate function
float3 __OVERLOADABLE__ clamp(float3, float3, float3);
^
:296:52: error: address expression must be an lvalue or a function designator
r.origin = matrixVectorMultiply(viewTransform, &(float3)(0, 0, -1));
^~~~~~~~~~~~~~~~~~
:297:62: error: address expression must be an lvalue or a function designator
r.dir = normalize(matrixVectorMultiply(viewTransform, &(float3)(x, y, 0)) - r.origin);
^~~~~~~~~~~~~~~~~
Is there any necessary keyword for using clamp function in OpenCL code? BTW, I'm using the environment of the Linux Ubuntu 10.04 64bit.
Try the following
return clamp(color,0.0f,1.0f);
This way we know for sure that 2nd and 3rd params are not ambiguous and that you are trying to call the function:
clamp(float4 color, float min, float max);
If this doesn't work, then see your color param, but the 2nd and 3rd param should be fine now.
There are several overloaded clamp builtin functions in OpenCL; the compiler needs to select exactly one, based on the types of the arguments. Valid combinations are
T clamp(T,T,T) and T clamp(T,S,S)
where T is one of the OpenCL integral or floating point types, and S is the scalar type of an element of T when T is a vector type.
It would appear that your sample code was illegally mixing float and integer arguments to the call. The constants 1 and 0 are of type int, unlike 0.0f and 1.0f which are of type float.
See the quick reference card for more details.
I am getting the same problems on the same piece of code (http://www.gamedev.net/blog/1241/entry-2254210-realtime-raytracing-with-opencl-ii/). It is written poorly and managed to hang my pc.
The clamp() problem is indeed fixed by making sure that the last two arguments are floats.
The matrixVectorMultiply() problem is fixed by changing the signature of that function. It originally is:
float3 matrixVectorMultiply(__global float* matrix, float3* vector){
float3 result;
result.x = matrix[0]*((*vector).x)+matrix[4]*((*vector).y)+matrix[8]*((*vector).z)+matrix[12];
result.y = matrix[1]*((*vector).x)+matrix[5]*((*vector).y)+matrix[9]*((*vector).z)+matrix[13];
result.z = matrix[2]*((*vector).x)+matrix[6]*((*vector).y)+matrix[10]*((*vector).z)+matrix[14];
return result;
}
However there is absolutely no reason for vector to be a pointer, so you can remove the * before every occurrence of vector.
Then the code should compile, but the program probably still crashes.
Probably not your issue, but worth noting: Between OpenCL 1.0 and 1.1 clamp changed slightly, so if you are not careful you can have code that compiles in one version and not the other. Specifically, in the OpenCL 1.1 specification, "Appendix F – Changes", "F.1 Summary of changes from OpenCL 1.0" it says "The following features are added to the OpenCL C programming language (section 6):", then "New built-in functions", then "clamp integer function defined in section 6.11.3"
So you're best off fully qualifying your parameters.
Related to this, in OpenCL 1.1 added (vector, scalar) variant of integer functions min and max, so don't use those in 1.0 (cast the scalar parameters to vectors instead).
Related
I am building a C++ program to verify a mathematical conjecture for up to 100 billion iterations. In order to test such high numbers, I cannot use a C++ int, so I am using the NTL library, using the type ZZ as my number type.
My algorithm looks like this:
ZZ generateNthSeq(ZZ n)
{
return floor(n*sqrt(2));
}
I have the two libraries being imported:
#include <cmath>
#include <NTL/ZZ.h>
But obviously this cannot compile because I get the error:
$ g++ deepness*.cpp
deepness.cpp: In function ‘NTL::ZZ generateNthSeq(NTL::ZZ)’:
deepness.cpp:41: error: no matching function for call to ‘floor(NTL::ZZ)’
/usr/include/bits/mathcalls.h:185: note: candidates are: double floor(double)
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/cmath:262: note: long double std::floor(long double)
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/cmath:258: note: float std::floor(float)
Stating that the floor mathematical operation cannot accept a ZZ class type. But I need the numbers to be pretty big. How can I accomplish what I want to do, which is to floor the function, while using the NTL library?
Note that it doesn't really make sense to apply floor to an integral type (well, it does, it's just a no-op). What you should be really worried about is the fact that your code is apparently passing something of type ZZ into floor!
That is, what can n * sqrt(2) possibly mean here?
Also, before even writing that, I'd've checked the documentation to see if integer * floating point actually exists in the library -- usually for that to be useful at all, you need arbitrary precision floating types available.
Checking through the headers, there is only one multiplication operator:
ZZ operator*(const ZZ& a, const ZZ& b);
and there is a conversion constructor:
explicit ZZ(long a); // promotion constructor
I can't figure out how your code is even compiling. Maybe you're using a different version of the library than I'm looking at, and the conversion constructor is implicit, and your double is getting "promoted" to a ZZ. This is surely not what you want, since promoting sqrt(2) to a ZZ is simply going to give you the integer 1.
You either need to:
look into whether or not NTL has arbitrary precision floating point capabilities
switch to a library that does have arbitrary precision floating point capabilities
convert your calculation to pure integer arithmetic
That last one is fairly easy here: you want
return SqrRoot(sqr(n) * 2); // sqr(n) will be a bit more efficient than `n * n`
I am writing a C++ program using Xcode, and I need to find the max and min of two numbers. I decided to use the built-in max and min functions of C++.
When I do :
float result = min(x1,x2); // x1, x2 are floats
Xcode recognises min just fine.
But when I do:
float result = max(x1,x2); // x1, x2 are floats
Xcode complains with the error:
No matching function for call to 'max'
If I COMMAND + Click on either max or min, the Xcode quickly takes me to the function definitions, so clearly Xcode knows they are both there.
How do I get max to work ?
EDIT: I have tried calling std::max, but I get the same error.
This type of error occur generally when your parameters that you are passing to min or max function is not of same type.
Make sure to check the parameter type of both parameters.
I'm trying to compile old Qt project and i encounter this error:
error: cannot convert 'float*' to 'qreal* {aka double*}' in
initialization
Here's the fragment of code:
void Camera::loadProjectionMatrix()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
qreal *dataMat = projectionMatrix_.data();
GLfloat matriceArray[16];
for (int i= 0; i < 16; ++i)
matriceArray[i] = dataMat[i];
glMultMatrixf(matriceArray);
}
What are my options to overcome this error?
The projection matrix will return float* to you as per documentation:
float * QMatrix4x4::data()
Returns a pointer to the raw data of this matrix.
The best practice would be to eliminate the qreal usage in your codebase regardless this case. When the contributors went through the Qt 5 refactoring, the qreal ancient concept was dropped as much as possible and definitely should not be used much in new code where the API deals with float.
The recommendation is to use float these days in such cases. This is a bit historical, really. Back then, it made sense to define qreal to double where available, but float where not, e.g. ARM platforms. See the old documentation:
typedef qreal
Typedef for double on all platforms except for those using CPUs with ARM architectures. On ARM-based platforms, qreal is a typedef for float for performance reasons.
In Qt 5, the documentation is slightly different, although the main concept seems to have remained the same:
typedef qreal
Typedef for double unless Qt is configured with the -qreal float option.
I would fix your code the following way:
void Camera::loadProjectionMatrix()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float *dataMat = projectionMatrix_.data();
GLfloat matriceArray[16];
for (int i= 0; i < 16; ++i)
matriceArray[i] = dataMat[i];
glMultMatrixf(matriceArray);
}
Strictly speaking, you could also go an alternative way to solve the issue, namely by using this method rather than data():
float & QMatrix4x4::operator()(int row, int column)
Returns a reference to the element at position (row, column) in this matrix so that the element can be assigned to.
In which case, you could even eliminate the dataMat variable and assign the items directly to your matriceArray in the iteration.
Going even further than that, you should consider using a Qt library for this common task, namely e.g. the opengl classes either in QtGui or Qt3D. It would make more sense to mess with low-level opengl API calls if you do something custom.
Apparently, projectionMatrix_.data() returns a float*, and you cannot assign a float* to a double* (which is what qreal* is in this case).
Use
float *dataMat = projectionMatrix_.data();
or
auto dataMat = projectionMatrix_.data();
instead. The latter sometimes has the advantage that it might still be correct code if the return type of the function changes for some reason, although that is nothing to expect from a mature library. Additionally, you cannot get the type wrong on accident.
I'm trying to sort an array of structs on my GPU with thrust::sort. However, when I compile with nvcc, I get this warning:
ptxas /tmp/tmpxft_00005186_00000000-5_antsim.ptx, line 1520; warning : Double is not supported. Demoting to float
I've isolated the problem to my call to thrust::sort, here:
thrust::sort(thrustAnts, thrustAnts + NUM_ANTS, antSortByX());
thrustAnts is an array of Ant structs located on the GPU, while antSortByX is a functor as defined below:
typedef struct {
float posX;
float posY;
float direction;
float speed;
u_char life;
u_char carrying;
curandState rngState;
} Ant;
struct antSortByX {
__host__ __device__ bool operator()(Ant &antOne, Ant &antTwo) {
return antOne.posX < antTwo.posX;
}
};
It seems to me as though there aren't any doubles in this, though I'm suspicious the less-than operator in my functor evaluates those floats as doubles. I can solve this problem by compiling with -arch sm_13, but I'm curious as to why this is complaining at me in the first place.
The demotion happens because CUDA devices support double precision calculations at first with compute capability 1.3. NVCC knows the specifications and demotes every double to float for devices with CC < 1.3 just because the hardware cannot handle double precisions.
A good feature list could be found on wikipedia: CUDA
That you can’t see any doubles in this code doesn't mean that they are not there. Most commonly this error results from a missing f postfix on a floating point constant. The compiler performance an implicit cast from all floats to double when one double is part of the expression. A floating point constant without the f is a double value and the casting starts. However, for the less-operator a cast without constant expressions should not happen.
I can only speculate, but it seems to me that in your case a double precision value could be used within the thrust::sort implementation. Since you provide only a user function to a higher order function (functions that take functions as parameters).
I am using Netbeans with gcc for this, and I find that the value of the function arguments are being corrupted between the calling function and the called function.
In myfuns.h:
float dotprod( float u1, float u2, float u3, float v1, float v2, float v3 );
In myfuns.c
float dotprod( float u1, float u2, float u3, float v1, float v2, float v3 )
{
float res= u1*v1+u2*v2+u3*v3 ;
return res;
}
In main.c
...
float dp=dotprod( rx, ry, rz, ddx, ddy, ddz );
...
If I print the values of u1,u2 etc in the dotprod() function, or examine them with the
debugger, the values are different to the values of rx,ry etc in main.c
If I convert the arguments from float to float*, the problem seems to go away. I also
tried adding a dummy integer argument before and after the 6 float arguments, the first one is OK but the last one also get corrupted. I have spent hours trying to spot the error.
Any suggestions ?
Are the types for all those variable in main() specified as float?
Is the prototype for dotprod() visible when you call it? In other words, does your main file have #include "myfuns.h"?
In particular, answering no for that second question means that the compiler will make certain assumptions about the arguments being passed that makes the value a different width, or interpret them in a different way.
For example, consider:
#include <stdio.h>
int main(int argc, char *argv[]) {
float x = 1.5, y = 2.5;
fn (x, y); // <-- compiler makes assumptions.
return 0;
}
void fn (float a, float b) { // <-- compiler should complain
printf ("%f %f\n", a, b); // about bad assumptions.
}
which outputs:
0.000000 1.937500
That's really not what you would expect. This was compiled with gcc and the slew of warnings that were spat out should have been reason enough to go back and check the code (a).
In this particular case, my int and float types are the same width (32 bits) but, because the compiler thinks the function accepts int, it will convert those floats to that type first. Unfortunately, when the function looks at those int values on the stack, it interprets them as float types, which are encoded quite differently.
It can be even worse if your expected and actual types are different widths, since you may find you try to use more data than what was put on the stack.
This particular code sample can be fixed simply by inserting:
void fn (float, float);
before main() (or swapping main() and fn() around) so that the prototype is not assumed. This results in no warnings from gcc and the correct output:
1.500000 2.500000
Basically, you have to ensure that the caller and callee agree on the parameters passed. That includes such things as calling convention, data types and parameter counts, among other things. A mismatch in any of these will cause you problems.
(a): Such as the following, on my system:
testprog.c: In function ‘main’:
testprog.c:5: warning: implicit declaration of function ‘fn’
testprog.c: At top level:
testprog.c:9: warning: conflicting types for ‘fn’
testprog.c:5: note: previous implicit declaration of ‘fn’ was here
Make sure you are passing the same type of data with the function parameter, i.e. the size and represent.
For a very simple test, try this in main:
float dp=dotprod( (float)rx, (float)ry, (float)rz, (float)ddx, (float)ddy, (float)ddz );