Warning, file /include/root/TMVA/ROperator_ConvTranspose.hxx was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 #ifndef TMVA_SOFIE_ROPERATOR_CONVTRANSPOSE_HXX
0002 #define TMVA_SOFIE_ROPERATOR_CONVTRANSPOSE_HXX
0003
0004 #include <TMVA/SOFIE_common.hxx>
0005 #include <TMVA/ROperator.hxx>
0006 #include <TMVA/RModel.hxx>
0007
0008 #include <memory>
0009 #include <sstream>
0010 #include <algorithm>
0011 #include <stdexcept>
0012 #include <vector>
0013 #include <cassert>
0014
0015 namespace TMVA::Experimental::SOFIE {
0016
0017
0018
0019
0020
0021
0022
0023 template <typename T>
0024 class ROperator_ConvTranspose final : public ROperator {
0025 private:
0026 std::string fAttrAutopad;
0027 std::vector<size_t> fAttrDilations;
0028 size_t fAttrGroup;
0029 std::vector<size_t> fAttrKernelShape;
0030 std::vector<size_t> fAttrOutputPadding;
0031 std::vector<size_t> fAttrOutputShape;
0032 std::vector<size_t> fAttrPads;
0033 std::vector<size_t> fAttrStrides;
0034
0035 std::string fNX;
0036 std::string fNW;
0037 std::string fNB;
0038 std::string fNBroadcastedB;
0039 std::string fNY;
0040
0041 std::string fConvK;
0042 std::string fImcol;
0043
0044 std::vector<size_t> fShapeX;
0045 std::vector<size_t> fShapeW;
0046 std::vector<size_t> fShapeB;
0047 std::vector<size_t> fShapeY;
0048
0049 std::string fType;
0050
0051 size_t fDim;
0052
0053 public:
0054
0055 ROperator_ConvTranspose() {}
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 ROperator_ConvTranspose(std::string autopad, std::vector<size_t> dilations, size_t group,
0073 std::vector<size_t> kernelShape, std::vector<size_t> outputPadding,
0074 std::vector<size_t> outputShape, std::vector<size_t> pads, std::vector<size_t> strides,
0075 std::string nameX, std::string nameW, std::string nameB, std::string nameY)
0076 : fAttrAutopad(autopad), fAttrDilations(dilations), fAttrGroup(group), fAttrKernelShape(kernelShape),
0077 fAttrOutputPadding(outputPadding), fAttrOutputShape(outputShape), fAttrPads(pads), fAttrStrides(strides),
0078 fNX(UTILITY::Clean_name(nameX)), fNW(UTILITY::Clean_name(nameW)), fNB(UTILITY::Clean_name(nameB)),
0079 fNY(UTILITY::Clean_name(nameY))
0080 {
0081 fInputTensorNames = { fNX, fNW };
0082 fOutputTensorNames = { fNY };
0083 if (!fNB.empty()) {
0084 fInputTensorNames.emplace_back(fNB);
0085 }
0086
0087 if (std::is_same<T, float>::value) {
0088 fType = "float";
0089 } else {
0090 throw std::runtime_error("TMVA SOFIE Encountered unsupported type parsing a Conv operator");
0091 }
0092 }
0093
0094
0095
0096
0097 std::vector<ETensorType> TypeInference(std::vector<ETensorType> input) override
0098 {
0099 ETensorType out = input[0];
0100 return {out};
0101 }
0102
0103
0104
0105
0106 std::vector<std::vector<size_t>> ShapeInference(std::vector<std::vector<size_t>> ) override;
0107
0108
0109
0110
0111 void Initialize(RModel &) override;
0112
0113
0114
0115 std::string GenerateInitCode() override;
0116
0117
0118
0119
0120 std::string Generate(std::string opName) override;
0121
0122
0123
0124 std::vector<std::string> GetBlasRoutines() override { return { std::string("Gemm"), std::string("Axpy") }; }
0125 };
0126
0127 template <typename T>
0128 auto ROperator_ConvTranspose<T>::ShapeInference(std::vector<std::vector<size_t>> input)
0129 -> std::vector<std::vector<size_t>>
0130 {
0131 const std::vector<size_t> &inputShape = input[0];
0132 const std::vector<size_t> &weightShape = input[1];
0133 size_t size = inputShape.size();
0134
0135 fDim = size - 2;
0136
0137 if (fAttrGroup == 0)
0138 fAttrGroup = 1;
0139 if (fAttrStrides.empty()) {
0140 fAttrStrides = std::vector<size_t>(fDim, 1);
0141 }
0142 if (fAttrDilations.empty()) {
0143 fAttrDilations = std::vector<size_t>(fDim, 1);
0144 }
0145
0146 if (fAttrKernelShape.empty()) {
0147 fAttrKernelShape.resize(fDim);
0148 for (size_t i = 0; i < fDim; i++)
0149 fAttrKernelShape[i] = fShapeW[i + 2] + (fAttrDilations[i] - 1) * (fShapeW[i + 2] - 1);
0150 }
0151 if (fAttrOutputPadding.empty())
0152 fAttrOutputPadding = std::vector<size_t>(fDim, 0);
0153
0154
0155
0156
0157
0158 std::vector<size_t> outShape(size);
0159 outShape[0] = inputShape[0];
0160 outShape[1] = weightShape[1] * fAttrGroup;
0161
0162
0163 if (fAttrPads.empty()) {
0164 fAttrPads = std::vector<size_t>(2 * fDim, 0);
0165 if (fAttrOutputShape.size() == fDim) {
0166
0167
0168 throw std::runtime_error("ConvTranspose with output_shape explicitly set not yet supported.");
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188 }
0189 if (fAttrAutopad != "NOTSET") {
0190 throw std::runtime_error("ConvTranspose with padding SAME_UPPER or SMAE_LOWER not supported");
0191 }
0192 }
0193 if (fAttrOutputShape.empty()) {
0194 fAttrOutputShape.resize(fDim);
0195 for (size_t i = 0; i < fDim; i++) {
0196 size_t j = i + 2;
0197 fAttrOutputShape[i] = fAttrStrides[i] * (inputShape[j] - 1) + fAttrKernelShape[i] + fAttrOutputPadding[i] -
0198 fAttrPads[i] - fAttrPads[fDim + i];
0199 }
0200 } else {
0201
0202
0203 throw std::runtime_error("ConvTranspose with output_shape explicitly set not yet supported.");
0204 }
0205
0206 for (size_t i = 0; i < fDim; i++)
0207 outShape[i + 2] = fAttrOutputShape[i];
0208 std::vector<std::vector<size_t>> ret({outShape});
0209 return ret;
0210 }
0211
0212 template <typename T>
0213 void ROperator_ConvTranspose<T>::Initialize(RModel &model)
0214 {
0215
0216 fUseSession = model.UseSession();
0217 if (!model.CheckIfTensorAlreadyExist(fNX)) {
0218 throw std::runtime_error("TMVA SOFIE Conv Transpose op Input Tensor " + fNX + " is not found in model");
0219 }
0220 fShapeX = model.GetTensorShape(fNX);
0221 if (fShapeX.size() < 3 || fShapeX.size() > 5) {
0222 std::cout << fNX << " : " << ConvertShapeToString(fShapeX) << std::endl;
0223 throw std::runtime_error("TMVA SOFIE Conv Transpose Op input data tensor" + fNX +
0224 " is not of 3,4 or 5 dimensions");
0225 }
0226 fDim = fShapeX.size() - 2;
0227 if (!model.CheckIfTensorAlreadyExist(fNW)) {
0228 throw std::runtime_error("TMVA SOFIE Conv op Input weight Tensor " + fNW + " is not found in model");
0229 }
0230 fShapeW = model.GetTensorShape(fNW);
0231 if (fShapeW.size() < 3 || fShapeW.size() > 5) {
0232 std::cout << fNW << " : " << ConvertShapeToString(fShapeW) << std::endl;
0233 throw std::runtime_error("TMVA SOFIE Conv Transpose Op input weight tensor" + fNW +
0234 " is not of 3,4 or 5 dimensions");
0235 }
0236 fShapeY = ShapeInference({fShapeX, fShapeW})[0];
0237
0238 model.AddIntermediateTensor(fNY, model.GetTensorType(fNX), fShapeY);
0239 if (fNB != "") {
0240 if (!model.CheckIfTensorAlreadyExist(fNB)) {
0241 throw std::runtime_error("TMVA SOFIE ConvTrans op Input Tensor " + fNB + " is not found in model");
0242 }
0243 fShapeB = model.GetTensorShape(fNB);
0244 if (fShapeB.size() < 1)
0245 throw std::runtime_error("TMVA SOFIE ConvTrans op: Bias Tensor has empty shape");
0246
0247 size_t bsize = ConvertShapeToLength(fShapeB);
0248 size_t ysize = ConvertShapeToLength(fShapeY);
0249
0250 bool broadcast_needed = (bsize != ysize);
0251
0252 if (broadcast_needed) {
0253
0254
0255 if (bsize != fShapeY[1])
0256 throw std::runtime_error("TMVA SOFIE ConvTrans op: Bias Tensor has wrong shape: " +
0257 ConvertShapeToString(fShapeB));
0258
0259 auto original_data = model.GetInitializedTensorData(fNB);
0260
0261 if (fType != "float")
0262 throw std::runtime_error(
0263 "TMVA SOFIE ConvTrans op: Broadcasting for non-float type tensors is not supported");
0264
0265 if (!fUseSession) {
0266
0267 std::shared_ptr<void> new_data_ptr(
0268 UTILITY::BroadcastConvBias<float>(static_cast<float *>(original_data.get()), bsize, fShapeY),
0269 std::default_delete<float[]>());
0270
0271 model.UpdateInitializedTensor(fNB, model.GetTensorType(fNB), fShapeY, new_data_ptr);
0272 fShapeB = model.GetTensorShape(fNB);
0273 fNBroadcastedB = fNB;
0274 } else {
0275
0276
0277 fNBroadcastedB = "Broadcasted" + fNB;
0278 model.AddIntermediateTensor(fNBroadcastedB, model.GetTensorType(fNB), fShapeY);
0279 }
0280 } else {
0281
0282 if (fShapeY != fShapeB)
0283 throw std::runtime_error("TMVA SOFIE ConvTrans op: Broadcasting is not needed but bias has wrong shape" +
0284 ConvertShapeToString(fShapeB));
0285 fNBroadcastedB = fNB;
0286 }
0287 }
0288
0289 size_t kernelSize = 1;
0290 size_t inputSize = 1;
0291 for (size_t i = 0; i < fDim; i++) {
0292 inputSize *= fShapeX[2 + i];
0293 kernelSize *= fAttrKernelShape[i];
0294 }
0295
0296 std::vector<size_t> shape1 = {fShapeW[0], fShapeW[1], kernelSize};
0297 std::vector<size_t> shape2 = {fShapeW[1], kernelSize, inputSize};
0298 model.AddIntermediateTensor(fNX + "_f", ConvertStringToType(fType), shape1);
0299 model.AddIntermediateTensor(fNX + "_xcol", ConvertStringToType(fType), shape2);
0300 fConvK = fNX + "_f";
0301 fImcol = fNX + "_xcol";
0302 fOutputTensorNames.emplace_back(fConvK);
0303 fOutputTensorNames.emplace_back(fImcol);
0304 }
0305
0306 template <typename T>
0307 std::string ROperator_ConvTranspose<T>::GenerateInitCode()
0308 {
0309 std::stringstream out;
0310
0311 size_t bsize = ConvertShapeToLength(fShapeB);
0312 size_t ysize = ConvertShapeToLength(fShapeY);
0313 if (bsize != ysize && !fNBroadcastedB.empty()) {
0314
0315 out << SP << "{\n";
0316 out << SP << SP << "float * data = TMVA::Experimental::SOFIE::UTILITY::BroadcastConvBias<float>(tensor_" << fNB
0317 << ", " << bsize << ", " << ConvertShapeToString(fShapeY) << ");\n";
0318 out << SP << SP << "std::copy(data, data + " << ConvertShapeToLength(fShapeY) << ", tensor_" << fNBroadcastedB
0319 << ");\n";
0320 out << SP << SP << "delete[] data;\n";
0321 out << SP << "}\n";
0322 }
0323 return out.str();
0324 }
0325
0326 template <typename T>
0327 std::string ROperator_ConvTranspose<T>::Generate(std::string OpName)
0328 {
0329 OpName = "op_" + OpName;
0330
0331 if (fShapeX.empty() || fShapeW.empty() || (fNB != "" && fShapeB.empty()) || fShapeY.empty()) {
0332 throw std::runtime_error("TMVA SOFIE Conv Op called to Generate without being initialized first");
0333 }
0334
0335 std::stringstream out;
0336
0337 size_t bsize = fShapeX[0];
0338 size_t kDepth = (fDim > 2) ? fShapeW[2] : 1;
0339 size_t kHeight = (fDim > 1) ? fShapeW[fDim] : 1;
0340 size_t kWidth = fShapeW[fDim + 1];
0341
0342 size_t iDepth = (fDim > 2) ? fShapeX[2] : 1;
0343 size_t iHeight = (fDim > 1) ? fShapeX[fDim] : 1;
0344 size_t iWidth = fShapeX[fDim + 1];
0345
0346 size_t oDepth = (fDim > 2) ? fShapeY[2] : 1;
0347 size_t oHeight = (fDim > 1) ? fShapeY[fDim] : 1;
0348 size_t oWidth = fShapeY[fDim + 1];
0349
0350 out << "\n//---- operator ConvTranspose " << OpName << "\n";
0351
0352
0353 if (!fUseSession) {
0354 size_t kernelSize = fAttrKernelShape[0];
0355 if (fDim > 1)
0356 kernelSize *= fAttrKernelShape[1];
0357 out << SP << fType << " tensor_" << fNX << "_f[" << fShapeW[0] * fShapeW[1] * kernelSize << "] = {0};\n";
0358 }
0359
0360
0361
0362
0363 size_t id = (fDim > 2) ? fDim - 3 : 2;
0364 size_t ih = (fDim > 1) ? fDim - 2 : 1;
0365 size_t iw = fDim - 1;
0366 size_t wstrideDil = fAttrDilations[iw];
0367 size_t hstride = kWidth;
0368 size_t hstrideDil = fAttrKernelShape[iw];
0369 if (fDim > 1)
0370 hstrideDil *= fAttrDilations[ih];
0371
0372 size_t dstride = kHeight * kWidth;
0373 size_t dstrideDil = fAttrKernelShape[iw];
0374 if (fDim > 1)
0375 dstrideDil *= fAttrKernelShape[ih];
0376 if (fDim > 2)
0377 dstrideDil *= fAttrDilations[id];
0378 size_t icstride = kHeight * kWidth * kDepth;
0379 size_t icstrideDil = 1;
0380 for (size_t i = 0; i < fDim; i++)
0381 icstrideDil *= fAttrKernelShape[i];
0382 size_t ocstride = fShapeW[1] * icstride;
0383 size_t ocstrideDil = fShapeW[1] * icstrideDil;
0384
0385
0386 out << SP << "for (std::size_t ic = 0; ic < " << fShapeW[0] << "; ic++) {\n";
0387 out << SP << SP << "for (std::size_t oc = 0; oc < " << fShapeW[1] << "; oc++) {\n";
0388
0389 if (fDim > 2)
0390 out << SP << SP << SP << "for (std::size_t kd = 0; kd < " << kDepth << "; kd++) {\n";
0391 if (fDim > 1)
0392 out << SP << SP << SP << "for (std::size_t kh = 0; kh < " << kHeight << "; kh++) {\n";
0393 out << SP << SP << SP << SP << "for (std::size_t kw = 0; kw < " << kWidth << "; kw++) {\n";
0394
0395 out << SP << SP << SP << SP << SP << "tensor_" << fNX << "_f[ic * " << ocstrideDil << " + oc * " << icstrideDil;
0396 if (fDim > 2)
0397 out << " + kd * " << dstrideDil;
0398 if (fDim > 1)
0399 out << " + kh * " << hstrideDil;
0400 out << " + kw * " << wstrideDil << " ] = tensor_" << fNW << "[ic * " << ocstride << " + oc * " << icstride;
0401
0402 if (fDim > 2)
0403 out << " + kd * " << dstride;
0404 if (fDim > 1)
0405 out << " + kh * " << hstride;
0406 out << " + kw ];\n";
0407
0408
0409
0410
0411
0412 out << SP << SP << SP << SP << "}\n";
0413 if (fDim > 1)
0414 out << SP << SP << SP << "}\n";
0415 if (fDim > 2)
0416 out << SP << SP << SP << "}\n";
0417
0418 out << SP << SP << "}\n";
0419 out << SP << "}\n";
0420
0421 out << SP << "char " << OpName << "_transA = 'N';\n";
0422 out << SP << "char " << OpName << "_transB = 'T';\n";
0423 out << SP << "int " << OpName << "_m = " << iHeight * iWidth * iDepth << ";\n";
0424 out << SP << "int " << OpName << "_n = " << icstrideDil * fShapeW[1] << ";\n";
0425 out << SP << "int " << OpName << "_k = " << fShapeW[0] << ";\n";
0426 out << SP << "float " << OpName << "_alpha = 1.0;\n";
0427 out << SP << "float " << OpName << "_beta = 0.0;\n";
0428
0429 if (!fUseSession) {
0430 out << SP << fType << " tensor_" << fNX << "_xcol[" << fShapeW[0] * icstrideDil * oDepth * oHeight * oWidth
0431 << "] = {0};\n";
0432 }
0433
0434
0435 out << SP << "for (size_t n = 0; n < " << bsize << "; n++) {\n";
0436
0437
0438
0439
0440
0441
0442
0443
0444 if (fDim == 1) {
0445 if (fAttrPads[0] != fAttrPads[1]) {
0446 std::cout << "TMVA SOFIE Operator Conv: asymmetric padding not supported. Assume an average padding "
0447 << std::endl;
0448 fAttrPads[0] = (fAttrPads[0] + fAttrPads[1]) / 2;
0449 }
0450 fAttrPads[1] = 0;
0451 }
0452 if (fDim == 2) {
0453 if (fAttrPads[0] != fAttrPads[2] || fAttrPads[1] != fAttrPads[3]) {
0454 std::cout << "TMVA SOFIE Operator ConvTranspose: asymmetric padding not supported. Assume an average padding "
0455 << std::endl;
0456 fAttrPads[0] = (fAttrPads[0] + fAttrPads[2]) / 2;
0457 fAttrPads[1] = (fAttrPads[1] + fAttrPads[3]) / 2;
0458 }
0459 }
0460 if (fDim == 3) {
0461 if (fAttrPads[0] != fAttrPads[3] || fAttrPads[1] != fAttrPads[4] || fAttrPads[2] != fAttrPads[5]) {
0462 std::cout << "TMVA SOFIE Operator ConvTranspose: asymmetric padding not supported. Assume an average padding "
0463 << std::endl;
0464 fAttrPads[0] = (fAttrPads[0] + fAttrPads[3]) / 2;
0465 fAttrPads[1] = (fAttrPads[1] + fAttrPads[4]) / 2;
0466 fAttrPads[2] = (fAttrPads[2] + fAttrPads[5]) / 2;
0467 }
0468 }
0469
0470 if (fAttrGroup == 1) {
0471 out << SP << SP << "size_t x_offset = n * " << fShapeX[1] * iDepth * iHeight * iWidth << ";\n";
0472 out << SP << SP << "size_t out_offset = n * " << fShapeY[1] * oDepth * oHeight * oWidth << ";\n";
0473
0474
0475
0476 out << SP << SP << "BLAS::sgemm_(&" << OpName << "_transA, &" << OpName << "_transB, &" << OpName << "_m, &"
0477 << OpName << "_n, &" << OpName << "_k, &" << OpName << "_alpha, "
0478 << "tensor_" << fNX << " + x_offset, &" << OpName
0479 << "_m,\n";
0480 out << SP << SP << SP << "tensor_" << fNX << "_f, &" << OpName << "_n, &" << OpName << "_beta, tensor_" << fNX
0481 << "_xcol, &" << OpName << "_m);\n";
0482
0483
0484
0485
0486 if (fDim < 3) {
0487 out << SP << SP << "TMVA::Experimental::SOFIE::UTILITY::col2im<float>(tensor_" << fNX
0488 << "_xcol,"
0489
0490
0491 << fShapeY[1] << "," << oHeight << "," << oWidth << ",";
0492 if (fDim == 1)
0493 out << "1, " << fAttrKernelShape[0] << ",0," << fAttrPads[0] << ",1," << fAttrStrides[0] << ",1,"
0494 << fAttrDilations[0];
0495 else
0496 out << fAttrKernelShape[0] << "," << fAttrKernelShape[1] << "," << fAttrPads[0] << "," << fAttrPads[1]
0497 << "," << fAttrStrides[0] << "," << fAttrStrides[1] << "," << fAttrDilations[0] << ","
0498 << fAttrDilations[1];
0499 out << ", tensor_" << fNY << " + out_offset);\n\n ";
0500 } else {
0501
0502 throw std::runtime_error("TMVA SOFIE 3D Conv Transpose not yet supported");
0503 out << SP << SP << "TMVA::Experimental::SOFIE::UTILITY::Im2col_3d<float>(tensor_" << fNX
0504 << " + x_offset,"
0505
0506
0507
0508 << fShapeX[1] << "," << oDepth << "," << oHeight << "," << oWidth << "," << fAttrKernelShape[0] << ","
0509 << fAttrKernelShape[1] << "," << fAttrKernelShape[2] << "," << fAttrPads[0] << "," << fAttrPads[1] << ","
0510 << fAttrPads[2] << "," << fAttrStrides[0] << "," << fAttrStrides[1] << "," << fAttrStrides[2] << ","
0511 << fAttrDilations[0] << "," << fAttrDilations[1] << "," << fAttrDilations[2] << ",tensor_" << fNX
0512 << "_xcol);\n\n ";
0513 }
0514
0515
0516
0517
0518
0519
0520 } else {
0521
0522
0523
0524 out << SP << SP << "for (size_t g = 0; g < " << fAttrGroup << "; g++) {\n";
0525 out << SP << SP << "size_t x_offset = n * " << fShapeX[1] * iHeight * iWidth << " + g * "
0526 << fShapeX[1] * iHeight * iWidth / fAttrGroup << ";\n ";
0527 out << SP << SP << "size_t out_offset = n * " << fShapeY[1] * oHeight * oWidth << " + g * "
0528 << fShapeY[1] * oHeight * oWidth / fAttrGroup << ";\n ";
0529
0530
0531 out << SP << SP << "BLAS::sgemm_(&" << OpName << "_transA, &" << OpName << "_transB, &" << OpName << "_m, &"
0532 << OpName << "_n, &" << OpName << "_k, &" << OpName << "_alpha, "
0533 << "tensor_" << fNX << " + x_offset, &" << OpName
0534 << "_m,\n";
0535 out << SP << SP << SP << "tensor_" << fNX << "_f, &" << OpName << "_n, &" << OpName << "_beta, tensor_" << fNX
0536 << "_xcol , &" << OpName << "_m);\n";
0537
0538 if (fDim < 3) {
0539 out << SP << SP << "TMVA::Experimental::SOFIE::UTILITY::col2im<float>(tensor_" << fNX
0540 << "_xcol,"
0541
0542
0543 << fShapeY[1] << "," << oHeight << "," << oWidth << ",";
0544 if (fDim == 1)
0545 out << "1, " << fAttrKernelShape[0] << ",0," << fAttrPads[0] << ",1," << fAttrStrides[0] << ",1,"
0546 << fAttrDilations[0];
0547 else
0548 out << fAttrKernelShape[0] << "," << fAttrKernelShape[1] << "," << fAttrPads[0] << "," << fAttrPads[1]
0549 << "," << fAttrStrides[0] << "," << fAttrStrides[1] << "," << fAttrDilations[0] << ","
0550 << fAttrDilations[1];
0551 out << ", tensor_" << fNY << " + out_offset);\n\n ";
0552 } else {
0553
0554 throw std::runtime_error("TMVA SOFIE 3D Conv Transpose not yet supported");
0555
0556 out << SP << SP << "TMVA::Experimental::SOFIE::UTILITY::Im2col_3d<float>(tensor_" << fNX
0557 << " + x_offset,"
0558
0559
0560
0561 << fShapeX[1] << "," << oDepth << "," << oHeight << "," << oWidth << "," << fAttrKernelShape[0] << ","
0562 << fAttrKernelShape[1] << "," << fAttrKernelShape[2] << "," << fAttrPads[0] << "," << fAttrPads[1] << ","
0563 << fAttrPads[2] << "," << fAttrStrides[0] << "," << fAttrStrides[1] << "," << fAttrStrides[2] << ","
0564 << fAttrDilations[0] << "," << fAttrDilations[1] << "," << fAttrDilations[2] << "," << "tensor_" << fNX
0565 << "_xcol);\n\n ";
0566 }
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580 out << SP << SP << "}\n";
0581 }
0582
0583 out << SP << "}\n";
0584
0585 if (fNBroadcastedB != "") {
0586 out << SP << "int " << OpName << "_size = " << fShapeY[0] * fShapeY[1] * oDepth * oHeight * oWidth << ";\n";
0587 out << SP << "float " << OpName << "_gamma = 1.0;\n";
0588 out << SP << "int " << OpName << "_incx = 1;\n";
0589 out << SP << "int " << OpName << "_incy = 1;\n";
0590
0591 out << SP << "BLAS::saxpy_(&" << OpName << "_size, &" << OpName << "_gamma, tensor_" << fNBroadcastedB << ", &"
0592 << OpName << "_incx, tensor_" << fNY << ", &" << OpName << "_incy);\n";
0593 }
0594
0595 return out.str();
0596 }
0597
0598 }
0599
0600 #endif