aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuan Zhao2019-10-29 02:14:54 -0500
committerYuan Zhao2019-10-30 21:54:46 -0500
commite0b7c38d199674f34ea1fb2c182744851785dd79 (patch)
treea5e0ba195715a11999f84c98e63dfcc9321003f7
parent34d236d1b2870e973ab045063af8980d779ec49a (diff)
downloadtidl-api-e0b7c38d199674f34ea1fb2c182744851785dd79.tar.gz
tidl-api-e0b7c38d199674f34ea1fb2c182744851785dd79.tar.xz
tidl-api-e0b7c38d199674f34ea1fb2c182744851785dd79.zip
Subgraph data conversion at boundaries
- Data layout: NCHW <-> NHWC - Data type: 8-bit quantized <-> float - MCT-1222
-rw-r--r--tidl_api/Makefile2
-rw-r--r--tidl_api/inc/subgraph_data_conv.h (renamed from tidl_api/src/subgraph_data_conv.h)17
-rw-r--r--tidl_api/inc/subgraph_runtime.h7
-rw-r--r--tidl_api/src/subgraph_data_conv.cpp142
-rw-r--r--tidl_api/src/subgraph_runtime.cpp24
5 files changed, 182 insertions, 10 deletions
diff --git a/tidl_api/Makefile b/tidl_api/Makefile
index 988cdc9..4dc298b 100644
--- a/tidl_api/Makefile
+++ b/tidl_api/Makefile
@@ -41,7 +41,7 @@ AR = ar
41SRCS = ocl_device.cpp configuration_parser.cpp configuration.cpp\ 41SRCS = ocl_device.cpp configuration_parser.cpp configuration.cpp\
42 executor.cpp execution_object.cpp trace.cpp util.cpp \ 42 executor.cpp execution_object.cpp trace.cpp util.cpp \
43 execution_object_pipeline.cpp \ 43 execution_object_pipeline.cpp \
44 subgraph_runtime.cpp 44 subgraph_runtime.cpp subgraph_data_conv.cpp
45SRCS_IMGUTIL = imgutil.cpp 45SRCS_IMGUTIL = imgutil.cpp
46SRCS_PYBIND = pybind_eo.cpp pybind_eop.cpp pybind_executor.cpp \ 46SRCS_PYBIND = pybind_eo.cpp pybind_eop.cpp pybind_executor.cpp \
47 pybind_configuration.cpp pybind_helpers.cpp 47 pybind_configuration.cpp pybind_helpers.cpp
diff --git a/tidl_api/src/subgraph_data_conv.h b/tidl_api/inc/subgraph_data_conv.h
index 24920fc..49b4315 100644
--- a/tidl_api/src/subgraph_data_conv.h
+++ b/tidl_api/inc/subgraph_data_conv.h
@@ -26,6 +26,9 @@
26 * THE POSSIBILITY OF SUCH DAMAGE. 26 * THE POSSIBILITY OF SUCH DAMAGE.
27 *****************************************************************************/ 27 *****************************************************************************/
28 28
29#include <stdint.h>
30#include <vector>
31
29namespace tidl { 32namespace tidl {
30 33
31/* @class SubgraphDataConv 34/* @class SubgraphDataConv
@@ -73,10 +76,10 @@ class SubgraphDataConv
73 //! @param None 76 //! @param None
74 SubgraphDataConv() {} 77 SubgraphDataConv() {}
75 78
76 SubgraphDataConv(const vector<bool>& is_signed, 79 SubgraphDataConv(const std::vector<bool>& is_signed,
77 const vector<float>& scaleQ, 80 const std::vector<float>& scaleQ,
78 const vector<bool>& is_NCHW, 81 const std::vector<bool>& is_NCHW,
79 const vector<int>& dims 82 const std::vector<int>& dims
80 ) : is_signed_m(is_signed), scaleQ_m(scaleQ), 83 ) : is_signed_m(is_signed), scaleQ_m(scaleQ),
81 is_NCHW_m(is_NCHW), dims_m(dims) 84 is_NCHW_m(is_NCHW), dims_m(dims)
82 {} 85 {}
@@ -99,7 +102,7 @@ class SubgraphDataConv
99 //! by TIDL 102 //! by TIDL
100 //! @param in floating point vector input to quantize 103 //! @param in floating point vector input to quantize
101 //! @param out 8-bit Quantized output (quantized from in) 104 //! @param out 8-bit Quantized output (quantized from in)
102 void ScaleQuant(const std::vector<float*>& in, uint8_t* out); 105 void ScaleQuant(const std::vector<float*>& in, uint8_t* out) const;
103 106
104 //! @brief De-Quantizes 8-bit Quantized {in} to floating point {out} 107 //! @brief De-Quantizes 8-bit Quantized {in} to floating point {out}
105 //! and transposes buffer from NCHW to NHWC format (if needed), 108 //! and transposes buffer from NCHW to NHWC format (if needed),
@@ -107,7 +110,7 @@ class SubgraphDataConv
107 //! tensor, as expected by external tensors 110 //! tensor, as expected by external tensors
108 //! @param in 8-bit Quantized input to De-Quantize 111 //! @param in 8-bit Quantized input to De-Quantize
109 //! @param out floating point output (De-Quantized from in) 112 //! @param out floating point output (De-Quantized from in)
110 void ScaleDequant(const uint8_t *in, std::vector<float*>& out); 113 void ScaleDequant(const uint8_t *in, std::vector<float*>& out) const;
111 114
112 private: 115 private:
113 //! if tensor needs to be evaluated as signed char 116 //! if tensor needs to be evaluated as signed char
@@ -123,6 +126,6 @@ class SubgraphDataConv
123 126
124 //! flattened 4d dims of external tensors 127 //! flattened 4d dims of external tensors
125 std::vector<int> dims_m; 128 std::vector<int> dims_m;
126} 129};
127 130
128} // namespace tidl 131} // namespace tidl
diff --git a/tidl_api/inc/subgraph_runtime.h b/tidl_api/inc/subgraph_runtime.h
index 09cf970..a38973e 100644
--- a/tidl_api/inc/subgraph_runtime.h
+++ b/tidl_api/inc/subgraph_runtime.h
@@ -33,6 +33,7 @@
33#include <mutex> 33#include <mutex>
34#include <condition_variable> 34#include <condition_variable>
35#include "execution_object_pipeline.h" 35#include "execution_object_pipeline.h"
36#include "subgraph_data_conv.h"
36 37
37 38
38namespace tidl { 39namespace tidl {
@@ -106,8 +107,8 @@ class ResM {
106 void FreeEOP(uint32_t subgraph_id, 107 void FreeEOP(uint32_t subgraph_id,
107 ExecutionObjectPipeline* eop); 108 ExecutionObjectPipeline* eop);
108 Configuration& GetConfiguration(uint32_t subgraph_id); 109 Configuration& GetConfiguration(uint32_t subgraph_id);
109 //const SubgraphDataConv& GetInConv(uint32_t subgraph_id); 110 const SubgraphDataConv& GetInConv(uint32_t subgraph_id);
110 //const SubgraphDataConv& GetOutConv(uint32_t subgraph_id); 111 const SubgraphDataConv& GetOutConv(uint32_t subgraph_id);
111 112
112 113
113 private: 114 private:
@@ -135,6 +136,8 @@ class ResM {
135 std::vector<Executor*> es_m; 136 std::vector<Executor*> es_m;
136 std::vector<Executor*> e2s_m; 137 std::vector<Executor*> e2s_m;
137 std::vector<ResEOP> *eops_m; 138 std::vector<ResEOP> *eops_m;
139 std::vector<SubgraphDataConv*> in_conv_m;
140 std::vector<SubgraphDataConv*> out_conv_m;
138}; 141};
139 142
140} // namespace tidl 143} // namespace tidl
diff --git a/tidl_api/src/subgraph_data_conv.cpp b/tidl_api/src/subgraph_data_conv.cpp
new file mode 100644
index 0000000..d8cc11f
--- /dev/null
+++ b/tidl_api/src/subgraph_data_conv.cpp
@@ -0,0 +1,142 @@
1/******************************************************************************
2 * Copyright (c) 2019 Texas Instruments Incorporated - http://www.ti.com/
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Texas Instruments Incorporated nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 * THE POSSIBILITY OF SUCH DAMAGE.
27 *****************************************************************************/
28
29#include "subgraph_data_conv.h"
30
31using namespace tidl;
32
33
34static inline uint8_t QuantizeValue(float v, float Q, int vmin, int vmax)
35{
36 // scale
37 int32_t qv = (int32_t) (v * Q);
38 // saturate
39 qv = qv < vmin ? vmin : qv;
40 qv = qv > vmax ? vmax : qv;
41 return (uint8_t) qv;
42}
43
44static inline float DequantizeValue(uint8_t v, float Q_inv, bool S)
45{
46 // interpret sign
47 int32_t sv = S ? ((int32_t)(int8_t) v) : ((int32_t) v);
48 // scale
49 return sv * Q_inv;
50}
51
52// Gets 1-d index for 4-d buffer[d][c][b][a]
53static inline int GetIndex(int d, int c, int b, int a,
54 int D, int C, int B, int A)
55{
56 return a + A*(b + B*(c + C*d));
57}
58
59
60void SubgraphDataConv::EstScaleQuant(const std::vector<float*>& in)
61{
62 // TODO
63}
64
65void SubgraphDataConv::EstScaleDequant(const std::vector<float*>& out)
66{
67 // TODO
68}
69
70
71void
72SubgraphDataConv::ScaleQuant(const std::vector<float*>& in, uint8_t* out)
73const
74{
75 int offset = 0;
76 for (uint32_t d = 0; d < is_NCHW_m.size(); d++)
77 {
78 float Q = scaleQ_m[d];
79 int N = dims_m[4 * d + 0];
80 int C = dims_m[4 * d + 1];
81 int H = dims_m[4 * d + 2];
82 int W = dims_m[4 * d + 3];
83 int vmin = is_signed_m[d] ? -128 : 0;
84 int vmax = is_signed_m[d] ? 127 : 255;
85 float *in_d = in[d];
86 if (is_NCHW_m[d]) // no need to transpose external tensor
87 {
88 for (int i = 0; i < N * C * H * W; i++)
89 out[offset + i] = QuantizeValue(in_d[i], Q, vmin, vmax);
90 }
91 else // need to transpose external tensor
92 {
93 for (int n = 0; n < N; n++)
94 for (int c = 0; c < C; c++)
95 for (int h = 0; h < H; h++)
96 for (int w = 0; w < W; w++)
97 {
98 int nchw = GetIndex(n, c, h, w, N, C, H, W);
99 int nhwc = GetIndex(n, h, w, c, N, H, W, C);
100 out[offset + nchw] = QuantizeValue(in_d[nhwc], Q, vmin, vmax);
101 }
102 }
103 offset += N * C * H * W;
104 }
105}
106
107void
108SubgraphDataConv::ScaleDequant(const uint8_t *in, std::vector<float*>& out)
109const
110{
111 int offset = 0;
112 for (uint32_t d = 0; d < is_NCHW_m.size(); d++)
113 {
114 float Q = scaleQ_m[d];
115 float Q_inv = 1.0f / Q;
116 int N = dims_m[4 * d + 0];
117 int C = dims_m[4 * d + 1];
118 int H = dims_m[4 * d + 2];
119 int W = dims_m[4 * d + 3];
120 bool S = is_signed_m[d];
121 float *out_d = out[d];
122 if (is_NCHW_m[d]) // no need to transpose external tensor
123 {
124 for (int i = 0; i < N * C * H * W; i++)
125 out_d[i] = DequantizeValue(in[offset + i], Q_inv, S);
126 }
127 else // need to transpose external tensor
128 {
129 for (int n = 0; n < N; n++)
130 for (int c = 0; c < C; c++)
131 for (int h = 0; h < H; h++)
132 for (int w = 0; w < W; w++)
133 {
134 int nchw = GetIndex(n, c, h, w, N, C, H, W);
135 int nhwc = GetIndex(n, h, w, c, N, H, W, C);
136 out_d[nhwc] = DequantizeValue(in[offset + nchw], Q_inv, S);
137 }
138 }
139 offset += N * C * H * W;
140 }
141}
142
diff --git a/tidl_api/src/subgraph_runtime.cpp b/tidl_api/src/subgraph_runtime.cpp
index 5445b9b..9f68c62 100644
--- a/tidl_api/src/subgraph_runtime.cpp
+++ b/tidl_api/src/subgraph_runtime.cpp
@@ -121,6 +121,10 @@ ResM::~ResM()
121 if (e != nullptr) delete e; 121 if (e != nullptr) delete e;
122 for (const Executor* e : e2s_m) 122 for (const Executor* e : e2s_m)
123 if (e != nullptr) delete e; 123 if (e != nullptr) delete e;
124 for (SubgraphDataConv *dc : in_conv_m)
125 if (dc != nullptr) delete dc;
126 for (SubgraphDataConv *dc : out_conv_m)
127 if (dc != nullptr) delete dc;
124} 128}
125 129
126ResM& ResM::Instance(uint32_t total_num_subgraphs) 130ResM& ResM::Instance(uint32_t total_num_subgraphs)
@@ -155,6 +159,15 @@ void ResM::Init(uint32_t num_subgraphs)
155 es_m.resize(num_subgraphs_m, nullptr); 159 es_m.resize(num_subgraphs_m, nullptr);
156 e2s_m.resize(num_subgraphs_m, nullptr); 160 e2s_m.resize(num_subgraphs_m, nullptr);
157 eops_m = new std::vector<ResEOP>(num_subgraphs_m); 161 eops_m = new std::vector<ResEOP>(num_subgraphs_m);
162
163 // TODO: this should come from parsing config file
164 for (uint32_t i = 0; i < num_subgraphs_m; i++)
165 {
166 in_conv_m.push_back(new SubgraphDataConv(
167 {true}, {128.0f}, {false}, {1,3,224,224}));
168 out_conv_m.push_back(new SubgraphDataConv(
169 {false}, {255.0f}, {true}, {1,1,1,1001}));
170 }
158 } 171 }
159} 172}
160 173
@@ -318,4 +331,15 @@ Configuration& ResM::GetConfiguration(uint32_t subgraph_id)
318 return cs_m[subgraph_id]; 331 return cs_m[subgraph_id];
319} 332}
320 333
334const SubgraphDataConv& ResM::GetInConv(uint32_t subgraph_id)
335{
336 assert(in_conv_m[subgraph_id] != nullptr);
337 return *in_conv_m[subgraph_id];
338}
339
340const SubgraphDataConv& ResM::GetOutConv(uint32_t subgraph_id)
341{
342 assert(out_conv_m[subgraph_id] != nullptr);
343 return *out_conv_m[subgraph_id];
344}
321 345