Caffe2 - C++ API
A deep learning, cross platform ML framework
int8_add_op.h
1 #ifndef CAFFE2_OPERATORS_INT8_ADD_OP_H_
2 #define CAFFE2_OPERATORS_INT8_ADD_OP_H_
3 
4 #include <qnnpack.h>
5 
6 #include "caffe2/core/context.h"
7 #include "caffe2/core/operator.h"
8 #include "caffe2/core/tensor_int8.h"
9 #include "caffe2/operators/quantized/int8_utils.h"
10 
11 namespace caffe2 {
12 
13 namespace int8 {
14 
15 template <Activation Ac>
16 class Int8AddOp final : public Operator<CPUContext> {
17  public:
18  explicit Int8AddOp(const OperatorDef& operator_def, Workspace* ws)
19  : Operator<CPUContext>(operator_def, ws), ws_(ws) {}
20 
21  ~Int8AddOp() {
22  if (this->qnnpackOperator_ != nullptr) {
23  qnnp_delete_operator(this->qnnpackOperator_);
24  this->qnnpackOperator_ = nullptr;
25  }
26  }
27 
28  bool RunOnDevice() override {
29  CAFFE_ENFORCE_EQ(Inputs().size(), 2);
30  const auto& A = Inputs()[0]->template Get<Int8TensorCPU>();
31  const auto& B = Inputs()[1]->template Get<Int8TensorCPU>();
32  auto* Y = Outputs()[0]->template GetMutable<Int8TensorCPU>();
33 
34  CAFFE_ENFORCE_EQ(
35  A.t.sizes(),
36  B.t.sizes(),
37  "inputs must have the same shape (broadcast semantics is not supported)");
38 
39  /*
40  * Record quantization parameters for A and B inputs, because if the op is
41  * in-place, we may overwrite these parameters later, when we set
42  * quantization parameters for Y tensor.
43  */
44  const uint8_t A_zero_point = A.zero_point;
45  const uint8_t B_zero_point = B.zero_point;
46  const float A_scale = A.scale;
47  const float B_scale = B.scale;
48 
49  const int32_t Y_zero_point =
50  this->template GetSingleArgument<int>("Y_zero_point", 0);
51  const float Y_scale =
52  this->template GetSingleArgument<float>("Y_scale", 1);
53  Y->t.ResizeLike(A.t);
54  Y->zero_point = Y_zero_point;
55  Y->scale = Y_scale;
56 
57  initQNNPACK();
58 
59  pthreadpool_t threadpool =
60  reinterpret_cast<pthreadpool_t>(ws_->GetThreadPool());
61 
62  if (this->qnnpackOperator_ == nullptr) {
63  const qnnp_status createStatus = qnnp_create_add_nc_q8(
64  1 /* channels */,
65  A_zero_point, A_scale,
66  B_zero_point, B_scale,
67  static_cast<uint8_t>(Y_zero_point), Y_scale,
68  activationLimits(Y_scale, Y_zero_point, Ac).first,
69  activationLimits(Y_scale, Y_zero_point, Ac).second,
70  0 /* flags */,
71  &qnnpackOperator_);
72  CAFFE_ENFORCE(
73  createStatus == qnnp_status_success,
74  "failed to create QNNPACK add operator");
75  CAFFE_ENFORCE(this->qnnpackOperator_ != nullptr);
76  }
77 
78  const qnnp_status setupStatus = qnnp_setup_add_nc_q8(
79  this->qnnpackOperator_,
80  A.t.numel() /* batch size */,
81  A.t.template data<uint8_t>(),
82  1 /* A stride */,
83  B.t.template data<uint8_t>(),
84  1 /* B stride */,
85  Y->t.template mutable_data<uint8_t>(),
86  1 /* Y stride */);
87  CAFFE_ENFORCE(
88  setupStatus == qnnp_status_success,
89  "failed to setup QNNPACK add operator");
90 
91 #ifdef FBCODE_CAFFE2
92  const qnnp_status runStatus =
93  qnnp_run_operator(this->qnnpackOperator_, nullptr /* thread pool */);
94 #else
95  const qnnp_status runStatus =
96  qnnp_run_operator(this->qnnpackOperator_, threadpool);
97 #endif
98  CAFFE_ENFORCE(
99  runStatus == qnnp_status_success,
100  "failed to run QNNPACK add operator");
101 
102  return true;
103  }
104 
105  private:
106  Workspace* ws_;
107  // QNNPACK add operator
108  qnnp_operator_t qnnpackOperator_{nullptr};
109 };
110 
111 } // namespace int8
112 
113 } // namespace caffe2
114 
115 #endif // CAFFE2_OPERATORS_INT8_ADD_OP_H_
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
Definition: workspace.h:47
Definition: static.cpp:52
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Definition: blob.h:13
Definition: static.cpp:58