Skip to content

Commit d3041f5

Browse files
authored
Merge pull request #1110 from inocsin/slice
[feat]: support slice with dynamic shape
2 parents 5ad9826 + 90c5194 commit d3041f5

File tree

6 files changed

+570
-153
lines changed

6 files changed

+570
-153
lines changed

core/conversion/converters/converter_util.cpp

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,131 @@ nvinfer1::ITensor* tensor_to_const(ConversionCtx* ctx, at::Tensor t, const std::
199199
return out;
200200
}
201201

202+
// clamp x to [lower_bound, upper_bound]
203+
nvinfer1::ITensor* clamp(
204+
ConversionCtx* ctx,
205+
nvinfer1::ITensor* x,
206+
nvinfer1::ITensor* lower_bound,
207+
nvinfer1::ITensor* upper_bound,
208+
std::string const& name) {
209+
210+
auto max_layer = add_elementwise(ctx, nvinfer1::ElementWiseOperation::kMAX, x, lower_bound, "max layer for " + name);
211+
TORCHTRT_CHECK(max_layer, "Unable to create max layer for clamp");
212+
LOG_DEBUG(ctx->logger, "Create " << max_layer->getName() << " for clamp");
213+
auto max_itensor = max_layer->getOutput(0);
214+
215+
auto min_layer = add_elementwise(ctx, nvinfer1::ElementWiseOperation::kMIN, max_itensor, upper_bound, "min layer for " + name);
216+
TORCHTRT_CHECK(min_layer, "Unable to create min layer for clamp");
217+
LOG_DEBUG(ctx->logger, "Create " << min_layer->getName() << " for clamp");
218+
auto min_itensor = min_layer->getOutput(0);
219+
return min_itensor;
220+
}
221+
222+
// clamp x to [0, input_dim]
223+
nvinfer1::ITensor* clamp_to_input_dim(
224+
ConversionCtx* ctx,
225+
nvinfer1::ITensor* x,
226+
nvinfer1::ITensor* input_dim,
227+
int nbdims,
228+
std::string const& name) {
229+
230+
auto zero = torch::zeros({nbdims}).to(torch::kI32);
231+
auto zero_itensor = tensor_to_const(ctx, zero);
232+
auto one = torch::ones({nbdims}).to(torch::kI32);
233+
auto one_itensor = tensor_to_const(ctx, one);
234+
235+
auto upper_bound_layer = add_elementwise(ctx, nvinfer1::ElementWiseOperation::kSUB, input_dim, one_itensor, "sub layer for " + name);
236+
TORCHTRT_CHECK(upper_bound_layer, "Unable to create sub layer for clamp to inputDim");
237+
LOG_DEBUG(ctx->logger, "Create " << upper_bound_layer->getName() << " for clamp to inputDim");
238+
auto upper_bound = upper_bound_layer->getOutput(0);
239+
240+
auto max_layer = add_elementwise(ctx, nvinfer1::ElementWiseOperation::kMAX, x, zero_itensor, "max layer for " + name);
241+
TORCHTRT_CHECK(max_layer, "Unable to create max_layer for clamp to inputDim");
242+
LOG_DEBUG(ctx->logger, "Create " << max_layer->getName() << " for clamp to inputDim");
243+
auto max_itensor = max_layer->getOutput(0);
244+
245+
auto min_layer = add_elementwise(ctx, nvinfer1::ElementWiseOperation::kMIN, max_itensor, upper_bound, "min layer for " + name);
246+
TORCHTRT_CHECK(min_layer, "Unable to create min_layer for clamp to inputDim");
247+
LOG_DEBUG(ctx->logger, "Create " << min_layer->getName() << " for clamp to inputDim");
248+
auto min_itensor = min_layer->getOutput(0);
249+
return min_itensor;
250+
}
251+
252+
// return indices < 0 ? inputDims + indices : indices
253+
nvinfer1::ITensor* normalize_indices(
254+
ConversionCtx* ctx,
255+
nvinfer1::ITensor* input_dim,
256+
nvinfer1::ITensor* indices,
257+
int nbdims,
258+
std::string const& name) {
259+
260+
auto zero = torch::zeros({nbdims}).to(torch::kI32);
261+
auto neg = -torch::ones({nbdims}).to(torch::kI32);
262+
auto zero_itensor = tensor_to_const(ctx, zero);
263+
auto neg_itensor = tensor_to_const(ctx, neg);
264+
// find the indices that = -1
265+
auto signs = clamp(ctx, indices, neg_itensor, zero_itensor, "clamp layer for " + name);
266+
267+
// get the inputDim value where indices == -1, else 0
268+
auto mul = add_elementwise(ctx, nvinfer1::ElementWiseOperation::kPROD, signs, input_dim, "prod layer for " + name);
269+
TORCHTRT_CHECK(mul, "Unable to create mul layer in normalize_indices");
270+
LOG_DEBUG(ctx->logger, "Create " << mul->getName() << " for normalize_indices");
271+
auto mul_itensor = mul->getOutput(0);
272+
273+
// add the inputDim value to indices where indices == -1
274+
auto sub = add_elementwise(ctx, nvinfer1::ElementWiseOperation::kSUB, indices, mul_itensor, "sub layer for " + name);
275+
TORCHTRT_CHECK(sub, "Unable to create sub layer in normalize_indices");
276+
LOG_DEBUG(ctx->logger, "Create " << sub->getName() << " for normalize_indices");
277+
auto sub_itensor = sub->getOutput(0);
278+
return sub_itensor;
279+
}
280+
281+
std::vector<nvinfer1::ITensor*> normalize_start_and_end(
282+
ConversionCtx* ctx,
283+
nvinfer1::ITensor* in_shape,
284+
nvinfer1::ITensor* in_start,
285+
nvinfer1::ITensor* in_end,
286+
int nbdims,
287+
std::string const& name) {
288+
auto start = normalize_indices(ctx, in_shape, in_start, nbdims, "normalize start of " + name);
289+
auto out_start = clamp_to_input_dim(ctx, start, in_shape, nbdims, "clamp start to inputDim for " + name);
290+
auto end = normalize_indices(ctx, in_shape, in_end, nbdims, "normalize end of " + name);
291+
auto out_end = clamp_to_input_dim(ctx, end, in_shape, nbdims, "clamp end to inputDim for " + name);
292+
std::vector<nvinfer1::ITensor*> outputs;
293+
outputs.push_back(out_start);
294+
outputs.push_back(out_end);
295+
return outputs;
296+
}
297+
298+
// size = (end - start) / stride + 1, where range is [start, end], end is included
299+
nvinfer1::ITensor* get_slice_size(
300+
ConversionCtx* ctx,
301+
nvinfer1::ITensor* start,
302+
nvinfer1::ITensor* end,
303+
nvinfer1::ITensor* stride,
304+
int nbdims,
305+
std::string const& name) {
306+
at::Tensor one_tensor = torch::ones({nbdims}).to(torch::kI32);
307+
auto one_itensor = tensor_to_const(ctx, one_tensor);
308+
309+
auto sub_layer = add_elementwise(ctx, nvinfer1::ElementWiseOperation::kSUB, end, start, "get_slice_size sub layer for " + name);
310+
TORCHTRT_CHECK(sub_layer, "Unable to create sub layer in calculate_output_size");
311+
LOG_DEBUG(ctx->logger, "Create " << sub_layer->getName() << " for calculate_output_size");
312+
auto sub_itensor = sub_layer->getOutput(0);
313+
314+
auto div_layer = add_elementwise(ctx, nvinfer1::ElementWiseOperation::kDIV, sub_itensor, stride, "get_slice_size div layer for " + name);
315+
TORCHTRT_CHECK(div_layer, "Unable to create div layer in calculate_output_size");
316+
LOG_DEBUG(ctx->logger, "Create " << div_layer->getName() << " for calculate_output_size");
317+
auto div_itensor = div_layer->getOutput(0);
318+
319+
auto add_layer = add_elementwise(ctx, nvinfer1::ElementWiseOperation::kSUM, div_itensor, one_itensor, "get_slice_size sum layer for " + name);
320+
TORCHTRT_CHECK(add_layer, "Unable to create add layer in calculate_output_size");
321+
LOG_DEBUG(ctx->logger, "Create " << add_layer->getName() << " for calculate_output_size");
322+
auto size_itensor = add_layer->getOutput(0);
323+
324+
return size_itensor;
325+
}
326+
202327
} // namespace converters
203328
} // namespace conversion
204329
} // namespace core

