80 likes | 150 Vues
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
E N D
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, Not Possible state Possible states ‘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 dist_h = (float*)malloc(fsize); status_h = (int*)malloc(isize); start_h = (int*)malloc(isize); end_h = (int*)malloc(isize); float R = 10.0*sqrt(2.0); int Nt = 8; Variables for inputting Radius And # of threads required for computation 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 Curvature change is not picked up because of poorer pixel resolution. Causes the circumference to be underestimated Large ‘R’ compared to pixel resolution Computed pi = 2.8567 for R=100xsqrt(2) Highly curved boundaries are not captured because of poorer pixel resolution. Causes the circumference to be overestimated Small ‘R’ compared to pixel resolution Computed pi = 3.7712for R=3xsqrt(2)
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’