-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNearestNeighbour1.cu
142 lines (113 loc) · 3.66 KB
/
NearestNeighbour1.cu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
This program is written to find the nearest neighbour of each point in 3 deminsional
space by implementing the brute force algorithm.
The brute force approach can easily be converted into a embarassingly parallel algorithm for
the GPU where there is no interaction between the threads.
Benchmarking is done to compare the CPU and GPU computational approaches to the problem.
*/
/*
Note that there is a considerable dependency of the ratio of execution times of the CPU and GPU on the
hardware which is being used to execute the run the program.
*/
// Importing the required headers
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<cuda.h>
#include<time.h>
struct position
{
int x,y,z; //odd number of parameters in the structure helps reducing bank conflicts in shared memory(if used).
};
// Returns the duration from start to end times in sec
double time_elapsed(struct timespec *start, struct timespec *end)
{
double t;
t = (end->tv_sec - start->tv_sec); // diff in seconds
t += (end->tv_nsec - start->tv_nsec) * 0.000000001; //diff in nanoseconds
return t;
}
// GPU Kernel
__global__ void GPU_Find(struct position *points, int *nearest, int n)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
int min = 1<<22;
int temp;
if(i >= n) return;
for(int j = 0; j < n; j++)
{
if(i == j) continue;
temp = (points[i].x - points[j].x)*(points[i].x - points[j].x);
temp += (points[i].y - points[j].y)*(points[i].y - points[j].y);
temp += (points[i].z - points[j].z)*(points[i].z - points[j].z);
if(temp < min)
{
min = temp;
nearest[i] = j;
}
}
return;
}
// CPU Function
void CPU_Find(struct position *points, int *nearest, int n)
{
int min; //All the distances are going to be smaller than this.
int temp;
for(int i = 0; i < n; i++)
{
min = 1<<22;
for(int j = 0; j < n; j++)
{
if(i == j) continue;
temp = (points[i].x - points[j].x)*(points[i].x - points[j].x);
temp += (points[i].y - points[j].y)*(points[i].y - points[j].y);
temp += (points[i].z - points[j].z)*(points[i].z - points[j].z);
temp = (int)sqrt(temp);
if(temp < min)
{
min = temp;
nearest[i] = j;
}
}
}
return;
}
// Code execution begins here
int main()
{
struct timespec start1, end1;
struct timespec start2, end2;
int n;
printf("Enter the value of n: ");
scanf("%d", &n);
struct position *points;
int *nearest1;
int *nearest2;
cudaMallocManaged(&points, n*sizeof(struct position));
cudaMallocManaged(&nearest1, n*sizeof(int));
cudaMallocManaged(&nearest2, n*sizeof(int));
for(int i = 0; i < n; i++)
{
points[i].x = rand()%100000;
points[i].y = rand()%100000;
points[i].z = rand()%10000;
nearest1[i] = -1;
nearest2[i] = -1;
}
clock_gettime(CLOCK_REALTIME, &start1); //start timestamp
GPU_Find<<<(n/128+1), 128>>>(points, nearest1, n);
cudaDeviceSynchronize();
clock_gettime(CLOCK_REALTIME, &end1); //end timestamp
clock_gettime(CLOCK_REALTIME, &start2); //start timestamp
CPU_Find(points, nearest2, n);
clock_gettime(CLOCK_REALTIME, &end2); //end timestamp
printf("\nTime taken by GPU is: %lf\n", time_elapsed(&start1, &end1)); //print result for GPU
printf("Time taken by CPU is: %lf\n", time_elapsed(&start2, &end2)); //print result for CPU
cudaFree(points);
cudaFree(nearest1);
cudaFree(nearest2);
return 0;
}
/*
The results obtained by the CPU and GPU may differ. Why so?
*/