@@ -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
0 commit comments