Scanner C++ API
kernel.h
1 /* Copyright 2016 Carnegie Mellon University
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #pragma once
17 
18 #include "scanner/api/frame.h"
19 #include "scanner/util/common.h"
20 #include "scanner/util/memory.h"
21 #include "scanner/util/profiler.h"
22 
23 #include <vector>
24 
25 namespace scanner {
26 
28 struct Element {
29  Element() = default;
30  Element(const Element&) = default;
31  Element(Element&&) = default;
32  Element& operator=(const Element&) = default;
33 
34  Element(u8* buffer, size_t size);
35  Element(Frame* frame);
36 
37  inline Frame* as_frame() { return reinterpret_cast<Frame*>(buffer); }
38  inline const Frame* as_const_frame() const {
39  return reinterpret_cast<Frame*>(buffer);
40  }
41  inline FrameInfo* as_frame_info() {
42  return reinterpret_cast<FrameInfo*>(buffer);
43  }
44  inline const FrameInfo* as_const_frame_info() const {
45  return reinterpret_cast<FrameInfo*>(buffer);
46  }
47 
48  inline bool is_null() const {
49  return buffer == nullptr;
50  }
51 
52  u8* buffer;
53  size_t size;
54  bool is_frame;
55  // @brief the index of the element in the input domain
56  i64 index;
57 };
58 
59 using Elements = std::vector<Element>;
60 
61 using BatchedElements = std::vector<Elements>;
62 
63 using StenciledElements = std::vector<Elements>;
64 
66 using StenciledBatchedElements = std::vector<std::vector<Elements>>;
67 
68 inline size_t num_rows(const Elements& column) { return column.size(); }
69 
70 inline void insert_element(Elements& column, u8* buffer, size_t size) {
71  column.push_back(::scanner::Element{buffer, size});
72 }
73 
74 inline void insert_frame(Elements& column, Frame* frame) {
75  column.push_back(::scanner::Element{frame});
76 }
77 
78 inline void insert_element(Element& element, u8* buffer, size_t size) {
79  element = ::scanner::Element{buffer, size};
80 }
81 
82 inline void insert_frame(Element& element, Frame* frame) {
83  element = ::scanner::Element{frame};
84 }
85 
86 inline Element add_element_ref(DeviceHandle device, Element& element) {
87  if (element.is_null()) {
88  return Element();
89  }
90  Element ele;
91  if (element.is_frame) {
92  Frame* frame = element.as_frame();
93  add_buffer_ref(device, frame->data);
94  // Copy frame because Frame is not referenced counted
95  ele = ::scanner::Element{new Frame(frame->as_frame_info(), frame->data)};
96  } else {
97  add_buffer_ref(device, element.buffer);
98  ele = element;
99  }
100  ele.index = element.index;
101  return ele;
102 }
103 
104 inline void delete_element(DeviceHandle device, Element& element) {
105  if (element.is_null()) {
106  return;
107  }
108  if (element.is_frame) {
109  Frame* frame = element.as_frame();
110  delete_buffer(device, frame->data);
111  delete frame;
112  } else {
113  delete_buffer(device, element.buffer);
114  }
115 }
116 
118 struct KernelConfig {
119  std::vector<DeviceHandle> devices;
120  std::vector<std::string> input_columns;
122  std::vector<proto::ColumnType> input_column_types;
123  std::vector<std::string> output_columns;
124  std::vector<proto::ColumnType> output_column_types;
125  std::vector<u8> args;
126  i32 node_id;
127 
128  static KernelConfig dummy() {
129  KernelConfig config;
130  config.devices.push_back(CPU_DEVICE);
131  return config;
132  }
133 };
134 
145 class BaseKernel {
146  public:
147  static const i32 UnlimitedDevices = 0;
148  BaseKernel(const KernelConfig& config);
149 
150  virtual ~BaseKernel(){};
151 
157  virtual void validate(proto::Result* result) { result->set_success(true); }
158 
164  virtual void fetch_resources(proto::Result* result) { result->set_success(true); }
165 
171  virtual void setup_with_resources(proto::Result* result) { result->set_success(true); }
172 
180  virtual void new_stream(const std::vector<u8>& args) {};
181 
191  virtual void reset(){};
192 
196  virtual void execute_kernel(const StenciledBatchedElements& input_columns,
197  BatchedElements& output_columns) = 0;
198 
202  virtual void set_profiler(Profiler* profiler) { profiler_ = profiler; }
203 
208  Profiler* profiler_ = nullptr;
209 };
210 
211 
223  public:
224  static const i32 UnlimitedDevices = 0;
225  StenciledBatchedKernel(const KernelConfig& config);
226 
227  virtual ~StenciledBatchedKernel(){};
228 
232  virtual void execute_kernel(const StenciledBatchedElements& input_columns,
233  BatchedElements& output_columns) override;
234 
235  protected:
255  virtual void execute(const StenciledBatchedElements& input_columns,
256  BatchedElements& output_columns) = 0;
257 
262  Profiler* profiler_ = nullptr;
263 };
264 
275 class BatchedKernel : public BaseKernel {
276  public:
277  BatchedKernel(const KernelConfig& config);
278 
279  virtual ~BatchedKernel(){};
280 
284  virtual void execute_kernel(const StenciledBatchedElements& input_columns,
285  BatchedElements& output_columns);
286  protected:
306  virtual void execute(const BatchedElements& input_columns,
307  BatchedElements& output_columns) = 0;
308 };
309 
310 class StenciledKernel : public BaseKernel {
311  public:
312  StenciledKernel(const KernelConfig& config);
313 
314  virtual ~StenciledKernel(){};
315 
319  virtual void execute_kernel(const StenciledBatchedElements& input_columns,
320  BatchedElements& output_columns);
321  protected:
341  virtual void execute(const StenciledElements& input_columns,
342  Elements& output_columns) = 0;
343 };
344 
345 class Kernel : public BaseKernel {
346  public:
347  Kernel(const KernelConfig& config);
348 
349  virtual ~Kernel(){};
350 
354  virtual void execute_kernel(const StenciledBatchedElements& input_columns,
355  BatchedElements& output_columns);
356  protected:
374  virtual void execute(const Elements& input_columns,
375  Elements& output_columns) = 0;
376 };
377 
379 class VideoKernel {
380  protected:
388  void check_frame(const DeviceHandle& device, const Element& element);
389 
390  void check_frame_info(const DeviceHandle& device, const Element& element);
391 
393  virtual void new_frame_info(){};
394 
395  FrameInfo frame_info_{};
396 };
397 
400 namespace internal {
401 
402 class KernelBuilder;
403 
404 using KernelConstructor =
405  std::function<BaseKernel*(const KernelConfig& config)>;
406 
408  public:
409  KernelRegistration(const KernelBuilder& builder);
410 };
411 
413  public:
414  friend class KernelRegistration;
415 
416  KernelBuilder(const std::string& name, KernelConstructor constructor)
417  : name_(name),
418  constructor_(constructor),
419  device_type_(DeviceType::CPU),
420  num_devices_(1),
421  can_batch_(false),
422  preferred_batch_size_(1) {}
423 
424  KernelBuilder& device(DeviceType device_type) {
425  device_type_ = device_type;
426  return *this;
427  }
428 
429  KernelBuilder& num_devices(i32 devices) {
430  num_devices_ = devices;
431  return *this;
432  }
433 
434  KernelBuilder& input_device(const std::string& input_name,
435  DeviceType device_type) {
436  input_devices_[input_name] = device_type;
437  return *this;
438  }
439 
440  KernelBuilder& output_device(const std::string& output_name,
441  DeviceType device_type) {
442  output_devices_[output_name] = device_type;
443  return *this;
444  }
445 
446  KernelBuilder& batch(i32 preferred_batch_size = 1) {
447  can_batch_ = true;
448  preferred_batch_size_ = preferred_batch_size;
449  return *this;
450  }
451 
452  private:
453  std::string name_;
454  KernelConstructor constructor_;
455  DeviceType device_type_;
456  i32 num_devices_;
457  std::map<std::string, DeviceType> input_devices_;
458  std::map<std::string, DeviceType> output_devices_;
459  bool can_batch_;
460  i32 preferred_batch_size_;
461 };
462 }
463 
464 #define REGISTER_KERNEL(name__, kernel__) \
465  REGISTER_KERNEL_HELPER(__COUNTER__, name__, kernel__)
466 
467 #define REGISTER_KERNEL_HELPER(uid__, name__, kernel__) \
468  REGISTER_KERNEL_UID(uid__, name__, kernel__)
469 
470 #define REGISTER_KERNEL_UID(uid__, name__, kernel__) \
471  static ::scanner::internal::KernelRegistration kernel_registration_##uid__ \
472  __attribute__((unused)) = ::scanner::internal::KernelBuilder( \
473  #name__, [](const ::scanner::KernelConfig& config) { \
474  return new kernel__(config); \
475  })
476 }
virtual void reset()
Requests that kernel resets its logical state.
Definition: kernel.h:191
Kernel parameters provided at instantiation.
Definition: kernel.h:118
virtual void new_stream(const std::vector< u8 > &args)
Called when the Kernel is about to process a new stream.
Definition: kernel.h:180
Kernel with support for frame and frame_info columns.
Definition: kernel.h:379
Interface for a unit of computation in a pipeline.
Definition: kernel.h:222
virtual void fetch_resources(proto::Result *result)
Downloads any resources necessary for the kernel to run.
Definition: kernel.h:164
virtual void validate(proto::Result *result)
Checks if kernel arguments are valid.
Definition: kernel.h:157
Definition: kernel.h:412
Interface for a unit of computation in a pipeline.
Definition: kernel.h:275
Frame.
Definition: frame.h:62
virtual void new_frame_info()
Callback for if frame info changes.
Definition: kernel.h:393
Element in a Scanner table, byte buffer of arbitrary size.
Definition: kernel.h:28
Definition: profiler.h:40
virtual void setup_with_resources(proto::Result *result)
Runs any setup code that relies on fetched resources.
Definition: kernel.h:171
Definition: common.h:53
Definition: database.cpp:36
i32 node_id
Byte-string of proto args if given.
Definition: kernel.h:126
Definition: kernel.h:310
FrameInfo.
Definition: frame.h:34
virtual void set_profiler(Profiler *profiler)
For internal use.
Definition: kernel.h:202
Interface for a unit of computation in a pipeline.
Definition: kernel.h:145
Definition: kernel.h:345