Computation of pi in CUDA

advertisement
Computation of pi in CUDA
• Measure circumference of the
circle by counting pixels on the
edge of the circle.
• Compute value of pi using this
circumference
Motivation
Say I have a digital camera and magnification system which gives me pixel size of 1 unit
on object plane
The image obtained is binary i.e. ‘1’ inside the circle and ‘0’ elsewhere.
What are my limitations in measurement of local radius of curvature ?
My hypothesis is that if I can measure circumference or compute ‘pi’. I can measure that
radius of curvature.
Algorithm
Pixel counting performed in region
0≤ x ≤ R/sqrt(2). In this region,
dy
dy
 0;
1
dx
dx
Possible states
Not Possible
state
‘d’ is the counter which keep tracks
of contour length
pi = 4 x d/R
Change ‘R’ and see the error in pi
Implementation in CUDA
The region from 0 ≤ x ≤ R/sqrt(2) is further divided into segments.
The contour length of each segment is computed independently by separate threads.
The sum of these contour lengths gives us 1/8th of the circumference of the circle.
‘pi’ value and error value are computed and outputted at the end of the program.
Some important parts of the CUDA code
float R = 10.0*sqrt(2.0);
int Nt = 8;
Variables for inputting Radius
And # of threads required for computation
dist_h = (float*)malloc(fsize);
status_h = (int*)malloc(isize);
start_h = (int*)malloc(isize);
end_h = (int*)malloc(isize);
Variables for tracking contour length,
Errors, start and end ‘x’ value for each thread
/* Kernel */
__global__ void distance(int *start, int *end, float *dist,
int *status, float R)
{ int yold = floor(0.5+(sqrt(R*R-(start[threadIdx.x]1.0)*(start[threadIdx.x]-1.0))));
int d = 0;
int flag = 0;
for (int k=start[threadIdx.x]; k <= end[threadIdx.x]; k++)
{ int ynew = floor(0.5+(sqrt(R*R-k*k)));
if (ynew == yold) { d = d + 1.0; }
else
{ if (ynew < yold) { d = d + 1.41421356; }
else { flag = 1; }
}
yold = ynew; }
dist[threadIdx.x] = d;
status[threadIdx.x] = flag;}
Kernel function
The function computes contour length
of a circular segment with radius ‘R’
Some important parts of the CUDA code
float sum = 0;
for (int i=0; i<Nt; i++)
{
sum = sum + dist_h[i];
if (status_h[i] == 1) printf("Error has occured",'\n'); }
sum = sum*4.0/R;
float error;
error = sum - 3.141592654;
printf(" value of pi = %2.15f\n ",sum);
printf(" error = %2.15f\n ",error);
Computation of ‘pi’ and the error
Printing of the values obtained
Result (for R = 10xsqrt(2))
value of pi =3.11126995
error = -0.0303227
Sources of error
Large ‘R’ compared to pixel resolution
Computed pi = 2.8567 for R=100xsqrt(2)
Small ‘R’ compared to pixel resolution
Computed pi = 3.7712 for R=3xsqrt(2)
Curvature change is not
picked up because of
poorer pixel resolution.
Causes the circumference
to be underestimated
Highly curved boundaries
are not captured because
of poorer pixel resolution.
Causes the circumference
to be overestimated
Reducing uncertainty in ‘R’ estimation
• Camera pixels record light intensity. If we can
predict the intensity distribution close to edge
and if that intensity distribution spreads over
3 or more pixels, we can possibly get subpixel
resolution.
• If R = f(x) is known, we can use that
information to reduce the uncertainty in ‘R’
Download