RandomBallCover  1.2.1
 Hosted by GitHub
helper_funcs.hpp
Go to the documentation of this file.
1 
29 #ifndef RBC_HELPERFUNCS_HPP
30 #define RBC_HELPERFUNCS_HPP
31 
32 #include <cassert>
33 #include <algorithm>
34 #include <functional>
35 #include <RBC/data_types.hpp>
36 
37 #if defined(__APPLE__) || defined(__MACOSX)
38 #include <OpenCL/cl.hpp>
39 #else
40 #include <CL/cl.hpp>
41 #endif
42 
43 
44 namespace RBC
45 {
46 
48  bool setProfilingFlag (int argc, char **argv);
49 
50 
56  template <typename T>
57  uint64_t nextPow2 (T num)
58  {
59  assert (num >= 0);
60 
61  uint64_t pow;
62  for (pow = 1; pow < (uint64_t) num; pow <<= 1) ;
63 
64  return pow;
65  }
66 
67 
76  template <typename T>
77  void printBuffer (const char *title, T *ptr, uint32_t width, uint32_t height)
78  {
79  std::cout << title << std::endl;
80 
81  for (int row = 0; row < height; ++row)
82  {
83  for (int col = 0; col < width; ++col)
84  {
85  std::cout << std::setw (3 * sizeof (T)) << +ptr[row * width + col] << " ";
86  }
87  std::cout << std::endl;
88  }
89 
90  std::cout << std::endl;
91  }
92 
93 
103  template <typename T>
104  void printBufferF (const char *title, T *ptr, uint32_t width, uint32_t height, uint32_t prec)
105  {
106  std::ios::fmtflags f (std::cout.flags ());
107  std::cout << title << std::endl;
108  std::cout << std::fixed << std::setprecision (prec);
109 
110  for (int row = 0; row < height; ++row)
111  {
112  for (int col = 0; col < width; ++col)
113  {
114  std::cout << std::setw (5 + prec) << ptr[row * width + col] << " ";
115  }
116  std::cout << std::endl;
117  }
118 
119  std::cout << std::endl;
120  std::cout.flags (f);
121  }
122 
123 
133  template <typename T>
134  void cpuReduce (T *in, T *out, uint32_t cols, uint32_t rows, std::function<bool (T, T)> func)
135  {
136  for (uint r = 0; r < rows; ++r)
137  {
138  T rec = in[r * cols];
139  for (uint c = 1; c < cols; ++c)
140  {
141  T tmp = in[r * cols + c];
142  if (func (tmp, rec)) rec = tmp;
143  }
144  out[r] = rec;
145  }
146  }
147 
148 
158  template <typename T>
159  void cpuInScan (T *in, T *out, uint32_t width, uint32_t height)
160  {
161  // Initialize the first element of each row
162  for (uint32_t row = 0; row < height; ++row)
163  out[row * width] = in[row * width];
164  // Perform the scan
165  for (uint32_t row = 0; row < height; ++row)
166  for (uint32_t col = 1; col < width; ++col)
167  out[row * width + col] = out[row * width + col - 1] + in[row * width + col];
168  }
169 
170 
180  template <typename T>
181  void cpuExScan (T *in, T *out, uint32_t width, uint32_t height)
182  {
183  // Initialize the first element of each row
184  for (uint32_t row = 0; row < height; ++row)
185  out[row * width] = 0;
186  // Perform the scan
187  for (uint32_t row = 0; row < height; ++row)
188  for (uint32_t col = 1; col < width; ++col)
189  out[row * width + col] = out[row * width + col - 1] + in[row * width + col - 1];
190  }
191 
192 
205  template <typename T>
206  void cpuRBCComputeDists (T *X, T *R, T *D, uint32_t nx, uint32_t nr, uint32_t d)
207  {
208  for (uint x = 0; x < nx; ++x)
209  {
210  for (uint r = 0; r < nr; ++r)
211  {
212  T dist = 0.f;
213  for (uint j = 0; j < d; ++j)
214  dist += std::pow (X[x * d + j] - R[r * d + j], 2);
215 
216  D[x * nr + r] = dist;
217  }
218  }
219  }
220 
221 
235  template <typename T>
236  void cpuRBCComputeDists8 (T *X, T *R, T *D, uint32_t nx, uint32_t nr, uint32_t d, T a)
237  {
238  for (uint x = 0; x < nx; ++x)
239  {
240  for (uint r = 0; r < nr; ++r)
241  {
242  T dist = 0.f;
243  for (uint j = 0; j < 4; ++j)
244  dist += 1.f / (1.f + a) * std::pow (X[x * d + j] - R[r * d + j], 2);
245  for (uint j = 4; j < 8; ++j)
246  dist += a * std::pow (X[x * d + j] - R[r * d + j], 2);
247 
248  D[x * nr + r] = dist;
249  }
250  }
251  }
252 
253 
269  template <typename T>
270  void cpuRBCMinDists (T *in, rbc_dist_id *out, uint32_t *N, uint32_t *Rnk,
271  uint32_t cols, uint32_t rows, bool accCounters)
272  {
273  if (accCounters)
274  for (uint c = 0; c < cols; ++c)
275  N[c] = 0;
276 
277  rbc_dist_id rbcMin;
278 
279  for (uint r = 0; r < rows; ++r)
280  {
281  rbcMin.dist = in[r * cols];
282  rbcMin.id = 0;
283 
284  for (uint c = 1; c < cols; ++c)
285  {
286  T tmp = in[r * cols + c];
287  if (tmp < rbcMin.dist)
288  {
289  rbcMin.dist = tmp;
290  rbcMin.id = c;
291  }
292  }
293 
294  out[r] = rbcMin;
295 
296  if (accCounters)
297  Rnk[r] = N[rbcMin.id]++;
298  }
299  }
300 
301 
320  template <typename T>
321  void cpuRBCPermute (T *X, rbc_dist_id *ID, T *Xp, rbc_dist_id *IDp, uint32_t *O, uint32_t *Rnk,
322  uint32_t nx, uint32_t nr, uint32_t d, bool permID)
323  {
324  for (uint32_t x = 0; x < nx; ++x)
325  {
326  uint id = ID[x].id;
327  uint offset = O[id];
328  uint rank = Rnk[x];
329 
330  for (uint32_t j = 0; j < d; ++j)
331  Xp[(offset + rank) * d + j] = X[x * d + j];
332 
333  if (permID == true)
334  IDp[offset + rank] = ID[x];
335  }
336  }
337 
338 
347  template <typename T>
348  T euclideanMetric (T *p1, T *p2, uint32_t d)
349  {
350  T dist = 0.f;
351 
352  for (int i = 0; i < d; ++i)
353  dist += std::pow (p1[i] - p2[i], 2);
354 
355  return std::sqrt (dist);
356  }
357 
358 
368  template <typename T>
369  T euclideanMetric8Squared (T *p1, T *p2, float a)
370  {
371  T dist = 0.f;
372 
373  for (int i = 0; i < 4; ++i)
374  dist += 1.f / (1.f + a) * std::pow (p1[i] - p2[i], 2);
375  for (int i = 4; i < 8; ++i)
376  dist += a * std::pow (p1[i] - p2[i], 2);
377 
378  return dist;
379  }
380 
381 
399  template <typename T>
400  void cpuRBCSearch (T *Qp, rbc_dist_id *RID, T *Xp, cl_uint *O, cl_uint *N, rbc_dist_id *NNID, T *NN,
401  uint32_t nq, uint32_t nr, uint32_t nx, uint32_t d)
402  {
403  cl_uint max_n = std::accumulate (N, N + nr, 0,
404  [](cl_uint a, cl_uint b) -> cl_uint { return std::max (a, b); });
405 
406  cl_float *D = new cl_float[nq * max_n];
407 
408  // Compute distances Q - X[L]
409  for (uint q = 0; q < nq; ++q)
410  {
411  cl_uint rID = RID[q].id;
412  cl_uint o = O[rID];
413  cl_uint n = N[rID];
414 
415  for (uint x = 0; x < max_n; ++x)
416  {
417  float dist = 0.f;
418 
419  if (x < n)
420  for (uint j = 0; j < d; ++j)
421  dist += std::pow (Qp[q * d + j] - Xp[(o + x) * d + j], 2);
422  else
423  dist = std::numeric_limits<float>::infinity ();
424 
425  D[q * max_n + x] = dist;
426  }
427  }
428 
429  cpuRBCMinDists (D, NNID, nullptr, nullptr, max_n, nq, false);
430 
431  for (uint32_t q = 0; q < nq; ++q)
432  {
433  uint nnID = O[RID[q].id] + NNID[q].id;
434 
435  for (uint32_t j = 0; j < d; ++j)
436  NN[q * d + j] = Xp[nnID * d + j];
437  }
438 
439  delete[] D;
440  }
441 
442 
461  template <typename T>
462  void cpuRBCSearch8 (T *Qp, rbc_dist_id *RID, T *Xp, cl_uint *O, cl_uint *N, rbc_dist_id *NNID, T *NN,
463  uint32_t nq, uint32_t nr, uint32_t nx, T a)
464  {
465  const unsigned int d = 8;
466  cl_uint max_n = std::accumulate (N, N + nr, 0,
467  [](cl_uint a, cl_uint b) -> cl_uint { return std::max (a, b); });
468 
469  cl_float *D = new cl_float[nq * max_n];
470 
471  // Compute distances Q - X[L]
472  for (uint q = 0; q < nq; ++q)
473  {
474  cl_uint rID = RID[q].id;
475  cl_uint o = O[rID];
476  cl_uint n = N[rID];
477 
478  for (uint x = 0; x < max_n; ++x)
479  {
480  float dist = 0.f;
481 
482  if (x < n)
483  {
484  for (uint j = 0; j < 4; ++j)
485  dist += 1.f / (1.f + a) * std::pow (Qp[q * d + j] - Xp[(o + x) * d + j], 2);
486  for (uint j = 4; j < d; ++j)
487  dist += a * std::pow (Qp[q * d + j] - Xp[(o + x) * d + j], 2);
488  }
489  else
490  dist = std::numeric_limits<float>::infinity ();
491 
492  D[q * max_n + x] = dist;
493  }
494  }
495 
496  cpuRBCMinDists (D, NNID, nullptr, nullptr, max_n, nq, false);
497 
498  for (uint32_t q = 0; q < nq; ++q)
499  {
500  uint nnID = O[RID[q].id] + NNID[q].id;
501 
502  for (uint32_t j = 0; j < d; ++j)
503  NN[q * d + j] = Xp[nnID * d + j];
504  }
505 
506  delete[] D;
507  }
508 
509 
521  template <typename T>
522  void cpuNNSearch (T *Q, T *X, T *NN, uint32_t nq, uint32_t nx, uint32_t d)
523  {
524  // Compute distance array
525  std::vector<T> D (nq * nx);
526 
527  for (uint32_t q = 0; q < nq; ++q)
528  for (uint32_t x = 0; x < nx; ++x)
529  D[q * nx + x] = euclideanMetric (&Q[q * d], &X[x * d], d);
530 
531  // Find NN IDs
532  std::vector<uint32_t> minID (nq);
533 
534  for (uint32_t q = 0; q < nq; ++q)
535  {
536  T minDist = D[q * nx];
537  uint32_t id = 0;
538 
539  for (uint32_t x = 1; x < nx; ++x)
540  {
541  T tmp = D[q * nx + x];
542  if (tmp < minDist)
543  {
544  minDist = tmp;
545  id = x;
546  }
547  }
548 
549  minID[q] = id;
550  }
551 
552  // Collect NNs
553  for (uint32_t q = 0; q < nq; ++q)
554  for (uint32_t j = 0; j < d; ++j)
555  NN[q * d + j] = X[minID[q] * d + j];
556  }
557 
558 
568  template <typename T>
569  T meanError (T *Q, T *NN, uint32_t n, uint32_t d)
570  {
571  std::vector<T> D (n);
572  unsigned int i = -1;
573 
574  std::generate (D.begin (), D.end (),
575  [&]() { i++; return euclideanMetric (&Q[i * d], &NN[i * d], d); });
576 
577  T sumD = std::accumulate (D.begin (), D.end (), 0.f);
578 
579  return sumD / (T) n;
580  }
581 
582 }
583 
584 #endif // RBC_HELPERFUNCS_HPP
void printBufferF(const char *title, T *ptr, uint32_t width, uint32_t height, uint32_t prec)
Prints an array of floating-point type to standard output.
Definition: helper_funcs.hpp:104
void cpuRBCPermute(T *X, rbc_dist_id *ID, T *Xp, rbc_dist_id *IDp, uint32_t *O, uint32_t *Rnk, uint32_t nx, uint32_t nr, uint32_t d, bool permID)
Performs a permutation of the RBC database to form the representative lists.
Definition: helper_funcs.hpp:321
uint64_t nextPow2(T num)
Returns the first power of 2 greater than or equal to the input.
Definition: helper_funcs.hpp:57
void cpuExScan(T *in, T *out, uint32_t width, uint32_t height)
Performs an exclusive scan operation on the columns of an array.
Definition: helper_funcs.hpp:181
T meanError(T *Q, T *NN, uint32_t n, uint32_t d)
Computes the mean euclidean distance from the queries to their NNs.
Definition: helper_funcs.hpp:569
Declarations of data types used by the Random Ball Cover data structure.
void cpuRBCComputeDists(T *X, T *R, T *D, uint32_t nx, uint32_t nr, uint32_t d)
Computes the distances between two sets of points in a brute force way.
Definition: helper_funcs.hpp:206
Struct holding a value and a key.
Definition: data_types.hpp:43
void cpuReduce(T *in, T *out, uint32_t cols, uint32_t rows, std::function< bool(T, T)> func)
Reduces each row of an array to a single element.
Definition: helper_funcs.hpp:134
T euclideanMetric(T *p1, T *p2, uint32_t d)
Calculates the euclidean distance betweeen two points.
Definition: helper_funcs.hpp:348
void cpuRBCMinDists(T *in, rbc_dist_id *out, uint32_t *N, uint32_t *Rnk, uint32_t cols, uint32_t rows, bool accCounters)
Computes the minimum element, and its corresponding column id, for each row in an array...
Definition: helper_funcs.hpp:270
Definition: helper_funcs.hpp:44
void cpuRBCSearch(T *Qp, rbc_dist_id *RID, T *Xp, cl_uint *O, cl_uint *N, rbc_dist_id *NNID, T *NN, uint32_t nq, uint32_t nr, uint32_t nx, uint32_t d)
Uses the RBC data structure to search for the nearest neighbors.
Definition: helper_funcs.hpp:400
void cpuNNSearch(T *Q, T *X, T *NN, uint32_t nq, uint32_t nx, uint32_t d)
Computes (brute force) the nearest neighbors of a set of queries.
Definition: helper_funcs.hpp:522
void cpuInScan(T *in, T *out, uint32_t width, uint32_t height)
Performs an inclusive scan operation on the columns of an array.
Definition: helper_funcs.hpp:159
bool setProfilingFlag(int argc, char **argv)
Checks the command line arguments for the profiling flag, --profiling.
Definition: helper_funcs.cpp:66
T euclideanMetric8Squared(T *p1, T *p2, float a)
Calculates the euclidean distance betweeen two points in ..
Definition: helper_funcs.hpp:369
cl_uint id
Definition: data_types.hpp:46
void cpuRBCComputeDists8(T *X, T *R, T *D, uint32_t nx, uint32_t nr, uint32_t d, T a)
Computes the distances between two sets of points in a brute force way.
Definition: helper_funcs.hpp:236
void printBuffer(const char *title, T *ptr, uint32_t width, uint32_t height)
Prints an array of an integer type to standard output.
Definition: helper_funcs.hpp:77
void cpuRBCSearch8(T *Qp, rbc_dist_id *RID, T *Xp, cl_uint *O, cl_uint *N, rbc_dist_id *NNID, T *NN, uint32_t nq, uint32_t nr, uint32_t nx, T a)
Uses the RBC data structure to search for the nearest neighbors.
Definition: helper_funcs.hpp:462
cl_float dist
Definition: data_types.hpp:45