167 if (!model.CheckIfTensorAlreadyExist(fNX)) {
168 throw std::runtime_error(
"TMVA SOFIE RNN Op input tensor " + fNX +
" is not found in model.");
170 fShapeX = model.GetTensorShape(fNX);
171 if (fShapeX.size() != 3) {
172 throw std::runtime_error(
"TMVA SOFIE RNN Op input tensor " + fNX +
" is not of 3 dimensions.");
174 if (!model.CheckIfTensorAlreadyExist(fNW)) {
175 throw std::runtime_error(
"TMVA SOFIE RNN Op input tensor " + fNW +
" is not found in model.");
177 fShapeW = model.GetTensorShape(fNW);
178 if (fShapeW.size() != 3) {
179 throw std::runtime_error(
"TMVA SOFIE RNN Op input tensor " + fNW +
" is not of 3 dimensions.");
181 if (!model.CheckIfTensorAlreadyExist(fNR)) {
182 throw std::runtime_error(
"TMVA SOFIE RNN Op input tensor " + fNR +
" is not found in model.");
184 fShapeR = model.GetTensorShape(fNR);
185 if (fShapeR.size() != 3) {
186 throw std::runtime_error(
"TMVA SOFIE RNN Op input tensor " + fNR +
" is not of 3 dimensions.");
189 if (!model.CheckIfTensorAlreadyExist(fNB)) {
190 throw std::runtime_error(
"TMVA SOFIE RNN op input tensor " + fNB +
" is not found in model.");
192 fShapeB = model.GetTensorShape(fNB);
193 if (fShapeB.size() != 2 && fShapeB.size() != 4) {
194 throw std::runtime_error(
"TMVA SOFIE RNN op input tensor " + fNB +
" is not of 2 or 4 dimensions.");
196 if (fShapeB.size() == 2) {
198 auto original_data = model.GetInitializedTensorData(fNB);
199 size_t num_directions = fShapeW[0];
200 size_t seq_length = (fAttrLayout == 0) ? fShapeX[0] : fShapeX[1];
201 size_t batch_size = (fAttrLayout == 0) ? fShapeX[1] : fShapeX[0];
202 if (fType ==
"float") {
203 float *original_bias =
static_cast<float *
>(original_data.get());
204 float *new_bias =
new float[num_directions * seq_length * batch_size * fAttrHiddenSize];
205 std::vector<float>
sum(fAttrHiddenSize);
206 for (
size_t direction = 0; direction < num_directions; direction++) {
207 for (
size_t h = 0;
h < fAttrHiddenSize;
h++) {
208 sum[
h] = original_bias[direction * 2 * fAttrHiddenSize +
h] +
209 original_bias[(2 * direction + 1) * fAttrHiddenSize +
h];
211 for (
size_t seq = 0; seq < seq_length; seq++) {
212 for (
size_t batch = 0; batch < batch_size; batch++) {
213 size_t bias_offset = direction * seq_length * batch_size * fAttrHiddenSize +
214 seq * batch_size * fAttrHiddenSize + batch * fAttrHiddenSize;
215 std::copy(
sum.begin(),
sum.end(), new_bias + bias_offset);
219 std::vector<size_t> new_bias_shape = {num_directions, seq_length, batch_size, fAttrHiddenSize};
220 std::shared_ptr<void> new_bias_ptr(new_bias, std::default_delete<
float[]>());
221 model.UpdateInitializedTensor(fNB, model.GetTensorType(fNB), new_bias_shape, new_bias_ptr);
222 fShapeB = model.GetTensorShape(fNB);
226 if (!fNSequence_lens.empty()) {
227 if (!model.CheckIfTensorAlreadyExist(fNSequence_lens)) {
228 throw std::runtime_error(
"TMVA SOFIE RNN Op input tensor " + fNSequence_lens +
"is not found in model.");
230 fShapeSequence_lens = model.GetTensorShape(fNSequence_lens);
231 if (fShapeSequence_lens.size() != 1) {
232 throw std::runtime_error(
"TMVA SOFIE RNN Op input tensor " + fNSequence_lens +
" is not of 1 dimension.");
235 if (!fNInitial_h.empty()) {
236 if (!model.CheckIfTensorAlreadyExist(fNInitial_h)) {
237 throw std::runtime_error(
"TMVA SOFIE RNN Op input tensor " + fNInitial_h +
" is not found in model.");
239 fShapeInitial_h = model.GetTensorShape(fNInitial_h);
240 if (fShapeInitial_h.size() != 3) {
241 throw std::runtime_error(
"TMVA SOFIE RNN Op input tensor " + fNInitial_h +
" is not of 3 dimensions.");
245 fShapeY = ShapeInference({fShapeX, fShapeW})[0];
246 if (!model.CheckIfTensorAlreadyExist(fNY)) {
247 model.AddIntermediateTensor(fNY, model.GetTensorType(fNX), fShapeY);
250 if (!fNY_h.empty()) {
251 fShapeY_h = ShapeInference({fShapeX, fShapeW})[1];
252 if (!model.CheckIfTensorAlreadyExist(fNY_h)) {
253 model.AddIntermediateTensor(fNY_h, model.GetTensorType(fNX), fShapeY_h);
257 for (
auto &activation : fAttrActivations) {
258 if (activation !=
"Relu" && activation !=
"Tanh" && activation !=
"Sigmoid" && activation !=
"Affine" &&
259 activation !=
"LeakyRelu" && activation !=
"ThresholdRelu" && activation !=
"ScaledTanh" &&
260 activation !=
"HardSigmoid" && activation !=
"Elu" && activation !=
"Softsign" && activation !=
"Softplus") {
261 throw std::runtime_error(
"TMVA SOFIE - Activation function " + activation +
" not implemented");
264 if (fAttrDirection !=
"forward" && fAttrDirection !=
"backward" && fAttrDirection !=
"bidirectional") {
265 throw std::runtime_error(
"TMVA SOFIE - Invalid RNN direction fAttrDirection = " + fAttrDirection);
267 if (fAttrHiddenSize != fShapeW[1]) {
268 throw std::runtime_error(
"TMVA SOFIE - fAttrHiddenSize must be equal to " + std::to_string(fShapeW[1]));
270 if (fAttrLayout > 1) {
271 throw std::runtime_error(
"TMVA SOFIE - Layout fAttrLayout = " + std::to_string(fAttrLayout) +
272 " must be 0 (timewise) or 1 (batchwise)");
274 if (fAttrActivations.empty()) {
275 if (fAttrDirection ==
"bidirectional") {
276 fAttrActivations = {
"Tanh",
"Tanh"};
278 fAttrActivations = {
"Tanh"};
282 model.AddNeededStdLib(
"cmath");
340 OpName =
"op_" + OpName;
341 std::stringstream out;
343 size_t seq_length = (fAttrLayout == 0) ? fShapeX[0] : fShapeX[1];
344 size_t batch_size = (fAttrLayout == 0) ? fShapeX[1] : fShapeX[0];
345 size_t input_size = fShapeX[2];
346 size_t num_directions = fShapeW[0];
349 if (fAttrLayout == 0) {
350 if (fType ==
"float") {
351 out <<
SP <<
"float const*" << OpName <<
"_input = tensor_" << fNX <<
";\n";
354 out <<
SP << fType <<
" * " << OpName <<
"_input = this->fVec_" << OpName <<
"_input;\n";
355 out <<
SP <<
"for(size_t seq = 0; seq < " << seq_length <<
"; seq++) {\n";
356 out <<
SP <<
SP <<
"for(size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
357 out <<
SP <<
SP <<
SP <<
"for(size_t i = 0; i < " << input_size <<
"; i++) {\n";
358 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input[seq * " << batch_size * input_size <<
" + batch * " << input_size
359 <<
" + i] = " <<
"tensor_" << fNX <<
"[batch * " << seq_length * input_size <<
" + seq * " << input_size
361 out <<
SP <<
SP <<
SP <<
"}\n";
362 out <<
SP <<
SP <<
"}\n";
367 if (!fNInitial_h.empty()) {
368 if (fAttrLayout == 0) {
369 out <<
SP << fType <<
" *" << OpName <<
"_initial_hidden_state = " <<
" tensor_" << fNInitial_h <<
";\n";
371 out <<
SP << fType <<
" * " << OpName <<
"_initial_hidden_state = this->fVec_" << OpName
372 <<
"_initial_hidden_state;\n";
374 for (
size_t direction = 0; direction < num_directions; direction++) {
375 out <<
SP <<
"for(size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
376 out <<
SP <<
SP <<
"for(size_t h = 0; h < " << fAttrHiddenSize <<
"; h++) {\n";
377 out <<
SP <<
SP <<
SP << OpName <<
"_initial_hidden_state[" << direction * batch_size * fAttrHiddenSize
378 <<
" + batch * " << fAttrHiddenSize <<
" + h] = tensor_" << fNInitial_h <<
"[batch * "
379 << num_directions * fAttrHiddenSize <<
" + " << direction * fAttrHiddenSize <<
" + h];\n";
380 out <<
SP <<
SP <<
"}\n";
386 out <<
SP << fType <<
" * " << OpName <<
"_feedforward = this->fVec_" << OpName <<
"_feedforward;\n";
389 if (fAttrLayout == 0 && !fNY.empty()) {
390 out <<
SP << fType <<
" *" << OpName <<
"_hidden_state = tensor_" << fNY <<
";\n";
392 out <<
SP << fType <<
" * " << OpName <<
"_hidden_state = this->fVec_" << OpName <<
"_hidden_state;\n";
395 out <<
SP <<
"char " << OpName <<
"_transA = 'N';\n";
396 out <<
SP <<
"char " << OpName <<
"_transB = 'T';\n";
397 out <<
SP <<
"int " << OpName <<
"_m = " << seq_length * batch_size <<
";\n";
398 out <<
SP <<
"int " << OpName <<
"_n = " << fAttrHiddenSize <<
";\n";
399 out <<
SP <<
"int " << OpName <<
"_k = " << input_size <<
";\n";
400 if (fType ==
"float") {
401 out <<
SP <<
"float " << OpName <<
"_alpha = 1.;\n";
402 out <<
SP <<
"float " << OpName <<
"_beta = .0;\n";
405 out <<
SP <<
"int " << OpName <<
"_bias_size = " << seq_length * batch_size * fAttrHiddenSize <<
";\n";
406 out <<
SP <<
"int " << OpName <<
"_incx = 1;\n";
407 out <<
SP <<
"int " << OpName <<
"_incy = 1;\n";
410 for (
size_t direction = 0; direction < num_directions; direction++) {
412 if (fType ==
"float") {
413 if (direction == 0) {
414 out <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName <<
"_n, &"
415 << OpName <<
"_m, &" << OpName <<
"_k, &" << OpName <<
"_alpha, tensor_" << fNW <<
", &" << OpName
416 <<
"_k, " << OpName <<
"_input, &" << OpName <<
"_k, &" << OpName <<
"_beta, " << OpName
417 <<
"_feedforward, &" << OpName <<
"_n);\n";
419 out <<
SP <<
"size_t " << OpName <<
"_w_offset = " << fAttrHiddenSize * input_size <<
";\n";
420 out <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName <<
"_n, &"
421 << OpName <<
"_m, &" << OpName <<
"_k, &" << OpName <<
"_alpha, tensor_" << fNW <<
" + " << OpName
422 <<
"_w_offset, &" << OpName <<
"_k, " << OpName <<
"_input, &" << OpName <<
"_k, &" << OpName
423 <<
"_beta, " << OpName <<
"_feedforward, &" << OpName <<
"_n);\n";
428 if (fType ==
"float") {
429 if (direction == 0) {
430 out <<
SP <<
"BLAS::saxpy_(&" << OpName <<
"_bias_size, &" << OpName <<
"_alpha, tensor_" << fNB <<
", &"
431 << OpName <<
"_incx, " << OpName <<
"_feedforward, &" << OpName <<
"_incy);\n";
433 out <<
SP <<
"size_t " << OpName <<
"_bias_offset = " << seq_length * batch_size * fAttrHiddenSize
435 out <<
SP <<
"BLAS::saxpy_(&" << OpName <<
"_bias_size, &" << OpName <<
"_alpha, tensor_" << fNB <<
" + "
436 << OpName <<
"_bias_offset, &" << OpName <<
"_incx, " << OpName <<
"_feedforward, &" << OpName
443 out <<
SP <<
"for (size_t seq = 0; seq < " << seq_length <<
"; seq++) {\n";
444 out <<
SP <<
SP <<
"size_t offset = seq * " << batch_size * fAttrHiddenSize <<
";\n";
445 out <<
SP <<
SP <<
"size_t size = " << batch_size * fAttrHiddenSize <<
";\n";
446 out <<
SP <<
SP <<
"size_t h_offset = seq * " << num_directions * batch_size * fAttrHiddenSize <<
" + "
447 << direction * batch_size * fAttrHiddenSize <<
";\n";
448 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_feedforward + offset, " << OpName
449 <<
"_feedforward + offset + size, " << OpName <<
"_hidden_state + h_offset);\n";
452 out <<
SP <<
"for (size_t seq = 0; seq < " << seq_length <<
"; seq++) {\n";
453 if (fAttrDirection ==
"backward" || direction == 1) {
454 out <<
SP <<
SP <<
"size_t index = " << seq_length - 1 <<
" - seq;\n";
456 out <<
SP <<
SP <<
"size_t index = seq;\n";
459 out <<
SP <<
SP <<
"int m2 = " << batch_size <<
";\n";
460 out <<
SP <<
SP <<
"size_t offset = index * " << num_directions * batch_size * fAttrHiddenSize <<
" + "
461 << direction * batch_size * fAttrHiddenSize <<
";\n";
462 out <<
SP <<
SP <<
"size_t size = " << batch_size * fAttrHiddenSize <<
";\n";
463 out <<
SP <<
SP <<
"if (seq == 0) {\n";
464 if (!fNInitial_h.empty()) {
466 out <<
SP <<
SP <<
SP <<
"size_t r_offset = " << direction * fAttrHiddenSize * fAttrHiddenSize <<
";\n";
467 out <<
SP <<
SP <<
SP <<
"size_t initial_hidden_state_offset = " << direction * batch_size * fAttrHiddenSize
469 if (fType ==
"float") {
470 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
471 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + r_offset, &" << OpName
472 <<
"_n, " << OpName <<
"_initial_hidden_state + initial_hidden_state_offset, &" << OpName <<
"_n, &"
473 << OpName <<
"_alpha, " << OpName <<
"_hidden_state + offset, &" << OpName <<
"_n);\n";
476 out <<
SP <<
SP <<
"} else {\n";
478 out <<
SP <<
SP <<
SP <<
"size_t r_offset = " << direction * fAttrHiddenSize * fAttrHiddenSize <<
";\n";
479 if (fAttrDirection ==
"backward" || direction == 1) {
480 out <<
SP <<
SP <<
SP <<
"size_t previous_offset = (index + 1) * "
481 << num_directions * batch_size * fAttrHiddenSize <<
" + " << direction * batch_size * fAttrHiddenSize
484 out <<
SP <<
SP <<
SP <<
"size_t previous_offset = (seq - 1) * "
485 << num_directions * batch_size * fAttrHiddenSize <<
" + " << direction * batch_size * fAttrHiddenSize
488 if (fType ==
"float") {
489 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
490 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + r_offset, &" << OpName
491 <<
"_n, " << OpName <<
"_hidden_state + previous_offset, &" << OpName <<
"_n, &" << OpName <<
"_alpha, "
492 << OpName <<
"_hidden_state + offset, &" << OpName <<
"_n);\n";
494 out <<
SP <<
SP <<
"}\n";
497 if (fAttrClip > .0) {
498 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + size; i++) {\n";
499 if (fType ==
"float") {
500 out <<
SP <<
SP <<
SP <<
"float x = (" << OpName <<
"_hidden_state[i] > " << -fAttrClip <<
") ? " << OpName
501 <<
"_hidden_state[i] : " << -fAttrClip <<
";\n";
503 out <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[i] = (x < " << fAttrClip <<
") ? x : " << fAttrClip <<
";\n";
504 out <<
SP <<
SP <<
"}\n";
508 if (fAttrActivations[direction] ==
"Relu") {
509 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + size; i++) {\n";
510 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_hidden_state[i] < 0.)\n";
511 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[i] = 0.;\n";
512 out <<
SP <<
SP <<
"}\n";
513 }
else if (fAttrActivations[direction] ==
"Tanh") {
514 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + size; i++) {\n";
515 if (fType ==
"float") {
516 out <<
SP <<
SP <<
SP <<
"float ex = std::exp(-2 * " << OpName <<
"_hidden_state[i]);\n";
518 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[i] = (1. - ex) / (1. + ex);\n";
519 out <<
SP <<
SP <<
"}\n";
520 }
else if (fAttrActivations[direction] ==
"Sigmoid") {
521 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + size; i++) {\n";
522 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[i] = 1. / (1. + std::exp(-" << OpName
523 <<
"_hidden_state[i]));\n";
524 out <<
SP <<
SP <<
"}\n";
525 }
else if (fAttrActivations[direction] ==
"Affine") {
526 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + size; i++) {\n";
527 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[i] = " << fAttrActivationAlpha[direction] <<
" * "
528 << OpName <<
"_hidden_state[i] + " << fAttrActivationBeta[direction] <<
";\n";
529 out <<
SP <<
SP <<
"}\n";
530 }
else if (fAttrActivations[direction] ==
"ScaledTanh") {
531 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + size; i++) {\n";
532 if (fType ==
"float") {
533 out <<
SP <<
SP <<
SP <<
"float ex = std::exp(-2 * " << fAttrActivationBeta[direction] <<
" * " << OpName
534 <<
"_hidden_state[i]);\n";
536 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[i] = " << fAttrActivationAlpha[direction]
537 <<
" * (1. - ex) / (1. + ex);\n";
538 out <<
SP <<
SP <<
"}\n";
539 }
else if (fAttrActivations[direction] ==
"HardSigmoid") {
540 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + size; i++) {\n";
541 if (fType ==
"float") {
542 out <<
SP <<
SP <<
SP <<
"float a = " << fAttrActivationAlpha[direction] <<
" * " << OpName
543 <<
"_hidden_state[i] + " << fAttrActivationBeta[direction] <<
";\n";
544 out <<
SP <<
SP <<
SP <<
"float b = (a > 0.) ? a : 0.;\n";
546 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[i] = (b < 1.) ? b : 1.;\n";
547 out <<
SP <<
SP <<
"}\n";
548 }
else if (fAttrActivations[direction] ==
"LeakyRelu") {
549 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + size; i++) {\n";
550 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_hidden_state[i] < 0.)\n";
551 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[i] = " << fAttrActivationAlpha[direction] <<
" * "
552 << OpName <<
"_hidden_state[i];\n";
553 out <<
SP <<
SP <<
"}\n";
554 }
else if (fAttrActivations[direction] ==
"ThresholdRelu") {
555 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + size; i++) {\n";
556 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_hidden_state[i] < " << fAttrActivationAlpha[direction] <<
")\n";
557 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[i] = 0.;\n";
558 out <<
SP <<
SP <<
"}";
559 }
else if (fAttrActivations[direction] ==
"Elu") {
560 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + size; i++) {\n";
561 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_hidden_state[i] < 0.)\n";
562 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[i] = " << fAttrActivationAlpha[direction]
563 <<
" * std::exp(" << OpName <<
"_hidden_state[i] - 1.);\n";
564 out <<
SP <<
SP <<
"}\n";
565 }
else if (fAttrActivations[direction] ==
"Softsign") {
566 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + size; i++) {\n";
567 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[i] = " << OpName <<
"_hidden_state[i] / (1. + abs("
568 << OpName <<
"_hidden_state[i]));\n";
569 out <<
SP <<
SP <<
"}\n";
571 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + size; i++) {\n";
572 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[i] = log(1. + std::exp(" << OpName
573 <<
"_hidden_state[i]));\n";
574 out <<
SP <<
SP <<
"}\n";
581 if (!fNSequence_lens.empty()) {
582 out <<
SP <<
"for (size_t seq = 0; seq < " << seq_length <<
"; seq++) {\n";
583 out <<
SP <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
584 out <<
SP <<
SP <<
SP <<
"if (seq >= tensor_" << fNSequence_lens <<
"[batch]) {\n";
585 out <<
SP <<
SP <<
SP <<
SP <<
"for (size_t h = 0; h < " << fAttrHiddenSize <<
"; h++) {\n";
586 if (num_directions == 1) {
587 out <<
SP <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[seq * "
588 << num_directions * batch_size * fAttrHiddenSize <<
" + batch * " << fAttrHiddenSize <<
" + h] = 0.;\n";
590 out <<
SP <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[seq * "
591 << num_directions * batch_size * fAttrHiddenSize <<
" + batch * " << fAttrHiddenSize <<
" + h] = 0.;\n";
592 out <<
SP <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[seq * "
593 << num_directions * batch_size * fAttrHiddenSize <<
" + " << batch_size * fAttrHiddenSize <<
" + batch * "
594 << fAttrHiddenSize <<
" + h] = 0.;\n";
596 out <<
SP <<
SP <<
SP <<
SP <<
"}\n";
597 out <<
SP <<
SP <<
SP <<
"}\n";
598 out <<
SP <<
SP <<
"}\n";
603 if (fAttrLayout == 0) {
604 if (!fNY_h.empty()) {
605 if (fNSequence_lens.empty()) {
606 size_t yh_size = batch_size * fAttrHiddenSize;
607 if (fAttrDirection ==
"backward") {
608 out <<
SP <<
"std::copy(" << OpName <<
"_hidden_state, " << OpName <<
"_hidden_state + " << yh_size
609 <<
", tensor_" << fNY_h <<
");\n";
611 size_t offset = (seq_length - 1) * num_directions * batch_size * fAttrHiddenSize;
612 out <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + " <<
offset <<
", " << OpName
613 <<
"_hidden_state + " <<
offset <<
" + " << yh_size <<
", tensor_" << fNY_h <<
");\n";
615 if (num_directions == 2) {
616 out <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + " << yh_size <<
", " << OpName
617 <<
"_hidden_state + " << 2 * yh_size <<
", tensor_" << fNY_h <<
" + " << yh_size <<
");\n";
620 if (fAttrDirection ==
"backward") {
621 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
622 out <<
SP <<
SP <<
"size_t offset = batch * " << fAttrHiddenSize <<
";\n";
623 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + offset, " << OpName
624 <<
"_hidden_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_h <<
" + offset);\n";
627 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
628 out <<
SP <<
SP <<
"size_t seq = " <<
"tensor_" << fNSequence_lens <<
"[batch] - 1;\n";
629 out <<
SP <<
SP <<
"size_t offset = seq * " << num_directions * batch_size * fAttrHiddenSize
630 <<
" + batch * " << fAttrHiddenSize <<
";\n";
631 out <<
SP <<
SP <<
"size_t yh_offset = batch * " << fAttrHiddenSize <<
";\n";
632 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + offset, " << OpName
633 <<
"_hidden_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_h <<
" + yh_offset);\n";
636 if (num_directions == 2) {
637 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
638 out <<
SP <<
SP <<
"size_t offset = " << batch_size * fAttrHiddenSize <<
" + batch * " << fAttrHiddenSize
640 out <<
SP <<
SP <<
"size_t yh_offset = " << batch_size * fAttrHiddenSize <<
" + batch * "
641 << fAttrHiddenSize <<
";\n";
642 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + offset, " << OpName
643 <<
"_hidden_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_h <<
" + yh_offset);\n";
650 for (
size_t direction = 0; direction < num_directions; direction++) {
651 out <<
SP <<
"for (size_t seq = 0; seq < " << seq_length <<
"; seq++) {\n";
652 out <<
SP <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
653 out <<
SP <<
SP <<
SP <<
"size_t offset = seq * " << num_directions * batch_size * fAttrHiddenSize <<
" + "
654 << direction * batch_size * fAttrHiddenSize <<
" + batch * " << fAttrHiddenSize <<
";\n";
655 out <<
SP <<
SP <<
SP <<
"size_t y_offset = batch * " << seq_length * num_directions * fAttrHiddenSize
656 <<
" + seq * " << num_directions * fAttrHiddenSize <<
" + " << direction * fAttrHiddenSize <<
";\n";
657 out <<
SP <<
SP <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + offset, " << OpName
658 <<
"_hidden_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY <<
" + y_offset);\n";
659 out <<
SP <<
SP <<
"}\n";
663 if (!fNY_h.empty()) {
664 if (fAttrDirection ==
"backward") {
665 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
666 out <<
SP <<
SP <<
"size_t offset = batch * " << fAttrHiddenSize <<
";\n";
667 out <<
SP <<
SP <<
"size_t yh_offset = batch * " << num_directions * fAttrHiddenSize <<
";\n";
668 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + offset, " << OpName
669 <<
"_hidden_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_h <<
" + yh_offset);\n";
672 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
673 if (fNSequence_lens.empty()) {
674 out <<
SP <<
SP <<
"size_t seq = " << seq_length - 1 <<
";\n";
676 out <<
SP <<
SP <<
"size_t seq = " <<
"tensor_" << fNSequence_lens <<
"[batch] - 1;\n";
678 out <<
SP <<
SP <<
"size_t offset = seq * " << num_directions * batch_size * fAttrHiddenSize
679 <<
" + batch * " << fAttrHiddenSize <<
";\n";
680 out <<
SP <<
SP <<
"size_t yh_offset = batch * " << num_directions * fAttrHiddenSize <<
";\n";
681 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + offset, " << OpName
682 <<
"_hidden_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_h <<
" + yh_offset);\n";
685 if (num_directions == 2) {
686 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
687 out <<
SP <<
SP <<
"size_t offset = " << batch_size * fAttrHiddenSize <<
" + batch * " << fAttrHiddenSize
689 out <<
SP <<
SP <<
"size_t yh_offset = batch * " << num_directions * fAttrHiddenSize <<
" + "
690 << fAttrHiddenSize <<
";\n";
691 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + offset, " << OpName
692 <<
"_hidden_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_h <<
" + yh_offset);\n";
ROperator_RNN(std::vector< float > activation_alpha, std::vector< float > activation_beta, std::vector< std::string > activations, float clip, std::string direction, size_t hidden_size, size_t layout, std::string nameX, std::string nameW, std::string nameR, std::string nameB, std::string nameSequence_lens, std::string nameInitial_h, std::string nameY, std::string nameY_h)
Constructor of ROperator_RNN from the attributes.