cancel
Showing results for 
Search instead for 
Did you mean: 

Archives Discussions

spectral
Adept II

floating point precision

Hi,

In my current kernel I use floating point values, but I think I got precision problems...

by example, I use an 'epsilon' defined as

#define EPSILON 1e-4 and play with values like 500.f etc....

I'm not sure how I can improve this ? Do you have any council ? ideas ?

0 Likes
9 Replies
himanshu_gautam
Grandmaster

hi viewon01,

I would myself be interested to find some new ideas here. Anyhow some  thought which I would like to share are:

Try using some iterations of numerical methods( like Newton raphson to improve accuracy)

Try to avoid division operation, it has the least precision among other operations.

You can also think of resorting to double if possible in your case.

0 Likes

A concrete example. I have to compute the intersection between a ray (Point,Direction) and a set of faces in 3D space.

Because it is raytracing, the "Point" is often located on a face, so, to avoid self-intersection I do the following :

P += N * epsilon;

Where P is the point, N is the normal direction and epsilon is a very small value (I use 1e-4 for now).

When I'm playing with big model, ie. coordinates like (500,500,500) I got some strange effects, playing with a smaller epsilon give me better results.

So, I decrease epsilon, but when playing with small models, (1,1,1) I have errors.

I think that I don't have this kind of problem when working in C++ on the CPU !

0 Likes

I have try to play with double, but the SDK doesn't support "double3" (as float3) ... the SDK give me compilation errors !

0 Likes

CPUs are capable of having higher precision than GPUs, so it can most certainly be true.

I think you might get better help if you post some kernel code snippet which is facing precision issues.

0 Likes

Here are some code, the problem is that epsilon is to "big" for some scenes. Smaller it is, better it is (in theory). The problem is the floating point precision !

Does the SDK has a lower precision than normal C++ ? Or there is a way (a pragma by example) to use the best precision ?

Thanks

void TriangleIntersect( clVector3 rayOrig, clVector3 rayDir, float minT, float *maxT, unsigned int *hitIndex, unsigned int currentIndex, __global Vertex *vertices, __global Triangle *tris) { // Load triangle vertices Point p0 = (vertices[tris[currentIndex].v[0]].P); Point p1 = (vertices[tris[currentIndex].v[1]].P); Point p2 = (vertices[tris[currentIndex].v[2]].P); clVector3 v0 = (clVector3) (p0.x, p0.y, p0.z); clVector3 v1 = (clVector3) (p1.x, p1.y, p1.z); clVector3 v2 = (clVector3) (p2.x, p2.y, p2.z); // Calculate intersection clVector3 e1 = v1 - v0; clVector3 e2 = v2 - v0; clVector3 s1 = cross(rayDir, e2); float divisor = dot(s1, e1); if (divisor == 0.f) return; float invDivisor = 1.f / divisor; // Compute first barycentric coordinate clVector3 d = rayOrig - v0; float b1 = dot(d, s1) * invDivisor; if (b1 < 0.f) return; // Compute second barycentric coordinate clVector3 s2 = cross(d, e1); float b2 = dot(rayDir, s2) * invDivisor; if (b2 < 0.f) return; float b0 = 1.f - b1 - b2; if (b0 < 0.f) return; // Compute _t_ to intersection point float t = dot(e2, s2) * invDivisor; if (t <= minT || t >= *maxT) return; // We have a hit *maxT = t; *hitIndex = currentIndex; } orig += EPSILON * normal; TriangleIntersect(orig, direction, minT, &maxT, &hitIndex, currentIndex, vertices, indices);

0 Likes

Reciprocal in OpenCL has accuracy of <=2.5 ULP for float. See section 7.4.

0 Likes

Thanks Jawed,

But what does it mean ?

0 Likes

What's the accuracy of the division for your reference code that runs on the CPU? What number format (float or double) are you using in C++?

If you want to use double3 on the GPU you will have to use double4 and ignore the w component.

You might want to look at other open source GPU based ray tracing (path tracing and the like) applications to see what they do about accuracy.

0 Likes