Cleaned up, debugged. Ready for 1st release
[RBC.git] / driver.cu
1 /* This file is part of the Random Ball Cover (RBC) library.
2 * (C) Copyright 2010, Lawrence Cayton [lcayton@tuebingen.mpg.de]
3 */
4
5 #include<stdio.h>
6 #include<stdlib.h>
7 #include<cuda.h>
8 #include<sys/time.h>
9 #include<math.h>
10 #include "defs.h"
11 #include "utils.h"
12 #include "utilsGPU.h"
13 #include "rbc.h"
14 #include "brute.h"
15 #include "sKernel.h"
16
17 void parseInput(int,char**);
18 void readData(char*,unint,unint,real*);
19 void readDataText(char*,unint,unint,real*);
20 void orgData(real*,unint,unint,matrix,matrix);
21
22
23 char *dataFile, *outFile;
24 unint n=0, m=0, d=0, numReps=0, s=0;
25 unint deviceNum=0;
26 int main(int argc, char**argv){
27 real *data;
28 matrix x, q;
29 unint *NNs, *NNsBrute;
30 unint i;
31 struct timeval tvB,tvE;
32 cudaError_t cE;
33 rbcStruct rbcS;
34
35 printf("*****************\n");
36 printf("RANDOM BALL COVER\n");
37 printf("*****************\n");
38
39 parseInput(argc,argv);
40
41 cuInit(0);
42 printf("Using GPU #%d\n",deviceNum);
43 if(cudaSetDevice(deviceNum) != cudaSuccess){
44 printf("Unable to select device %d.. exiting. \n",deviceNum);
45 exit(1);
46 }
47
48 unsigned int memFree, memTot;
49 CUcontext pctx;
50 unsigned int flags=0;
51 int device;
52 cudaGetDevice(&device);
53 cuCtxCreate(&pctx,flags,device);
54 cuMemGetInfo(&memFree, &memTot);
55 printf("GPU memory free = %u/%u (MB) \n",memFree/(1024*1024),memTot/(1024*1024));
56
57 data = (real*)calloc( (n+m)*d, sizeof(*data) );
58 x.mat = (real*)calloc( PAD(n)*PAD(d), sizeof(*(x.mat)) );
59
60 //Need to allocate extra space, as each group of q will be padded later.
61 q.mat = (real*)calloc( PAD(m)*PAD(d), sizeof(*(q.mat)) );
62 x.r = n; x.c = d; x.pr = PAD(n); x.pc = PAD(d); x.ld = x.pc;
63 q.r = m; q.c = d; q.pr = PAD(m); q.pc = PAD(d); q.ld = q.pc;
64
65 NNs = (unint*)calloc( m, sizeof(*NNs) );
66 for(i=0; i<m; i++)
67 NNs[i]=DUMMY_IDX;
68 NNsBrute = (unint*)calloc( m, sizeof(*NNsBrute) );
69
70 readData(dataFile, (n+m), d, data);
71 orgData(data, (n+m), d, x, q);
72 free(data);
73
74 for(i=0;i<m;i++)
75 NNs[i]=NNsBrute[i]=DUMMY_IDX;
76
77 /* printf("running brute force..\n"); */
78 /* gettimeofday(&tvB,NULL); */
79 /* bruteSearch(x,q,NNsBrute); */
80 /* gettimeofday(&tvE,NULL); */
81 /* printf("\t.. time elapsed = %6.4f \n",timeDiff(tvB,tvE)); */
82
83 printf("\nrunning rbc..\n");
84 gettimeofday(&tvB,NULL);
85 buildRBC(x, &rbcS, numReps, s);
86 gettimeofday(&tvE,NULL);
87 printf("\t.. build time for rbc = %6.4f \n",timeDiff(tvB,tvE));
88
89 gettimeofday(&tvB,NULL);
90 queryRBC(q, rbcS, NNs);
91 gettimeofday(&tvE,NULL);
92 printf("\t.. query time for rbc = %6.4f \n",timeDiff(tvB,tvE));
93
94 destroyRBC(&rbcS);
95 printf("finished \n");
96
97 cE = cudaGetLastError();
98 if( cE != cudaSuccess ){
99 printf("Execution failed; error type: %s \n", cudaGetErrorString(cE) );
100 }
101
102 printf("\nComputing error rates (this might take a while)\n");
103 real *ranges = (real*)calloc(q.pr,sizeof(*ranges));
104 for(i=0;i<q.r;i++){
105 if(NNs[i]>n) printf("error");
106 ranges[i] = distVec(q,x,i,NNs[i]) - 10e-6;
107 }
108
109 unint *cnts = (unint*)calloc(q.pr,sizeof(*cnts));
110 gettimeofday(&tvB,NULL);
111 bruteRangeCount(x,q,ranges,cnts);
112 gettimeofday(&tvE,NULL);
113
114 long int nc=0;
115 for(i=0;i<m;i++){
116 nc += cnts[i];
117 }
118 double mean = ((double)nc)/((double)m);
119 double var = 0.0;
120 for(i=0;i<m;i++) {
121 var += (((double)cnts[i])-mean)*(((double)cnts[i])-mean)/((double)m);
122 }
123 printf("\tavg rank = %6.4f; std dev = %6.4f \n\n", mean, sqrt(var));
124 printf("(range count took %6.4f) \n", timeDiff(tvB, tvE));
125
126
127 if(outFile){
128 FILE* fp = fopen(outFile, "a");
129 fprintf( fp, "%d %d %6.5f %6.5f \n", numReps, s, mean, sqrt(var) );
130 fclose(fp);
131 }
132
133 free(ranges);
134 free(cnts);
135 free(NNs);
136 free(NNsBrute);
137 free(x.mat);
138 free(q.mat);
139 }
140
141
142 void parseInput(int argc, char **argv){
143 int i=1;
144 if(argc <= 1){
145 printf("\nusage: \n testRBC -f datafile (bin) -n numPts (DB) -m numQueries -d dim -r numReps -s numPtsPerRep [-o outFile] [-g GPU num]\n\n");
146 printf("\tdatafile = binary file containing the data\n");
147 printf("\tnumPts = size of database\n");
148 printf("\tnumQueries = number of queries\n");
149 printf("\tdim = dimensionailty\n");
150 printf("\tnumReps = number of representatives\n");
151 printf("\tnumPtsPerRep = number of points assigned to each representative\n");
152 printf("\toutFile = output file (optional); stored in text format\n");
153 printf("\tGPU num = ID # of the GPU to use (optional) for multi-GPU machines\n");
154 printf("\n\n");
155 exit(0);
156 }
157
158 while(i<argc){
159 if(!strcmp(argv[i], "-f"))
160 dataFile = argv[++i];
161 else if(!strcmp(argv[i], "-n"))
162 n = atoi(argv[++i]);
163 else if(!strcmp(argv[i], "-m"))
164 m = atoi(argv[++i]);
165 else if(!strcmp(argv[i], "-d"))
166 d = atoi(argv[++i]);
167 else if(!strcmp(argv[i], "-r"))
168 numReps = atoi(argv[++i]);
169 else if(!strcmp(argv[i], "-s"))
170 s = atoi(argv[++i]);
171 else if(!strcmp(argv[i], "-o"))
172 outFile = argv[++i];
173 else if(!strcmp(argv[i], "-g"))
174 deviceNum = atoi(argv[++i]);
175 else{
176 fprintf(stderr,"%s : unrecognized option.. exiting\n",argv[i]);
177 exit(1);
178 }
179 i++;
180 }
181
182 if( !n || !m || !d || !numReps || !s || !dataFile){
183 fprintf(stderr,"more arguments needed.. exiting\n");
184 exit(1);
185 }
186
187 if(numReps>n){
188 fprintf(stderr,"can't have more representatives than points.. exiting\n");
189 exit(1);
190 }
191 }
192
193
194 void readData(char *dataFile, unint rows, unint cols, real *data){
195 FILE *fp;
196 unint numRead;
197
198 fp = fopen(dataFile,"r");
199 if(fp==NULL){
200 fprintf(stderr,"error opening file.. exiting\n");
201 exit(1);
202 }
203
204 numRead = fread(data,sizeof(real),rows*cols,fp);
205 if(numRead != rows*cols){
206 fprintf(stderr,"error reading file.. exiting \n");
207 exit(1);
208 }
209 fclose(fp);
210 }
211
212
213 void readDataText(char *dataFile, unint rows, unint cols, real *data){
214 FILE *fp;
215 real t;
216
217 fp = fopen(dataFile,"r");
218 if(fp==NULL){
219 fprintf(stderr,"error opening file.. exiting\n");
220 exit(1);
221 }
222
223 for(int i=0; i<rows; i++){
224 for(int j=0; j<cols; j++){
225 if(fscanf(fp,"%f ", &t)==EOF){
226 fprintf(stderr,"error reading file.. exiting \n");
227 exit(1);
228 }
229 data[IDX( i, j, cols )]=(real)t;
230 }
231 }
232 fclose(fp);
233 }
234
235 //This function splits the data into two matrices, x and q, of
236 //their specified dimensions. The data is split randomly.
237 //It is assumed that the number of rows of data (the parameter n)
238 //is at least as large as x.r+q.r
239 void orgData(real *data, unint n, unint d, matrix x, matrix q){
240
241 unint i,fi,j;
242 unint *p;
243 p = (unint*)calloc(n,sizeof(*p));
244
245 randPerm(n,p);
246
247 for(i=0,fi=0 ; i<x.r ; i++,fi++){
248 for(j=0;j<x.c;j++){
249 x.mat[IDX(i,j,x.ld)] = data[IDX(p[fi],j,d)];
250 }
251 }
252
253 for(i=0 ; i<q.r ; i++,fi++){
254 for(j=0;j<q.c;j++){
255 q.mat[IDX(i,j,q.ld)] = data[IDX(p[fi],j,d)];
256 }
257 }
258
259 free(p);
260 }
261