Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ROperator_ConvTranspose.hxx
Go to the documentation of this file.
1#ifndef TMVA_SOFIE_ROPERATOR_CONVTRANSPOSE_HXX
2#define TMVA_SOFIE_ROPERATOR_CONVTRANSPOSE_HXX
3
5#include <TMVA/ROperator.hxx>
6#include <TMVA/RModel.hxx>
7
8#include <memory>
9#include <sstream>
10#include <algorithm>
11#include <stdexcept>
12#include <vector>
13#include <cassert>
14
16
17/*! \brief Transposed Convolution operator
18 *
19 * Inference code generation for a transposed convolution layer.
20 * See the <a href="https://github.com/onnx/onnx/blob/main/docs/Operators.md#convtranspose">ONNX documentation</a> for
21 * details about the transposed conv layer.
22 */
23template <typename T>
25private:
26 std::string fAttrAutopad;
27 std::vector<size_t> fAttrDilations;
28 size_t fAttrGroup;
29 std::vector<size_t> fAttrKernelShape;
30 std::vector<size_t> fAttrOutputPadding;
31 std::vector<size_t> fAttrOutputShape;
32 std::vector<size_t> fAttrPads;
33 std::vector<size_t> fAttrStrides;
34
35 std::string fNX;
36 std::string fNW;
37 std::string fNB;
38 std::string fNBroadcastedB;
39 std::string fNY;
40
41 std::string fConvK;
42 std::string fImcol;
43
44 std::vector<size_t> fShapeX;
45 std::vector<size_t> fShapeW;
46 std::vector<size_t> fShapeB;
47 std::vector<size_t> fShapeY;
48
49 std::string fType;
50
51 size_t fDim; // dimension of the convolution
52
53public:
54 /*! Default constructor of ROperator_ConvTranspose */
56
57 /*! \brief Constructor of ROperator_ConvTranspose from the attributes
58 *
59 * \param autopad padding
60 * \param dilations dilations of the kernel
61 * \param group number of groups
62 * \param kernelShape shape of the kernel
63 * \param outputPadding padding of the output
64 * \param outputShape shape of the output
65 * \param pads padding of the input
66 * \param strides strides
67 * \param nameX name of the input
68 * \param nameW name of the weight
69 * \param nameB name of the bias
70 * \param nameY name of the output
71 */
72 ROperator_ConvTranspose(std::string autopad, std::vector<size_t> dilations, size_t group,
73 std::vector<size_t> kernelShape, std::vector<size_t> outputPadding,
74 std::vector<size_t> outputShape, std::vector<size_t> pads, std::vector<size_t> strides,
75 std::string nameX, std::string nameW, std::string nameB, std::string nameY)
77 fAttrDilations(dilations),
82 fAttrPads(pads),
83 fAttrStrides(strides),
84 fNX(UTILITY::Clean_name(nameX)),
85 fNW(UTILITY::Clean_name(nameW)),
86 fNB(UTILITY::Clean_name(nameB)),
87 fNY(UTILITY::Clean_name(nameY))
88 {
91 if (!fNB.empty()) {
92 fInputTensorNames.emplace_back(fNB);
93 }
94
95 if (std::is_same<T, float>::value) {
96 fType = "float";
97 } else {
98 throw std::runtime_error("TMVA SOFIE Encountered unsupported type parsing a Conv operator");
99 }
100 }
101
102 /*! \brief Infers the shape of the input tensors
103 * \param input shape of the input tensors
104 */
105 std::vector<std::vector<size_t>> ShapeInference(std::vector<std::vector<size_t>> /*input*/);
106
107 /*! \brief Initialize the model
108 * \param model Model
109 */
110 void Initialize(RModel &) override;
111
112 /*! \brief Generate code for initializing the op
113 */
114 std::string GenerateInitCode() override;
115
116 /*! \brief Generate the inference code
117 * \param opName name of the operator
118 */
119 std::string Generate(std::string opName) override;
120
121 /*! \brief Returns the blas routines needed to compile the generated code
122 */
123 std::vector<std::string> GetBlasRoutines() override { return {std::string("Gemm"), std::string("Axpy")}; }
124};
125
126template <typename T>
127auto ROperator_ConvTranspose<T>::ShapeInference(std::vector<std::vector<size_t>> input)
128 -> std::vector<std::vector<size_t>>
129{
130 const std::vector<size_t> &inputShape = input[0];
131 const std::vector<size_t> &weightShape = input[1];
132 size_t size = inputShape.size();
133 // Dimension of the conv transpose op
134 fDim = size - 2;
135 // Number of groups
136 if (fAttrGroup == 0)
137 fAttrGroup = 1;
138 if (fAttrStrides.empty()) {
139 fAttrStrides = std::vector<size_t>(fDim, 1);
140 }
141 if (fAttrDilations.empty()) {
142 fAttrDilations = std::vector<size_t>(fDim, 1);
143 }
144 // The shape of the kernel is kw for 1d image, kh x Kw for 2d images and kd x kh x kw for a 3d image
145 if (fAttrKernelShape.empty()) {
146 fAttrKernelShape.resize(fDim);
147 for (size_t i = 0; i < fDim; i++)
148 fAttrKernelShape[i] = fShapeW[i + 2] + (fAttrDilations[i] - 1) * (fShapeW[i + 2] - 1);
149 }
150 if (fAttrOutputPadding.empty())
151 fAttrOutputPadding = std::vector<size_t>(fDim, 0);
152
153 // The Shape of the output is batch_size x out_channel x out_w for a 1d image,
154 // batch_size x out_channel x out_h x out_w for a 2d image and
155 // batch_size x out_channel x out_d x out_h x out_w for a 3d image
156 // where out_channel = weight_shape[1] * group
157 std::vector<size_t> outShape(size);
158 outShape[0] = inputShape[0];
159 outShape[1] = weightShape[1] * fAttrGroup;
160
161 // Generate the padding
162 if (fAttrPads.empty()) {
163 fAttrPads = std::vector<size_t>(2 * fDim, 0);
164
165 if (fAttrAutopad != "NOTSET") {
166 throw std::runtime_error("ConvTranspose with padding SAME_UPPER or SMAE_LOWER not supported");
167 }
168 }
169 if (fAttrOutputShape.empty()) {
170 fAttrOutputShape.resize(fDim);
171 for (size_t i = 0; i < fDim; i++) {
172 size_t j = i + 2;
173 fAttrOutputShape[i] = fAttrStrides[i] * (inputShape[j] - 1) + fAttrKernelShape[i] + fAttrOutputPadding[i] -
174 fAttrPads[i] - fAttrPads[fDim + i];
175 }
176 } else {
177 // The shape of the output is explicitly set
178 fAttrPads = std::vector<size_t>(2 * fDim, 0);
179 for (size_t i = 0; i < fDim; ++i) {
180 size_t input_shape = inputShape[i + 2];
181 size_t output_shape = fAttrOutputShape[i];
182 size_t kernel_shape = weightShape[i + 2];
183
184 size_t stride = fAttrStrides[i];
185 size_t dilation = fAttrDilations[i];
186 size_t output_padding = fAttrOutputPadding[i];
187
188 size_t effective_kernel_shape = (kernel_shape - 1) * dilation + 1;
190
192 throw std::runtime_error("ConvTranspose: explicitly set output_shape is too large for "
193 "the given input and kernel shapes.");
194 }
195
197
198 fAttrPads[i + fDim] = total_padding / 2;
199 fAttrPads[i] = total_padding - fAttrPads[i + fDim];
200 }
201 }
202
203 for (size_t i = 0; i < fDim; i++)
204 outShape[i + 2] = fAttrOutputShape[i];
205 std::vector<std::vector<size_t>> ret({outShape});
206 return ret;
207}
208
209template <typename T>
211{
212
213 if (!model.CheckIfTensorAlreadyExist(fNX)) {
214 throw std::runtime_error("TMVA SOFIE Conv Transpose op Input Tensor " + fNX + " is not found in model");
215 }
216 fShapeX = model.GetTensorShape(fNX);
217 if (fShapeX.size() < 3 || fShapeX.size() > 5) {
218 std::cout << fNX << " : " << ConvertShapeToString(fShapeX) << std::endl;
219 throw std::runtime_error("TMVA SOFIE Conv Transpose Op input data tensor" + fNX +
220 " is not of 3,4 or 5 dimensions");
221 }
222 fDim = fShapeX.size() - 2;
223 if (!model.CheckIfTensorAlreadyExist(fNW)) {
224 throw std::runtime_error("TMVA SOFIE Conv op Input weight Tensor " + fNW + " is not found in model");
225 }
226 fShapeW = model.GetTensorShape(fNW);
227 if (fShapeW.size() < 3 || fShapeW.size() > 5) {
228 std::cout << fNW << " : " << ConvertShapeToString(fShapeW) << std::endl;
229 throw std::runtime_error("TMVA SOFIE Conv Transpose Op input weight tensor" + fNW +
230 " is not of 3,4 or 5 dimensions");
231 }
232 fShapeY = ShapeInference({fShapeX, fShapeW})[0];
233
234 model.AddIntermediateTensor(fNY, model.GetTensorType(fNX), fShapeY);
235 if (fNB != "") {
236 if (!model.CheckIfTensorAlreadyExist(fNB)) {
237 throw std::runtime_error("TMVA SOFIE ConvTrans op Input Tensor " + fNB + " is not found in model");
238 }
239 fShapeB = model.GetTensorShape(fNB);
240 if (fShapeB.size() < 1)
241 throw std::runtime_error("TMVA SOFIE ConvTrans op: Bias Tensor has empty shape");
242
243 size_t bsize = ConvertShapeToLength(fShapeB);
244 size_t ysize = ConvertShapeToLength(fShapeY);
245 // broadcasting is needed if first stride of B is not same of Y
246 bool broadcast_needed = (bsize != ysize);
247 // Broadcast the bias B
248 if (broadcast_needed) {
249 // we assume bias tensor size is equal to number of filters that is the second dimension in
250 // the output tensor
251 if (bsize != fShapeY[1])
252 throw std::runtime_error("TMVA SOFIE ConvTrans op: Bias Tensor has wrong shape: " +
253 ConvertShapeToString(fShapeB));
254
255 if (fType != "float")
256 throw std::runtime_error(
257 "TMVA SOFIE ConvTrans op: Broadcasting for non-float type tensors is not supported");
258 // Add broadcasting code in Session constructor and in GenerateInitCode:
259 // we need to add a new intermediate tensor for broadcasted bias tensor
260 fNBroadcastedB = "Broadcasted" + fNB;
261 model.AddIntermediateTensor(fNBroadcastedB, model.GetTensorType(fNB), fShapeY);
262 } else {
263 // bias tensor is already correct shape, no need to broadcast
264 if (fShapeY != fShapeB)
265 throw std::runtime_error("TMVA SOFIE ConvTrans op: Broadcasting is not needed but bias has wrong shape" +
266 ConvertShapeToString(fShapeB));
267 fNBroadcastedB = fNB;
268 }
269 }
270
271 size_t kernelSize = 1;
272 size_t inputSize = 1;
273 for (size_t i = 0; i < fDim; i++) {
274 inputSize *= fShapeX[2 + i];
275 kernelSize *= fAttrKernelShape[i];
276 }
277
278 std::vector<size_t> shape1 = {fShapeW[0], fShapeW[1], kernelSize};
279 std::vector<size_t> shape2 = {fShapeW[1], kernelSize, inputSize};
280 // private workspaces of this node, named after its output (see ROperator_Conv)
281 model.AddIntermediateTensor(fNY + "_f", ConvertStringToType(fType), shape1);
282 model.AddIntermediateTensor(fNY + "_xcol", ConvertStringToType(fType), shape2);
283 fConvK = fNY + "_f";
284 fImcol = fNY + "_xcol";
285 fOutputTensorNames.emplace_back(fConvK);
286 fOutputTensorNames.emplace_back(fImcol);
287
288 // register the inference helper functions used by the generated code
289 // (only the <3D case is supported, which uses col2im)
290 model.AddNeededHelperFunction("col2im");
291 if (!fNB.empty())
292 model.AddNeededHelperFunction("BroadcastConvBias");
293}
294
295template <typename T>
297{
298 std::stringstream out;
299 // generate initialization code for broadcasting of bias tensor
300 size_t bsize = ConvertShapeToLength(fShapeB);
301 size_t ysize = ConvertShapeToLength(fShapeY);
302 if (bsize != ysize && !fNBroadcastedB.empty()) {
303 // include a separate scope to avoid defining unique operator temp variables
304 out << SP << "{\n";
305 out << SP << SP << "float * data = UTILITY::BroadcastConvBias<float>(tensor_" << fNB << ", " << bsize << ", "
306 << ConvertShapeToString(fShapeY) << ");\n";
307 out << SP << SP << "std::copy(data, data + " << ConvertShapeToLength(fShapeY) << ", tensor_" << fNBroadcastedB
308 << ");\n";
309 out << SP << SP << "delete[] data;\n";
310 out << SP << "}\n";
311 }
312 return out.str();
313}
314
315template <typename T>
317{
318 OpName = "op_" + OpName;
319
320 if (fShapeX.empty() || fShapeW.empty() || (fNB != "" && fShapeB.empty()) || fShapeY.empty()) {
321 throw std::runtime_error("TMVA SOFIE Conv Op called to Generate without being initialized first");
322 }
323
324 std::stringstream out;
325
326 size_t bsize = fShapeX[0];
327 size_t kDepth = (fDim > 2) ? fShapeW[2] : 1; // kernel depth
328 size_t kHeight = (fDim > 1) ? fShapeW[fDim] : 1; // kernel height
329 size_t kWidth = fShapeW[fDim + 1]; // kernel width
330
331 size_t iDepth = (fDim > 2) ? fShapeX[2] : 1; // input depth
332 size_t iHeight = (fDim > 1) ? fShapeX[fDim] : 1; // input height
333 size_t iWidth = fShapeX[fDim + 1]; // input width
334
335 size_t oDepth = (fDim > 2) ? fShapeY[2] : 1; // output depth
336 size_t oHeight = (fDim > 1) ? fShapeY[fDim] : 1; // ouput height
337 size_t oWidth = fShapeY[fDim + 1]; // output width
338
339 out << "\n//---- operator ConvTranspose " << OpName << "\n";
340
341 // vectorize the (dilated)convolution kernels into a matrix
342 // The shape of the kernel is W for 1d image, H x W for 2d image and D x H x W
343 // for 3d image
344 size_t id = (fDim > 2) ? fDim - 3 : 2;
345 size_t ih = (fDim > 1) ? fDim - 2 : 1;
346 size_t iw = fDim - 1;
347 size_t wstrideDil = fAttrDilations[iw];
348 size_t hstride = kWidth;
349 size_t hstrideDil = fAttrKernelShape[iw];
350 if (fDim > 1)
351 hstrideDil *= fAttrDilations[ih];
352 // stride dilated in the height
353 size_t dstride = kHeight * kWidth;
354 size_t dstrideDil = fAttrKernelShape[iw];
355 if (fDim > 1)
356 dstrideDil *= fAttrKernelShape[ih];
357 if (fDim > 2)
358 dstrideDil *= fAttrDilations[id];
359 size_t icstride = kHeight * kWidth * kDepth;
360 size_t icstrideDil = 1;
361 for (size_t i = 0; i < fDim; i++)
362 icstrideDil *= fAttrKernelShape[i];
363 size_t ocstride = fShapeW[1] * icstride;
364 size_t ocstrideDil = fShapeW[1] * icstrideDil;
365
366 // The shape of f is [M/group, kHeight x kWidth]
367 out << SP << "for (std::size_t ic = 0; ic < " << fShapeW[0] << "; ic++) {\n";
368 out << SP << SP << "for (std::size_t oc = 0; oc < " << fShapeW[1] << "; oc++) {\n";
369 // out << SP << SP << SP << "size_t kIndex = 0;\n"; // filter index
370 if (fDim > 2)
371 out << SP << SP << SP << "for (std::size_t kd = 0; kd < " << kDepth << "; kd++) {\n";
372 if (fDim > 1)
373 out << SP << SP << SP << "for (std::size_t kh = 0; kh < " << kHeight << "; kh++) {\n";
374 out << SP << SP << SP << SP << "for (std::size_t kw = 0; kw < " << kWidth << "; kw++) {\n";
375
376 out << SP << SP << SP << SP << SP << "tensor_" << fConvK << "[ic * " << ocstrideDil << " + oc * " << icstrideDil;
377 if (fDim > 2)
378 out << " + kd * " << dstrideDil;
379 if (fDim > 1)
380 out << " + kh * " << hstrideDil;
381 out << " + kw * " << wstrideDil << " ] = tensor_" << fNW << "[ic * " << ocstride << " + oc * " << icstride;
382
383 if (fDim > 2)
384 out << " + kd * " << dstride;
385 if (fDim > 1)
386 out << " + kh * " << hstride;
387 out << " + kw ];\n";
388
389 // here we rotate the input kernel tranforming 0,1,2,...N-1 in N-1,N-2,...,2,1,0
390 // out << " + " << icstride -1 << " - kIndex ];\n"; // tranform 1,2,3,4 in 4,3,2,1
391 // out << SP << SP << SP << SP << SP << "kIndex++;\n"; // update input filter index
392
393 out << SP << SP << SP << SP << "}\n";
394 if (fDim > 1)
395 out << SP << SP << SP << "}\n";
396 if (fDim > 2)
397 out << SP << SP << SP << "}\n";
398
399 out << SP << SP << "}\n";
400 out << SP << "}\n";
401
402 out << SP << "char " << OpName << "_transA = 'N';\n";
403 out << SP << "char " << OpName << "_transB = 'T';\n";
404 out << SP << "int " << OpName << "_m = " << iHeight * iWidth * iDepth << ";\n";
405 out << SP << "int " << OpName << "_n = " << icstrideDil * fShapeW[1] << ";\n"; // output channels * filters
406 out << SP << "int " << OpName << "_k = " << fShapeW[0] << ";\n"; // input channels
407 out << SP << "float " << OpName << "_alpha = 1.0;\n";
408 out << SP << "float " << OpName << "_beta = 0.0;\n";
409
410 // Loop on batch size
411 out << SP << "for (size_t n = 0; n < " << bsize << "; n++) {\n";
412
413 // IM2COL: Unroll the input tensor
414 // order input data as (e.g. kernel 2x2) and (xa,ya) is channel 1 and (xb,yb) is channel 2
415 // (xa1,..,xak,ya1,..yak)(xb1,...,xbk,yb1,..,ybk)
416 // (xa2,...xak+1,ya1,...yak)(......)
417 // trick for speed is using caffe im2col and output a matrix which contains filtered values as rows.
418 // By doing this one has consecutive memory reads and writes
419 // Resulting matrix op_xcol is (output channels * filter_h * filter_w , output_h * output_w)
420
421 if (fAttrGroup == 1) {
422 out << SP << SP << "size_t x_offset = n * " << fShapeX[1] * iDepth * iHeight * iWidth << ";\n";
423 out << SP << SP << "size_t out_offset = n * " << fShapeY[1] * oDepth * oHeight * oWidth << ";\n";
424
425 // DO BLAS before:
426 // BLAS
427 out << SP << SP << "BLAS::sgemm_(&" << OpName << "_transA, &" << OpName << "_transB, &" << OpName << "_m, &"
428 << OpName << "_n, &" << OpName << "_k, &" << OpName << "_alpha, "
429 << "tensor_" << fNX << " + x_offset, &" << OpName
430 << "_m,\n"; // use m if op_xcol is not transpose , otherwise k
431 out << SP << SP << SP << "tensor_" << fConvK << ", &" << OpName << "_n, &" << OpName << "_beta, tensor_" << fImcol
432 << ", &" << OpName << "_m);\n";
433
434 // when using im2col - resulting matrix is transposed, is (input_c * filter_h * filter_w, output_h *
435 // output_w)
436 // before using col2im I need to transpose matrix
437 if (fDim < 3) {
438 out << SP << SP << "UTILITY::col2im<float>(tensor_" << fImcol
439 << ","
440 // channels, height, width, kernel_h, kernel_w, pad_h_begin, pad_h_end, pad_w_begin, pad_w_end,
441 // stride_h, stride_w, dilation_h, dilation_w,
442 << fShapeY[1] << "," << oHeight << "," << oWidth << ",";
443 if (fDim == 1)
444 out << "1, " << fAttrKernelShape[0] << ",0,0," << fAttrPads[0] << "," << fAttrPads[1] << ",1,"
445 << fAttrStrides[0] << ",1," << fAttrDilations[0];
446 else // dim ==2
447 out << fAttrKernelShape[0] << "," << fAttrKernelShape[1] << "," << fAttrPads[0] << "," << fAttrPads[2]
448 << "," << fAttrPads[1] << "," << fAttrPads[3] << "," << fAttrStrides[0] << "," << fAttrStrides[1] << ","
449 << fAttrDilations[0] << "," << fAttrDilations[1];
450 out << ", tensor_" << fNY << " + out_offset);\n\n ";
451 } else {
452 // 3d : needs a col2im for 3d
453 throw std::runtime_error("TMVA SOFIE 3D Conv Transpose not yet supported");
454 out << SP << SP << "UTILITY::Im2col_3d<float>(tensor_" << fNX
455 << " + x_offset,"
456 // channels, d, h, w, k_d, k_h, k_w, pad_d_begin, pad_d_end, pad_h_begin, pad_h_end,
457 // pad_w_begin, pad_w_end, stride_d, stride_h, stride_w, dilation_d, dilation_h, dilation_w,
458 //
459 << fShapeX[1] << "," << oDepth << "," << oHeight << "," << oWidth << "," << fAttrKernelShape[0] << ","
460 << fAttrKernelShape[1] << "," << fAttrKernelShape[2] << "," << fAttrPads[0] << "," << fAttrPads[3] << ","
461 << fAttrPads[1] << "," << fAttrPads[4] << "," << fAttrPads[2] << "," << fAttrPads[5] << ","
462 << fAttrStrides[0] << "," << fAttrStrides[1] << "," << fAttrStrides[2] << "," << fAttrDilations[0] << ","
463 << fAttrDilations[1] << "," << fAttrDilations[2] << ",tensor_" << fImcol << ");\n\n ";
464 }
465 // // BLAS
466 // out << SP << SP << "BLAS::sgemm_(&" << OpName << "_transA, &" << OpName << "_transB, &" << OpName << "_m, &"
467 // << OpName << "_n, &" << OpName << "_k, &" << OpName << "_alpha, tensor_" << fImcol << ", &" << OpName
468 // << "_m,\n"; // use m if op_xcol is not transpose , otherwise k
469 // out << SP << SP << SP <<"tensor_" << fConvK << ", &" << OpName << "_k, &" << OpName << "_beta, tensor_" << fNY
470 // << " + out_offset, &" << OpName << "_m);\n";
471 } else {
472 // case of group transposed convolution
473 // Unroll (IM2COL) the input tensor- make loop on groups and repeat operations (IM2COL + GEMM for each
474 // group)
475 out << SP << SP << "for (size_t g = 0; g < " << fAttrGroup << "; g++) {\n";
476 out << SP << SP << "size_t x_offset = n * " << fShapeX[1] * iHeight * iWidth << " + g * "
477 << fShapeX[1] * iHeight * iWidth / fAttrGroup << ";\n ";
478 out << SP << SP << "size_t out_offset = n * " << fShapeY[1] * oHeight * oWidth << " + g * "
479 << fShapeY[1] * oHeight * oWidth / fAttrGroup << ";\n ";
480
481 // do BLAS here (LM: probably need an offset for op_f the kernels)
482 out << SP << SP << "BLAS::sgemm_(&" << OpName << "_transA, &" << OpName << "_transB, &" << OpName << "_m, &"
483 << OpName << "_n, &" << OpName << "_k, &" << OpName << "_alpha, "
484 << "tensor_" << fNX << " + x_offset, &" << OpName
485 << "_m,\n"; // use m if op_xcol is not transpose , otherwise k
486 out << SP << SP << SP << "tensor_" << fConvK << ", &" << OpName << "_n, &" << OpName << "_beta, tensor_" << fImcol
487 << " , &" << OpName << "_m);\n";
488
489 if (fDim < 3) {
490 out << SP << SP << "UTILITY::col2im<float>(tensor_" << fImcol
491 << ","
492 // channels, height, width, kernel_h, kernel_w, pad_h_begin, pad_h_end, pad_w_begin, pad_w_end,
493 // stride_h, stride_w, dilation_h, dilation_w,
494 << fShapeY[1] << "," << oHeight << "," << oWidth << ",";
495 if (fDim == 1)
496 out << "1, " << fAttrKernelShape[0] << ",0,0," << fAttrPads[0] << "," << fAttrPads[1] << ",1,"
497 << fAttrStrides[0] << ",1," << fAttrDilations[0];
498 else // dim ==2
499 out << fAttrKernelShape[0] << "," << fAttrKernelShape[1] << "," << fAttrPads[0] << "," << fAttrPads[2]
500 << "," << fAttrPads[1] << "," << fAttrPads[3] << "," << fAttrStrides[0] << "," << fAttrStrides[1] << ","
501 << fAttrDilations[0] << "," << fAttrDilations[1];
502 out << ", tensor_" << fNY << " + out_offset);\n\n ";
503 } else {
504 // 3d im2col
505 throw std::runtime_error("TMVA SOFIE 3D Conv Transpose not yet supported");
506
507 out << SP << SP << "UTILITY::Im2col_3d<float>(tensor_" << fNX
508 << " + x_offset,"
509 // channels, d, h, w, k_d, k_h, k_w, pad_d_begin, pad_d_end, pad_h_begin, pad_h_end,
510 // pad_w_begin, pad_w_end, stride_d, stride_h, stride_w, dilation_d, dilation_h, dilation_w,
511 //
512 << fShapeX[1] << "," << oDepth << "," << oHeight << "," << oWidth << "," << fAttrKernelShape[0] << ","
513 << fAttrKernelShape[1] << "," << fAttrKernelShape[2] << "," << fAttrPads[0] << "," << fAttrPads[3] << ","
514 << fAttrPads[1] << "," << fAttrPads[4] << "," << fAttrPads[2] << "," << fAttrPads[5] << ","
515 << fAttrStrides[0] << "," << fAttrStrides[1] << "," << fAttrStrides[2] << "," << fAttrDilations[0] << ","
516 << fAttrDilations[1] << "," << fAttrDilations[2] << "," << "tensor_" << fImcol << ");\n\n ";
517 }
518
519 // // BLAS
520 // // offset g must be g * k * n
521 // out << SP << SP << SP << "size_t offset_f = g * " << fShapeW[0] * fShapeW[1] * icstrideDil / fAttrGroup <<
522 // ";\n"; out << SP << SP << "BLAS::sgemm_(&" << OpName << "_transA, &" << OpName << "_transB, &" << OpName <<
523 // "_m, &"
524 // << OpName << "_n, &" << OpName << "_k, &" << OpName << "_alpha, tensor_" << fImcol << ", &" << OpName
525 // << "_m,\n"; // use m if op_xcol is not transpose , otherwise k
526 // out << SP << SP << SP << "tensor_" << fConvK << " + offset_f, &" << OpName << "_k, &" << OpName << "_beta,
527 // tensor_" << fNY
528 // << " + out_offset"
529 // << ", &" << OpName << "_m);\n";
530
531 out << SP << SP << "}\n"; // end of group loop
532 }
533
534 out << SP << "}\n"; // end of batch size loop
535
536 if (fNBroadcastedB != "") {
537 out << SP << "int " << OpName << "_size = " << fShapeY[0] * fShapeY[1] * oDepth * oHeight * oWidth << ";\n";
538 out << SP << "float " << OpName << "_gamma = 1.0;\n";
539 out << SP << "int " << OpName << "_incx = 1;\n";
540 out << SP << "int " << OpName << "_incy = 1;\n";
541
542 out << SP << "BLAS::saxpy_(&" << OpName << "_size, &" << OpName << "_gamma, tensor_" << fNBroadcastedB << ", &"
543 << OpName << "_incx, tensor_" << fNY << ", &" << OpName << "_incy);\n";
544 }
545
546 return out.str();
547}
548
549} // namespace TMVA::Experimental::SOFIE
550
551#endif
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void input
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
std::vector< std::string > GetBlasRoutines() override
Returns the blas routines needed to compile the generated code.
ROperator_ConvTranspose(std::string autopad, std::vector< size_t > dilations, size_t group, std::vector< size_t > kernelShape, std::vector< size_t > outputPadding, std::vector< size_t > outputShape, std::vector< size_t > pads, std::vector< size_t > strides, std::string nameX, std::string nameW, std::string nameB, std::string nameY)
Constructor of ROperator_ConvTranspose from the attributes.
void Initialize(RModel &) override
Initialize the model.
ROperator_ConvTranspose()
Default constructor of ROperator_ConvTranspose.
std::string GenerateInitCode() override
Generate code for initializing the op.
std::string Generate(std::string opName) override
Generate the inference code.
std::vector< std::vector< size_t > > ShapeInference(std::vector< std::vector< size_t > >)
Infers the shape of the input tensors.
std::vector< std::string_view > fInputTensorNames
Definition ROperator.hxx:44
std::vector< std::string_view > fOutputTensorNames
Definition ROperator.hxx:45
std::size_t ConvertShapeToLength(const std::vector< size_t > &shape)
ETensorType ConvertStringToType(std::string type)
std::string ConvertShapeToString(const std::vector< size_t > &shape)