core/conversion/converters/converter_util.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <map>
44
#include <string>
5+
#include <limits>
56

67
#include "core/conversion/conversionctx/ConversionCtx.h"
78
#include "core/conversion/converters/Weights.h"
@@ -50,6 +51,35 @@ nvinfer1::ITensor* castITensor(ConversionCtx* ctx, nvinfer1::ITensor* tensor, nv
5051
// Freeze an at::Tensor in a IConstant layer
5152
nvinfer1::ITensor* tensor_to_const(ConversionCtx* ctx, at::Tensor t, const std::string& name = std::string());
5253

54+
nvinfer1::ITensor* clamp(
55+
ConversionCtx* ctx,
56+
nvinfer1::ITensor* x,
57+
nvinfer1::ITensor* lower_bound,
58+
nvinfer1::ITensor* upper_bound,
59+
std::string const& name);
60+
61+
nvinfer1::ITensor* normalize_indices(
62+
ConversionCtx* ctx,
63+
nvinfer1::ITensor* input_dim,
64+
nvinfer1::ITensor* indices,
65+
std::string const& name);
66+
67+
std::vector<nvinfer1::ITensor*> normalize_start_and_end(
68+
ConversionCtx* ctx,
69+
nvinfer1::ITensor* in_shape,
70+
nvinfer1::ITensor* in_start,
71+
nvinfer1::ITensor* in_end,
72+
int nbdims,
73+
std::string const& name);
74+
75+
nvinfer1::ITensor* get_slice_size(
76+
ConversionCtx* ctx,
77+
nvinfer1::ITensor* start,
78+
nvinfer1::ITensor* end,
79+
nvinfer1::ITensor* stride,
80+
int nbdims,
81+
std::string const& name);
82+
5383
} // namespace converters
5484
} // namespace conversion
5585
} // namespace core

0 commit comments

Comments
 (0)