workingset.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019-2024, NVIDIA CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <cuml/common/logger.hpp>
20 #include <cuml/svm/svm_parameter.h>
21 
22 #include <raft/core/handle.hpp>
23 
24 #include <rmm/device_scalar.hpp>
25 #include <rmm/device_uvector.hpp>
26 
27 #include <algorithm>
28 #include <cstddef>
29 #include <limits>
30 
31 namespace ML {
32 namespace SVM {
33 
44 template <typename math_t>
45 class WorkingSet {
46  public:
48  bool FIFO_strategy = true;
49 
59  WorkingSet(const raft::handle_t& handle,
60  cudaStream_t stream,
61  int n_rows = 0,
62  int n_ws = 0,
63  SvmType svmType = C_SVC)
64  : handle(handle),
65  stream(stream),
66  svmType(svmType),
67  n_rows(n_rows),
68  available(0, stream),
69  available_sorted(0, stream),
70  cub_storage(0, stream),
71  f_idx(0, stream),
72  f_idx_sorted(0, stream),
73  f_sorted(0, stream),
74  idx_tmp(0, stream),
75  idx(0, stream),
76  ws_idx_sorted(0, stream),
77  ws_idx_selected(0, stream),
78  ws_idx_save(0, stream),
79  ws_priority(0, stream),
80  ws_priority_sorted(0, stream),
81  d_num_selected(stream)
82  {
83  n_train = (svmType == EPSILON_SVR) ? n_rows * 2 : n_rows;
84  SetSize(n_train, n_ws);
85  }
86 
88 
95  void SetSize(int n_train, int n_ws = 0)
96  {
97  if (n_ws == 0 || n_ws > n_train) { n_ws = n_train; }
98  n_ws = std::min(1024, n_ws);
99  this->n_ws = n_ws;
100  CUML_LOG_DEBUG("Creating working set with %d elements", n_ws);
101  AllocateBuffers();
102  }
103 
105  int GetSize() { return n_ws; }
106 
112  int* GetIndices() { return idx.data(); }
113 
139  math_t* f, math_t* alpha, math_t* y, const math_t* C, int n_already_selected = 0);
140 
159  void Select(math_t* f, math_t* alpha, math_t* y, const math_t* C)
160  {
161  if (n_ws >= n_train) {
162  // All elements are selected, we have initialized idx to cover this case
163  return;
164  }
165  int nc = n_ws / 4;
166  int n_selected = 0;
167  if (firstcall) {
168  if (nc >= 1) {
169  firstcall = false;
170  } else {
171  // This can only happen for n_ws < 4.
172  // We keep the calculation always in firstcall mode (only SimpleSelect
173  // is used, no advanced strategies because we do not have enough elements)
174  //
175  // Nothing to do, firstcall is already true
176  }
177  } else {
178  // keep 1/2 of the old working set
179  if (FIFO_strategy) {
180  // FIFO selection following ThunderSVM
181  raft::copy(idx.data(), ws_idx_save.data() + 2 * nc, 2 * nc, stream);
182  n_selected = nc * 2;
183  } else {
184  // priority based selection preferring to keep newer elements in ws
185  n_selected = PrioritySelect(alpha, C, nc);
186  }
187  }
188  SimpleSelect(f, alpha, y, C, n_selected);
189  raft::copy(ws_idx_save.data(), idx.data(), n_ws, stream);
190  }
191 
210  int PrioritySelect(math_t* alpha, const math_t* C, int nc);
211 
212  private:
213  const raft::handle_t& handle;
214  cudaStream_t stream;
215 
216  bool firstcall = true;
217  int n_train = 0;
218  int n_rows = 0;
219  int n_ws = 0;
220 
221  SvmType svmType;
222 
223  int TPB = 256;
224 
225  // Buffers for the domain size [n_train]
226  rmm::device_uvector<int> f_idx;
227  rmm::device_uvector<int> f_idx_sorted;
229  rmm::device_uvector<int> idx_tmp;
230  rmm::device_uvector<math_t> f_sorted;
232  rmm::device_uvector<bool> available;
233  rmm::device_uvector<bool> available_sorted;
234 
235  // working set buffers size [n_ws]
236  rmm::device_uvector<int> idx;
237  rmm::device_uvector<int> ws_idx_sorted;
238  rmm::device_uvector<int> ws_idx_selected;
239  rmm::device_uvector<int> ws_idx_save;
240 
241  rmm::device_uvector<int> ws_priority;
242  rmm::device_uvector<int> ws_priority_sorted;
243 
244  rmm::device_scalar<int> d_num_selected;
245  std::size_t cub_bytes = 0;
246  rmm::device_uvector<char> cub_storage;
247 
248  void AllocateBuffers();
249 
264  int GatherAvailable(int n_already_selected, int n_needed, bool copy_front);
265 
266  void Initialize();
267 
278  template <typename select_op>
279  int SelectPrevWs(int n_needed, int n_already_selected, select_op op);
280 };
281 
282 }; // end namespace SVM
283 }; // end namespace ML
Definition: workingset.h:45
int GetSize()
Definition: workingset.h:105
void Select(math_t *f, math_t *alpha, math_t *y, const math_t *C)
Select working set indices.
Definition: workingset.h:159
WorkingSet(const raft::handle_t &handle, cudaStream_t stream, int n_rows=0, int n_ws=0, SvmType svmType=C_SVC)
Manage a working set.
Definition: workingset.h:59
bool FIFO_strategy
Workspace selection strategy, note that only FIFO is tested so far
Definition: workingset.h:48
void SetSize(int n_train, int n_ws=0)
Set the size of the working set and allocate buffers accordingly.
Definition: workingset.h:95
~WorkingSet()
Definition: workingset.h:87
void SimpleSelect(math_t *f, math_t *alpha, math_t *y, const math_t *C, int n_already_selected=0)
Select new elements for a working set.
int * GetIndices()
Return a device pointer to the the working set indices.
Definition: workingset.h:112
int PrioritySelect(math_t *alpha, const math_t *C, int nc)
Select elements from the previous working set based on their priority.
#define CUML_LOG_DEBUG(fmt,...)
Definition: logger.hpp:198
SvmType
Definition: svm_parameter.h:21
@ EPSILON_SVR
Definition: svm_parameter.h:21
@ C_SVC
Definition: svm_parameter.h:21
Definition: dbscan.hpp:30
const_agnostic_same_t< T, U > copy(buffer< T > &dst, buffer< U > const &src, typename buffer< T >::index_type dst_offset, typename buffer< U >::index_type src_offset, typename buffer< T >::index_type size, cuda_stream stream)
Definition: buffer.hpp:327