196 if (!model.CheckIfTensorAlreadyExist(fNX)) {
197 throw std::runtime_error(
"TMVA SOFIE LSTM Op input tensor " + fNX +
" is not found in model.");
199 fShapeX = model.GetTensorShape(fNX);
200 if (fShapeX.size() != 3) {
201 throw std::runtime_error(
"TMVA SOFIE LSTM Op input tensor " + fNX +
" is not of 3 dimensions.");
203 if (!model.CheckIfTensorAlreadyExist(fNW)) {
204 throw std::runtime_error(
"TMVA SOFIE LSTM Op input tensor " + fNW +
" is not found in model.");
206 fShapeW = model.GetTensorShape(fNW);
207 if (fShapeW.size() != 3) {
208 throw std::runtime_error(
"TMVA SOFIE LSTM Op input tensor " + fNW +
" is not of 3 dimensions.");
210 if (!model.CheckIfTensorAlreadyExist(fNR)) {
211 throw std::runtime_error(
"TMVA SOFIE LSTM Op input tensor " + fNR +
" is not found in model.");
213 fShapeR = model.GetTensorShape(fNR);
214 if (fShapeR.size() != 3) {
215 throw std::runtime_error(
"TMVA SOFIE LSTM Op input tensor " + fNR +
" is not of 3 dimensions.");
218 if (!model.CheckIfTensorAlreadyExist(fNB)) {
219 throw std::runtime_error(
"TMVA SOFIE LSTM op input tensor " + fNB +
" is not found in model.");
221 fShapeB = model.GetTensorShape(fNB);
222 if (fShapeB.size() != 2 && fShapeB.size() != 5) {
223 throw std::runtime_error(
"TMVA SOFIE LSTM op input tensor " + fNB +
" is not of 2 or 5 dimensions.");
225 if (fShapeB.size() == 2) {
227 auto original_data = model.GetInitializedTensorData(fNB);
228 size_t num_directions = fShapeW[0];
229 size_t seq_length = (fAttrLayout == 0) ? fShapeX[0] : fShapeX[1];
230 size_t batch_size = (fAttrLayout == 0) ? fShapeX[1] : fShapeX[0];
231 if (fType ==
"float") {
232 float *original_bias =
static_cast<float *
>(original_data.get());
233 float *new_bias =
new float[4 * num_directions * seq_length * batch_size * fAttrHiddenSize];
234 for (
size_t gate = 0; gate < 4; gate++) {
235 std::vector<float>
sum(fAttrHiddenSize);
236 for (
size_t direction = 0; direction < num_directions; direction++) {
237 size_t offset = direction * 8 * fAttrHiddenSize + gate * fAttrHiddenSize;
238 for (
size_t h = 0;
h < fAttrHiddenSize;
h++) {
241 for (
size_t seq = 0; seq < seq_length; seq++) {
242 for (
size_t batch = 0; batch < batch_size; batch++) {
243 size_t bias_offset = gate * num_directions * seq_length * batch_size * fAttrHiddenSize +
244 direction * seq_length * batch_size * fAttrHiddenSize +
245 seq * batch_size * fAttrHiddenSize + batch * fAttrHiddenSize;
246 std::copy(
sum.begin(),
sum.end(), new_bias + bias_offset);
251 std::vector<size_t> new_bias_shape = {4, num_directions, seq_length, batch_size, fAttrHiddenSize};
252 std::shared_ptr<void> new_bias_ptr(new_bias, std::default_delete<
float[]>());
253 model.UpdateInitializedTensor(fNB, model.GetTensorType(fNB), new_bias_shape, new_bias_ptr);
254 fShapeB = model.GetTensorShape(fNB);
258 if (!fNSequence_lens.empty()) {
259 if (!model.CheckIfTensorAlreadyExist(fNSequence_lens)) {
260 throw std::runtime_error(
"TMVA SOFIE LSTM Op input tensor " + fNSequence_lens +
"is not found in model.");
262 fShapeSequence_lens = model.GetTensorShape(fNSequence_lens);
263 if (fShapeSequence_lens.size() != 1) {
264 throw std::runtime_error(
"TMVA SOFIE LSTM Op input tensor " + fNSequence_lens +
" is not of 1 dimension.");
267 if (!fNInitial_h.empty()) {
268 if (!model.CheckIfTensorAlreadyExist(fNInitial_h)) {
269 throw std::runtime_error(
"TMVA SOFIE LSTM Op input tensor " + fNInitial_h +
" is not found in model.");
271 fShapeInitial_h = model.GetTensorShape(fNInitial_h);
272 if (fShapeInitial_h.size() != 3) {
273 throw std::runtime_error(
"TMVA SOFIE LSTM Op input tensor " + fNInitial_h +
" is not of 3 dimensions.");
276 if (!fNInitial_c.empty()) {
277 if (!model.CheckIfTensorAlreadyExist(fNInitial_c)) {
278 throw std::runtime_error(
"TMVA SOFIE LSTM Op input tensor " + fNInitial_c +
" is not found in model.");
280 fShapeInitial_c = model.GetTensorShape(fNInitial_c);
281 if (fShapeInitial_c.size() != 3) {
282 throw std::runtime_error(
"TMVA SOFIE LSTM Op input tensor " + fNInitial_c +
" is not of 3 dimensions.");
286 if (!model.CheckIfTensorAlreadyExist(fNP)) {
287 throw std::runtime_error(
"TMVA SOFIE LSTM op input tensor " + fNP +
" is not found in model.");
289 fShapeP = model.GetTensorShape(fNP);
290 if (fShapeP.size() != 2 && fShapeP.size() != 4) {
291 throw std::runtime_error(
"TMVA SOFIE LSTM op input tensor " + fNP +
" is not of 2 or 4 dimensions.");
293 if (fShapeP.size() == 2) {
295 auto original_data = model.GetInitializedTensorData(fNP);
296 size_t num_directions = fShapeW[0];
297 size_t batch_size = (fAttrLayout == 0) ? fShapeX[1] : fShapeX[0];
298 if (fType ==
"float") {
299 float *original_p =
static_cast<float *
>(original_data.get());
300 float *new_p =
new float[num_directions * 3 * batch_size * fAttrHiddenSize];
301 for (
size_t direction = 0; direction < num_directions; direction++) {
302 for (
size_t gate = 0; gate < 3; gate++) {
303 size_t p_offset = direction * 3 * fAttrHiddenSize + gate * fAttrHiddenSize;
304 for (
size_t batch = 0; batch < batch_size; batch++) {
305 size_t offset = direction * 3 * batch_size * fAttrHiddenSize +
306 gate * batch_size * fAttrHiddenSize + batch * fAttrHiddenSize;
307 std::copy(original_p + p_offset, original_p + p_offset + fAttrHiddenSize, new_p +
offset);
311 std::vector<size_t> new_p_shape = {num_directions, 3, batch_size, fAttrHiddenSize};
312 std::shared_ptr<void> new_p_ptr(new_p, std::default_delete<
float[]>());
313 model.UpdateInitializedTensor(fNP, model.GetTensorType(fNP), new_p_shape, new_p_ptr);
314 fShapeP = model.GetTensorShape(fNP);
319 fShapeY = ShapeInference({fShapeX, fShapeW})[0];
320 if (!model.CheckIfTensorAlreadyExist(fNY)) {
321 model.AddIntermediateTensor(fNY, model.GetTensorType(fNX), fShapeY);
324 if (!fNY_h.empty()) {
325 fShapeY_h = ShapeInference({fShapeX, fShapeW})[1];
326 if (!model.CheckIfTensorAlreadyExist(fNY_h)) {
327 model.AddIntermediateTensor(fNY_h, model.GetTensorType(fNX), fShapeY_h);
330 if (!fNY_c.empty()) {
331 fShapeY_c = ShapeInference({fShapeX, fShapeW})[2];
332 if (!model.CheckIfTensorAlreadyExist(fNY_c)) {
333 model.AddIntermediateTensor(fNY_c, model.GetTensorType(fNX), fShapeY_c);
337 for (
auto &activation : fAttrActivations) {
338 if (activation !=
"Relu" && activation !=
"Tanh" && activation !=
"Sigmoid" && activation !=
"Affine" &&
339 activation !=
"LeakyRelu" && activation !=
"ThresholdRelu" && activation !=
"ScaledTanh" &&
340 activation !=
"HardSigmoid" && activation !=
"Elu" && activation !=
"Softsign" && activation !=
"Softplus") {
341 throw std::runtime_error(
"TMVA SOFIE - Activation function " + activation +
" not implemented");
344 if (fAttrDirection !=
"forward" && fAttrDirection !=
"backward" && fAttrDirection !=
"bidirectional") {
345 throw std::runtime_error(
"TMVA SOFIE - Invalid LSTM direction fAttrDirection = " + fAttrDirection);
347 if (4 * fAttrHiddenSize != fShapeW[1]) {
348 throw std::runtime_error(
"TMVA SOFIE - fAttrHiddenSize must be equal to " + std::to_string(fShapeW[1] / 4));
350 if (fAttrInputForget > 1) {
351 throw std::runtime_error(
"TMVA SOFIE - fAttrInputForget = " + std::to_string(fAttrInputForget) +
354 if (fAttrLayout > 1) {
355 throw std::runtime_error(
"TMVA SOFIE - Layout fAttrLayout = " + std::to_string(fAttrLayout) +
356 " must be 0 (timewise) or 1 (batchwise)");
358 if (fAttrActivations.empty()) {
359 if (fAttrDirection ==
"bidirectional") {
360 fAttrActivations = {
"Sigmoid",
"Tanh",
"Tanh",
"Sigmoid",
"Tanh",
"Tanh"};
362 fAttrActivations = {
"Sigmoid",
"Tanh",
"Tanh"};
445 OpName =
"op_" + OpName;
446 std::stringstream out;
448 size_t seq_length = (fAttrLayout == 0) ? fShapeX[0] : fShapeX[1];
449 size_t batch_size = (fAttrLayout == 0) ? fShapeX[1] : fShapeX[0];
450 size_t input_size = fShapeX[2];
451 size_t num_directions = fShapeW[0];
454 if (fAttrLayout == 0) {
455 out <<
SP << fType <<
" const *" << OpName <<
"_input = tensor_" << fNX <<
";\n";
457 out <<
SP << fType <<
" * " << OpName <<
"_input = this->fVec_" << OpName <<
"_input;\n";
459 out <<
SP <<
"for(size_t seq = 0; seq < " << seq_length <<
"; seq++) {\n";
460 out <<
SP <<
SP <<
"for(size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
461 out <<
SP <<
SP <<
SP <<
"for(size_t i = 0; i < " << input_size <<
"; i++) {\n";
462 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input[seq * " << batch_size * input_size <<
" + batch * " << input_size
463 <<
" + i] = " <<
"tensor_" << fNX <<
"[batch * " << seq_length * input_size <<
" + seq * " << input_size
465 out <<
SP <<
SP <<
SP <<
"}\n";
466 out <<
SP <<
SP <<
"}\n";
471 if (!fNInitial_h.empty()) {
472 if (fAttrLayout == 0) {
473 out <<
SP << fType <<
" const*" << OpName <<
"_initial_hidden_state = " <<
" tensor_" << fNInitial_h <<
";\n";
475 out <<
SP << fType <<
" const* " << OpName <<
"_initial_hidden_state = this->fVec_" << OpName
476 <<
"_initial_hidden_state;\n";
478 for (
size_t direction = 0; direction < num_directions; direction++) {
479 out <<
SP <<
"for(size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
480 out <<
SP <<
SP <<
"for(size_t h = 0; h < " << fAttrHiddenSize <<
"; h++) {\n";
481 out <<
SP <<
SP <<
SP << OpName <<
"_initial_hidden_state[" << direction * batch_size * fAttrHiddenSize
482 <<
" + batch * " << fAttrHiddenSize <<
" + h] = tensor_" << fNInitial_h <<
"[batch * "
483 << num_directions * fAttrHiddenSize <<
" + " << direction * fAttrHiddenSize <<
" + h];\n";
484 out <<
SP <<
SP <<
"}\n";
491 if (!fNInitial_c.empty()) {
492 if (fAttrLayout == 0) {
493 out <<
SP << fType <<
" const*" << OpName <<
"_initial_cell_state = " <<
" tensor_" << fNInitial_c <<
";\n";
495 out <<
SP << fType <<
" const* " << OpName <<
"_initial_cell_state = this->fVec_" << OpName
496 <<
"_initial_cell_state;\n";
498 for (
size_t direction = 0; direction < num_directions; direction++) {
499 out <<
SP <<
"for(size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
500 out <<
SP <<
SP <<
"for(size_t h = 0; h < " << fAttrHiddenSize <<
"; h++) {\n";
501 out <<
SP <<
SP <<
SP << OpName <<
"_initial_cell_state[" << direction * batch_size * fAttrHiddenSize
502 <<
" + batch * " << fAttrHiddenSize <<
" + h] = tensor_" << fNInitial_c <<
"[batch * "
503 << num_directions * fAttrHiddenSize <<
" + " << direction * fAttrHiddenSize <<
" + h];\n";
504 out <<
SP <<
SP <<
"}\n";
511 out <<
SP << fType <<
" * " << OpName <<
"_ff_input_gate = this->fVec_" << OpName <<
"_ff_input_gate;\n";
512 out <<
SP << fType <<
" * " << OpName <<
"_ff_output_gate = this->fVec_" << OpName <<
"_ff_output_gate;\n";
513 out <<
SP << fType <<
" * " << OpName <<
"_ff_cell_gate = this->fVec_" << OpName <<
"_ff_cell_gate;\n";
514 if (fAttrInputForget == 0) {
515 out <<
SP << fType <<
" * " << OpName <<
"_ff_forget_gate = this->fVec_" << OpName <<
"_ff_forget_gate;\n";
518 out <<
SP << fType <<
" * " << OpName <<
"_input_gate = this->fVec_" << OpName <<
"_input_gate;\n";
519 out <<
SP << fType <<
" * " << OpName <<
"_output_gate = this->fVec_" << OpName <<
"_output_gate;\n";
520 out <<
SP << fType <<
" * " << OpName <<
"_cell_gate = this->fVec_" << OpName <<
"_cell_gate;\n";
521 if (fAttrInputForget == 0) {
522 out <<
SP << fType <<
" * " << OpName <<
"_forget_gate = this->fVec_" << OpName <<
"_forget_gate;\n";
525 out <<
SP << fType <<
" * " << OpName <<
"_cell_state = this->fVec_" << OpName <<
"_cell_state;\n";
526 out <<
SP << fType <<
" * " << OpName <<
"_new_cell_state = this->fVec_" << OpName <<
"_new_cell_state;\n";
529 if (fAttrLayout == 0 && !fNY.empty()) {
530 out <<
SP << fType <<
" *" << OpName <<
"_hidden_state = tensor_" << fNY <<
";\n";
532 out <<
SP << fType <<
" * " << OpName <<
"_hidden_state = this->fVec_" << OpName <<
"_hidden_state;\n";
535 out <<
SP <<
"char " << OpName <<
"_transA = 'N';\n";
536 out <<
SP <<
"char " << OpName <<
"_transB = 'T';\n";
537 out <<
SP <<
"int " << OpName <<
"_m = " << seq_length * batch_size <<
";\n";
538 out <<
SP <<
"int " << OpName <<
"_n = " << fAttrHiddenSize <<
";\n";
539 out <<
SP <<
"int " << OpName <<
"_k = " << input_size <<
";\n";
540 if (fType ==
"float") {
541 out <<
SP << fType <<
" " << OpName <<
"_alpha = 1.;\n";
542 out <<
SP << fType <<
" " << OpName <<
"_beta = 0.;\n";
545 out <<
SP <<
"int " << OpName <<
"_bias_size = " << seq_length * batch_size * fAttrHiddenSize <<
";\n";
546 out <<
SP <<
"int " << OpName <<
"_incx = 1;\n";
547 out <<
SP <<
"int " << OpName <<
"_incy = 1;\n";
550 auto emit_sgemm = [&](
const std::string &out_name,
size_t offset) -> std::string {
551 std::stringstream ss;
552 ss <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName <<
"_n, &" << OpName
553 <<
"_m, &" << OpName <<
"_k, &" << OpName <<
"_alpha, tensor_" << fNW;
558 ss <<
", &" << OpName <<
"_k, " << OpName <<
"_input, &" << OpName <<
"_k, &" << OpName <<
"_beta, " << OpName
559 <<
"_" << out_name <<
", &" << OpName <<
"_n);\n";
563 for (
size_t direction = 0; direction < num_directions; direction++) {
564 if (direction == 0) {
565 if (fType ==
"float") {
567 out <<
SP << emit_sgemm(
"ff_input_gate", 0);
569 size_t wo_offset = fAttrHiddenSize * input_size;
570 out <<
SP << emit_sgemm(
"ff_output_gate", wo_offset);
572 size_t wc_offset = 3 * fAttrHiddenSize * input_size;
573 out <<
SP << emit_sgemm(
"ff_cell_gate", wc_offset);
576 if (fType ==
"float") {
578 out <<
SP << emit_sgemm(
"ff_input_gate", 4 * fAttrHiddenSize * input_size);
580 size_t wo_offset = 4 * fAttrHiddenSize * input_size + 1 * fAttrHiddenSize * input_size;
581 out <<
SP << emit_sgemm(
"ff_output_gate", wo_offset);
583 size_t wc_offset = 4 * fAttrHiddenSize * input_size + 3 * fAttrHiddenSize * input_size;
584 out <<
SP << emit_sgemm(
"ff_cell_gate", wc_offset);
587 if (fAttrInputForget == 0) {
589 if (direction == 0) {
590 if (fType ==
"float") {
591 size_t wf_offset = 2 * fAttrHiddenSize * input_size;
592 out <<
SP << emit_sgemm(
"ff_forget_gate", wf_offset);
595 if (fType ==
"float") {
596 size_t wf_offset = 4 * fAttrHiddenSize * input_size + 2 * fAttrHiddenSize * input_size;
597 out <<
SP << emit_sgemm(
"ff_forget_gate", wf_offset);
604 if (direction == 0) {
605 if (fType ==
"float") {
607 out <<
SP <<
"BLAS::saxpy_(&" << OpName <<
"_bias_size, &" << OpName <<
"_alpha, tensor_" << fNB <<
", &"
608 << OpName <<
"_incx, " << OpName <<
"_ff_input_gate, &" << OpName <<
"_incy);\n";
610 size_t bo_offset = seq_length * batch_size * fAttrHiddenSize;
611 out <<
SP <<
"BLAS::saxpy_(&" << OpName <<
"_bias_size, &" << OpName <<
"_alpha, tensor_" << fNB <<
" + "
612 << bo_offset <<
", &" << OpName <<
"_incx, " << OpName <<
"_ff_output_gate, &" << OpName
615 size_t bc_offset = 3 * seq_length * batch_size * fAttrHiddenSize;
616 out <<
SP <<
"BLAS::saxpy_(&" << OpName <<
"_bias_size, &" << OpName <<
"_alpha, tensor_" << fNB <<
" + "
617 << bc_offset <<
", &" << OpName <<
"_incx, " << OpName <<
"_ff_cell_gate, &" << OpName
621 if (fType ==
"float") {
623 size_t bi_offset = 4 * seq_length * batch_size * fAttrHiddenSize;
624 out <<
SP <<
"BLAS::saxpy_(&" << OpName <<
"_bias_size, &" << OpName <<
"_alpha, tensor_" << fNB <<
" + "
625 << bi_offset <<
", &" << OpName <<
"_incx, " << OpName <<
"_ff_input_gate, &" << OpName
629 4 * seq_length * batch_size * fAttrHiddenSize + seq_length * batch_size * fAttrHiddenSize;
630 out <<
SP <<
"BLAS::saxpy_(&" << OpName <<
"_bias_size, &" << OpName <<
"_alpha, tensor_" << fNB <<
" + "
631 << bo_offset <<
", &" << OpName <<
"_incx, " << OpName <<
"_ff_output_gate, &" << OpName
634 size_t bc_offset = 4 * num_directions * seq_length * batch_size * fAttrHiddenSize +
635 3 * seq_length * batch_size * fAttrHiddenSize;
636 out <<
SP <<
"BLAS::saxpy_(&" << OpName <<
"_bias_size, &" << OpName <<
"_alpha, tensor_" << fNB <<
" + "
637 << bc_offset <<
", &" << OpName <<
"_incx, " << OpName <<
"_ff_cell_gate, &" << OpName
641 if (fAttrInputForget == 0) {
643 if (direction == 0) {
644 if (fType ==
"float") {
645 size_t bo_offset = 2 * seq_length * batch_size * fAttrHiddenSize;
646 out <<
SP <<
"BLAS::saxpy_(&" << OpName <<
"_bias_size, &" << OpName <<
"_alpha, tensor_" << fNB
647 <<
" + " << bo_offset <<
", &" << OpName <<
"_incx, " << OpName <<
"_ff_forget_gate, &" << OpName
651 if (fType ==
"float") {
653 4 * seq_length * batch_size * fAttrHiddenSize + 2 * seq_length * batch_size * fAttrHiddenSize;
654 out <<
SP <<
"BLAS::saxpy_(&" << OpName <<
"_bias_size, &" << OpName <<
"_alpha, tensor_" << fNB
655 <<
" + " << bo_offset <<
", &" << OpName <<
"_incx, " << OpName <<
"_ff_forget_gate, &" << OpName
664 out <<
SP <<
"for (size_t seq = 0; seq < " << seq_length <<
"; seq++) {\n";
665 out <<
SP <<
SP <<
"size_t ff_offset = seq * " << batch_size * fAttrHiddenSize <<
";\n";
666 if (direction == 0) {
667 out <<
SP <<
SP <<
"size_t gate_offset = seq * " << num_directions * batch_size * fAttrHiddenSize <<
";\n";
669 out <<
SP <<
SP <<
"size_t gate_offset = seq * " << num_directions * batch_size * fAttrHiddenSize <<
" + "
670 << batch_size * fAttrHiddenSize <<
";\n";
672 size_t ff_seq_size = batch_size * fAttrHiddenSize;
673 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_ff_input_gate + ff_offset, " << OpName
674 <<
"_ff_input_gate + ff_offset + " << ff_seq_size <<
", " << OpName <<
"_input_gate + gate_offset);\n";
675 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_ff_output_gate + ff_offset, " << OpName
676 <<
"_ff_output_gate + ff_offset + " << ff_seq_size <<
", " << OpName <<
"_output_gate + gate_offset);\n";
677 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_ff_cell_gate + ff_offset, " << OpName
678 <<
"_ff_cell_gate + ff_offset + " << ff_seq_size <<
", " << OpName <<
"_cell_gate + gate_offset);\n";
679 if (fAttrInputForget == 0) {
680 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_ff_forget_gate + ff_offset, " << OpName
681 <<
"_ff_forget_gate + ff_offset + " << ff_seq_size <<
", " << OpName <<
"_forget_gate + gate_offset);\n";
685 out <<
SP <<
"for (size_t seq = 0; seq < " << seq_length <<
"; seq++) {\n";
686 if (fAttrDirection ==
"backward" || direction == 1) {
687 out <<
SP <<
SP <<
"size_t index = " << seq_length - 1 <<
" - seq;\n";
689 out <<
SP <<
SP <<
"size_t index = seq;\n";
691 out <<
SP <<
SP <<
"int m2 = " << batch_size <<
";\n";
692 if (direction == 0) {
693 out <<
SP <<
SP <<
"size_t offset = index * " << num_directions * batch_size * fAttrHiddenSize <<
";\n";
695 out <<
SP <<
SP <<
"size_t offset = index * " << num_directions * batch_size * fAttrHiddenSize <<
" + "
696 << batch_size * fAttrHiddenSize <<
";\n";
698 size_t size = batch_size * fAttrHiddenSize;
700 out <<
SP <<
SP <<
"if (seq == 0) {\n";
701 if (!fNInitial_h.empty()) {
702 if (direction == 0) {
703 if (fType ==
"float") {
704 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
705 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
", &" << OpName
706 <<
"_n, " << OpName <<
"_initial_hidden_state, &" << OpName <<
"_n, &" << OpName <<
"_alpha, "
707 << OpName <<
"_input_gate + offset, &" << OpName <<
"_n);\n";
708 size_t ro_offset = fAttrHiddenSize * fAttrHiddenSize;
709 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
710 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + " << ro_offset
711 <<
", &" << OpName <<
"_n, " << OpName <<
"_initial_hidden_state, &" << OpName <<
"_n, &" << OpName
712 <<
"_alpha, " << OpName <<
"_output_gate + offset, &" << OpName <<
"_n);\n";
713 size_t rc_offset = 3 * fAttrHiddenSize * fAttrHiddenSize;
714 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
715 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + " << rc_offset
716 <<
", &" << OpName <<
"_n, " << OpName <<
"_initial_hidden_state, &" << OpName <<
"_n, &" << OpName
717 <<
"_alpha, " << OpName <<
"_cell_gate + offset, &" << OpName <<
"_n);\n";
718 if (fAttrInputForget == 0) {
719 size_t rf_offset = 2 * fAttrHiddenSize * fAttrHiddenSize;
720 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &"
721 << OpName <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + "
722 << rf_offset <<
", &" << OpName <<
"_n, " << OpName <<
"_initial_hidden_state, &" << OpName
723 <<
"_n, &" << OpName <<
"_alpha, " << OpName <<
"_forget_gate + offset, &" << OpName <<
"_n);\n";
727 if (fType ==
"float") {
728 size_t ri_offset = 4 * fAttrHiddenSize * fAttrHiddenSize;
729 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
730 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + " << ri_offset
731 <<
", &" << OpName <<
"_n, " << OpName <<
"_initial_hidden_state, &" << OpName <<
"_n, &" << OpName
732 <<
"_alpha, " << OpName <<
"_input_gate + offset, &" << OpName <<
"_n);\n";
733 size_t ro_offset = 4 * fAttrHiddenSize * fAttrHiddenSize + 1 * fAttrHiddenSize * fAttrHiddenSize;
734 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
735 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + " << ro_offset
736 <<
", &" << OpName <<
"_n, " << OpName <<
"_initial_hidden_state, &" << OpName <<
"_n, &" << OpName
737 <<
"_alpha, " << OpName <<
"_output_gate + offset, &" << OpName <<
"_n);\n";
738 size_t rc_offset = 4 * fAttrHiddenSize * fAttrHiddenSize + 3 * fAttrHiddenSize * fAttrHiddenSize;
739 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
740 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + " << rc_offset
741 <<
", &" << OpName <<
"_n, " << OpName <<
"_initial_hidden_state, &" << OpName <<
"_n, &" << OpName
742 <<
"_alpha, " << OpName <<
"_cell_gate + offset, &" << OpName <<
"_n);\n";
743 if (fAttrInputForget == 0) {
744 size_t rf_offset = 4 * fAttrHiddenSize * fAttrHiddenSize + 2 * fAttrHiddenSize * fAttrHiddenSize;
745 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &"
746 << OpName <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + "
747 << rf_offset <<
", &" << OpName <<
"_n, " << OpName <<
"_initial_hidden_state, &" << OpName
748 <<
"_n, &" << OpName <<
"_alpha, " << OpName <<
"_forget_gate + offset, &" << OpName <<
"_n);\n";
753 out <<
SP <<
SP <<
"} else {\n";
755 if (direction == 0) {
756 if (fAttrDirection ==
"backward") {
757 out <<
SP <<
SP <<
SP <<
"size_t previous_offset = (index + 1) * "
758 << num_directions * batch_size * fAttrHiddenSize <<
";\n";
760 out <<
SP <<
SP <<
SP <<
"size_t previous_offset = (seq - 1) * "
761 << num_directions * batch_size * fAttrHiddenSize <<
";\n";
763 if (fType ==
"float") {
764 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
765 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
", &" << OpName <<
"_n, "
766 << OpName <<
"_hidden_state + previous_offset, &" << OpName <<
"_n, &" << OpName <<
"_alpha, " << OpName
767 <<
"_input_gate + offset, &" << OpName <<
"_n);\n";
768 size_t ro_offset = 1 * fAttrHiddenSize * fAttrHiddenSize;
769 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
770 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + " << ro_offset
771 <<
", &" << OpName <<
"_n, " << OpName <<
"_hidden_state + previous_offset, &" << OpName <<
"_n, &"
772 << OpName <<
"_alpha, " << OpName <<
"_output_gate + offset, &" << OpName <<
"_n);\n";
773 size_t rc_offset = 3 * fAttrHiddenSize * fAttrHiddenSize;
774 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
775 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + " << rc_offset
776 <<
", &" << OpName <<
"_n, " << OpName <<
"_hidden_state + previous_offset, &" << OpName <<
"_n, &"
777 << OpName <<
"_alpha, " << OpName <<
"_cell_gate + offset, &" << OpName <<
"_n);\n";
778 if (fAttrInputForget == 0) {
779 size_t rf_offset = 2 * fAttrHiddenSize * fAttrHiddenSize;
780 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
781 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + " << rf_offset
782 <<
", &" << OpName <<
"_n, " << OpName <<
"_hidden_state + previous_offset, &" << OpName <<
"_n, &"
783 << OpName <<
"_alpha, " << OpName <<
"_forget_gate + offset, &" << OpName <<
"_n);\n";
787 out <<
SP <<
SP <<
SP <<
"size_t previous_offset = (index + 1) * "
788 << num_directions * batch_size * fAttrHiddenSize <<
" + " << batch_size * fAttrHiddenSize <<
";\n";
789 if (fType ==
"float") {
790 size_t ri_offset = 4 * fAttrHiddenSize * fAttrHiddenSize;
791 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
792 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + " << ri_offset
793 <<
", &" << OpName <<
"_n, " << OpName <<
"_hidden_state + previous_offset, &" << OpName <<
"_n, &"
794 << OpName <<
"_alpha, " << OpName <<
"_input_gate + offset, &" << OpName <<
"_n);\n";
795 size_t ro_offset = 4 * fAttrHiddenSize * fAttrHiddenSize + fAttrHiddenSize * fAttrHiddenSize;
796 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
797 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + " << ro_offset
798 <<
", &" << OpName <<
"_n, " << OpName <<
"_hidden_state + previous_offset, &" << OpName <<
"_n, &"
799 << OpName <<
"_alpha, " << OpName <<
"_output_gate + offset, &" << OpName <<
"_n);\n";
800 size_t rc_offset = 4 * fAttrHiddenSize * fAttrHiddenSize + 3 * fAttrHiddenSize * fAttrHiddenSize;
801 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
802 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + " << rc_offset
803 <<
", &" << OpName <<
"_n, " << OpName <<
"_hidden_state + previous_offset, &" << OpName <<
"_n, &"
804 << OpName <<
"_alpha, " << OpName <<
"_cell_gate + offset, &" << OpName <<
"_n);\n";
805 if (fAttrInputForget == 0) {
806 size_t rf_offset = 4 * fAttrHiddenSize * fAttrHiddenSize + 2 * fAttrHiddenSize * fAttrHiddenSize;
807 out <<
SP <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transB, &" << OpName <<
"_transA, &" << OpName
808 <<
"_n, &m2, &" << OpName <<
"_n, &" << OpName <<
"_alpha, tensor_" << fNR <<
" + " << rf_offset
809 <<
", &" << OpName <<
"_n, " << OpName <<
"_hidden_state + previous_offset, &" << OpName <<
"_n, &"
810 << OpName <<
"_alpha, " << OpName <<
"_forget_gate + offset, &" << OpName <<
"_n);\n";
814 out <<
SP <<
SP <<
"}\n";
817 if (fAttrClip > .0) {
818 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
819 if (fType ==
"float") {
820 out <<
SP <<
SP <<
SP <<
"float x = (" << OpName <<
"_cell_gate[i] > " << -fAttrClip <<
") ? " << OpName
821 <<
"_cell_gate[i] : " << -fAttrClip <<
";\n";
823 out <<
SP <<
SP <<
SP << OpName <<
"_cell_gate[i] = (x < " << fAttrClip <<
") ? x : " << fAttrClip <<
";\n";
824 out <<
SP <<
SP <<
"}\n";
827 if (fAttrActivations[direction * 3 + 1] ==
"Relu") {
828 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
829 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_cell_gate[i] < 0.)\n";
830 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_cell_gate[i] = 0.;\n";
831 out <<
SP <<
SP <<
"}\n";
832 }
else if (fAttrActivations[direction * 3 + 1] ==
"Tanh") {
833 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
834 if (fType ==
"float") {
835 out <<
SP <<
SP <<
SP <<
"float ex = exp(-2 * " << OpName <<
"_cell_gate[i]);\n";
837 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_cell_gate[i] = (1. - ex) / (1. + ex);\n";
838 out <<
SP <<
SP <<
"}\n";
839 }
else if (fAttrActivations[direction * 3 + 1] ==
"Sigmoid") {
840 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
841 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_cell_gate[i] = 1. / (1. + exp(-" << OpName <<
"_cell_gate[i]));\n";
842 out <<
SP <<
SP <<
"}\n";
843 }
else if (fAttrActivations[direction * 3 + 1] ==
"Affine") {
844 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
845 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_cell_gate[i] = " << fAttrActivationAlpha[direction * 3 + 1] <<
" * "
846 << OpName <<
"_cell_gate[i] + " << fAttrActivationBeta[direction * 3 + 1] <<
";\n";
847 out <<
SP <<
SP <<
"}\n";
848 }
else if (fAttrActivations[direction * 3 + 1] ==
"ScaledTanh") {
849 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
850 if (fType ==
"float") {
851 out <<
SP <<
SP <<
SP <<
"float ex = exp(-2 * " << fAttrActivationBeta[direction * 3 + 1] <<
" * " << OpName
852 <<
"_cell_gate[i]);\n";
854 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_cell_gate[i] = " << fAttrActivationAlpha[direction * 3 + 1]
855 <<
" * (1. - ex) / (1. + ex);\n";
856 out <<
SP <<
SP <<
"}\n";
857 }
else if (fAttrActivations[direction * 3 + 1] ==
"HardSigmoid") {
858 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
859 if (fType ==
"float") {
860 out <<
SP <<
SP <<
SP <<
"float a = " << fAttrActivationAlpha[direction * 3 + 1] <<
" * " << OpName
861 <<
"_cell_gate[i] + " << fAttrActivationBeta[direction * 3 + 1] <<
";\n";
862 out <<
SP <<
SP <<
SP <<
"float b = (a > 0.) ? a : 0.;\n";
864 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_cell_gate[i] = (b < 1.) ? b : 1.;\n";
865 out <<
SP <<
SP <<
"}\n";
866 }
else if (fAttrActivations[direction * 3 + 1] ==
"LeakyRelu") {
867 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
868 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_cell_gate[i] < 0.)\n";
869 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_cell_gate[i] = " << fAttrActivationAlpha[direction * 3 + 1] <<
" * "
870 << OpName <<
"_cell_gate[i];\n";
871 out <<
SP <<
SP <<
"}\n";
872 }
else if (fAttrActivations[direction * 3 + 1] ==
"ThresholdRelu") {
873 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
874 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_cell_gate[i] < " << fAttrActivationAlpha[direction * 3 + 1]
876 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_cell_gate[i] = 0.;\n";
877 out <<
SP <<
SP <<
"}";
878 }
else if (fAttrActivations[direction * 3 + 1] ==
"Elu") {
879 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
880 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_cell_gate[i] < 0.)\n";
881 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_cell_gate[i] = " << fAttrActivationAlpha[direction * 3 + 1]
882 <<
" * exp(" << OpName <<
"_cell_gate[i] - 1.);\n";
883 out <<
SP <<
SP <<
"}\n";
884 }
else if (fAttrActivations[direction * 3 + 1] ==
"Softsign") {
885 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
886 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_cell_gate[i] = " << OpName <<
"_cell_gate[i] / (1. + abs(" << OpName
887 <<
"_cell_gate[i]));\n";
888 out <<
SP <<
SP <<
"}\n";
890 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
891 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_cell_gate[i] = log(1. + exp(" << OpName <<
"_cell_gate[i]));\n";
892 out <<
SP <<
SP <<
"}\n";
898 out <<
SP <<
SP <<
"if (seq == 0) {\n";
899 if (!fNInitial_c.empty()) {
900 if (direction == 0) {
901 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " <<
size <<
"; i++) {\n";
902 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i + offset] += tensor_" << fNP <<
"[i] * "
903 << OpName <<
"_initial_cell_state[i];\n";
904 out <<
SP <<
SP <<
SP <<
"}\n";
905 if (fAttrInputForget == 0) {
906 size_t pf_offset = batch_size * fAttrHiddenSize;
907 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " <<
size <<
"; i++) {\n";
908 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i + offset] += tensor_" << fNP <<
"[i + "
909 << pf_offset <<
"] * " << OpName <<
"_initial_cell_state[i];\n";
910 out <<
SP <<
SP <<
SP <<
"}\n";
913 size_t pi_offset = 3 * batch_size * fAttrHiddenSize;
914 size_t initial_c_offset = batch_size * fAttrHiddenSize;
915 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " <<
size <<
"; i++) {\n";
916 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i + offset] += tensor_" << fNP <<
"[i + "
917 << pi_offset <<
"] * " << OpName <<
"_initial_cell_state[i + " << initial_c_offset <<
"];\n";
918 out <<
SP <<
SP <<
SP <<
"}\n";
919 if (fAttrInputForget == 0) {
920 size_t pf_offset = 3 * batch_size * fAttrHiddenSize + batch_size * fAttrHiddenSize;
921 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " <<
size <<
"; i++) {\n";
922 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i + offset] += tensor_" << fNP <<
"[i + "
923 << pf_offset <<
"] * " << OpName <<
"_initial_cell_state[i + " << initial_c_offset <<
"];\n";
924 out <<
SP <<
SP <<
SP <<
"}\n";
928 out <<
SP <<
SP <<
"} else {\n";
929 if (direction == 0) {
930 if (fAttrDirection ==
"backward") {
931 out <<
SP <<
SP <<
SP <<
"size_t c_offset = (index + 1) * "
932 << num_directions * batch_size * fAttrHiddenSize <<
";\n";
934 out <<
SP <<
SP <<
SP <<
"size_t c_offset = (seq - 1) * "
935 << num_directions * batch_size * fAttrHiddenSize <<
";\n";
937 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " <<
size <<
"; i++) {\n";
938 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i + offset] += tensor_" << fNP <<
"[i] * " << OpName
939 <<
"_cell_state[i + c_offset];\n";
940 out <<
SP <<
SP <<
SP <<
"}\n";
941 if (fAttrInputForget == 0) {
942 size_t pf_offset = batch_size * fAttrHiddenSize;
943 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " <<
size <<
"; i++) {\n";
944 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i + offset] += tensor_" << fNP <<
"[i + "
945 << pf_offset <<
"] * " << OpName <<
"_cell_state[i + c_offset];\n";
946 out <<
SP <<
SP <<
SP <<
"}\n";
949 size_t pi_offset = 3 * batch_size * fAttrHiddenSize;
950 out <<
SP <<
SP <<
SP <<
"size_t c_offset = (index + 1) * " << num_directions * batch_size * fAttrHiddenSize
951 <<
" + " << batch_size * fAttrHiddenSize <<
";\n";
952 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " <<
size <<
"; i++) {\n";
953 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i + offset] += tensor_" << fNP <<
"[i + " << pi_offset
954 <<
"] * " << OpName <<
"_cell_state[i + c_offset];\n";
955 out <<
SP <<
SP <<
SP <<
"}\n";
956 if (fAttrInputForget == 0) {
957 size_t pf_offset = 3 * batch_size * fAttrHiddenSize + batch_size * fAttrHiddenSize;
958 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " <<
size <<
"; i++) {\n";
959 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i + offset] += tensor_" << fNP <<
"[i + "
960 << pf_offset <<
"] * " << OpName <<
"_cell_state[i + c_offset];\n";
961 out <<
SP <<
SP <<
SP <<
"}\n";
964 out <<
SP <<
SP <<
"}\n";
968 if (fAttrClip > .0) {
969 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
970 if (fType ==
"float") {
971 out <<
SP <<
SP <<
SP <<
"float x = (" << OpName <<
"_input_gate[i] > " << -fAttrClip <<
") ? " << OpName
972 <<
"_input_gate[i] : " << -fAttrClip <<
";\n";
974 out <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i] = (x < " << fAttrClip <<
") ? x : " << fAttrClip <<
";\n";
975 out <<
SP <<
SP <<
"}\n";
978 if (fAttrActivations[direction * 3] ==
"Relu") {
979 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
980 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_input_gate[i] < 0.)\n";
981 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i] = 0.;\n";
982 out <<
SP <<
SP <<
"}\n";
983 }
else if (fAttrActivations[direction * 3] ==
"Tanh") {
984 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
985 if (fType ==
"float") {
986 out <<
SP <<
SP <<
SP <<
"float ex = exp(-2 * " << OpName <<
"_input_gate[i]);\n";
988 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i] = (1. - ex) / (1. + ex);\n";
989 out <<
SP <<
SP <<
"}\n";
990 }
else if (fAttrActivations[direction * 3] ==
"Sigmoid") {
991 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
992 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i] = 1. / (1. + exp(-" << OpName
993 <<
"_input_gate[i]));\n";
994 out <<
SP <<
SP <<
"}\n";
995 }
else if (fAttrActivations[direction * 3] ==
"Affine") {
996 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
997 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i] = " << fAttrActivationAlpha[direction * 3] <<
" * "
998 << OpName <<
"_input_gate[i] + " << fAttrActivationBeta[direction * 3] <<
";\n";
999 out <<
SP <<
SP <<
"}\n";
1000 }
else if (fAttrActivations[direction * 3] ==
"ScaledTanh") {
1001 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1002 if (fType ==
"float") {
1003 out <<
SP <<
SP <<
SP <<
"float ex = exp(-2 * " << fAttrActivationBeta[direction * 3] <<
" * " << OpName
1004 <<
"_input_gate[i]);\n";
1006 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i] = " << fAttrActivationAlpha[direction * 3]
1007 <<
" * (1. - ex) / (1. + ex);\n";
1008 out <<
SP <<
SP <<
"}\n";
1009 }
else if (fAttrActivations[direction * 3] ==
"HardSigmoid") {
1010 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1011 if (fType ==
"float") {
1012 out <<
SP <<
SP <<
SP <<
"float a = " << fAttrActivationAlpha[direction * 3] <<
" * " << OpName
1013 <<
"_input_gate[i] + " << fAttrActivationBeta[direction * 3] <<
";\n";
1014 out <<
SP <<
SP <<
SP <<
"float b = (a > 0.) ? a : 0.;\n";
1016 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i] = (b < 1.) ? b : 1.;\n";
1017 out <<
SP <<
SP <<
"}\n";
1018 }
else if (fAttrActivations[direction * 3] ==
"LeakyRelu") {
1019 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1020 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_input_gate[i] < 0.)\n";
1021 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i] = " << fAttrActivationAlpha[direction * 3] <<
" * "
1022 << OpName <<
"_input_gate[i];\n";
1023 out <<
SP <<
SP <<
"}\n";
1024 }
else if (fAttrActivations[direction * 3] ==
"ThresholdRelu") {
1025 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1026 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_input_gate[i] < " << fAttrActivationAlpha[direction * 3]
1028 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i] = 0.;\n";
1029 out <<
SP <<
SP <<
"}";
1030 }
else if (fAttrActivations[direction * 3] ==
"Elu") {
1031 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1032 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_input_gate[i] < 0.)\n";
1033 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i] = " << fAttrActivationAlpha[direction * 3]
1034 <<
" * exp(" << OpName <<
"_input_gate[i] - 1.);\n";
1035 out <<
SP <<
SP <<
"}\n";
1036 }
else if (fAttrActivations[direction * 3] ==
"Softsign") {
1037 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1038 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i] = " << OpName <<
"_input_gate[i] / (1. + abs("
1039 << OpName <<
"_input_gate[i]));\n";
1040 out <<
SP <<
SP <<
"}\n";
1042 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1043 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_input_gate[i] = log(1. + exp(" << OpName <<
"_input_gate[i]));\n";
1044 out <<
SP <<
SP <<
"}\n";
1047 if (fAttrInputForget == 0) {
1049 if (fAttrClip > .0) {
1050 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1051 if (fType ==
"float") {
1052 out <<
SP <<
SP <<
SP <<
"float x = (" << OpName <<
"_forget_gate[i] > " << -fAttrClip <<
") ? "
1053 << OpName <<
"_forget_gate[i] : " << -fAttrClip <<
";\n";
1055 out <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i] = (x < " << fAttrClip <<
") ? x : " << fAttrClip
1057 out <<
SP <<
SP <<
"}\n";
1060 if (fAttrActivations[direction * 3] ==
"Relu") {
1061 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1062 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_forget_gate[i] < 0.)\n";
1063 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i] = 0.;\n";
1064 out <<
SP <<
SP <<
"}\n";
1065 }
else if (fAttrActivations[direction * 3] ==
"Tanh") {
1066 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1067 if (fType ==
"float") {
1068 out <<
SP <<
SP <<
SP <<
"float ex = exp(-2 * " << OpName <<
"_forget_gate[i]);\n";
1070 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i] = (1. - ex) / (1. + ex);\n";
1071 out <<
SP <<
SP <<
"}\n";
1072 }
else if (fAttrActivations[direction * 3] ==
"Sigmoid") {
1073 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1074 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i] = 1. / (1. + exp(-" << OpName
1075 <<
"_forget_gate[i]));\n";
1076 out <<
SP <<
SP <<
"}\n";
1077 }
else if (fAttrActivations[direction * 3] ==
"Affine") {
1078 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1079 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i] = " << fAttrActivationAlpha[direction * 3]
1080 <<
" * " << OpName <<
"_forget_gate[i] + " << fAttrActivationBeta[direction * 3] <<
";\n";
1081 out <<
SP <<
SP <<
"}\n";
1082 }
else if (fAttrActivations[direction * 3] ==
"ScaledTanh") {
1083 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1084 if (fType ==
"float") {
1085 out <<
SP <<
SP <<
SP <<
"float ex = exp(-2 * " << fAttrActivationBeta[direction * 3] <<
" * " << OpName
1086 <<
"_forget_gate[i]);\n";
1088 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i] = " << fAttrActivationAlpha[direction * 3]
1089 <<
" * (1. - ex) / (1. + ex);\n";
1090 out <<
SP <<
SP <<
"}\n";
1091 }
else if (fAttrActivations[direction * 3] ==
"HardSigmoid") {
1092 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1093 if (fType ==
"float") {
1094 out <<
SP <<
SP <<
SP <<
"float a = " << fAttrActivationAlpha[direction * 3] <<
" * " << OpName
1095 <<
"_forget_gate[i] + " << fAttrActivationBeta[direction * 3] <<
";\n";
1096 out <<
SP <<
SP <<
SP <<
"float b = (a > 0.) ? a : 0.;\n";
1098 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i] = (b < 1.) ? b : 1.;\n";
1099 out <<
SP <<
SP <<
"}\n";
1100 }
else if (fAttrActivations[direction * 3] ==
"LeakyRelu") {
1101 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1102 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_forget_gate[i] < 0.)\n";
1103 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i] = " << fAttrActivationAlpha[direction * 3]
1104 <<
" * " << OpName <<
"_forget_gate[i];\n";
1105 out <<
SP <<
SP <<
"}\n";
1106 }
else if (fAttrActivations[direction * 3] ==
"ThresholdRelu") {
1107 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1108 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_forget_gate[i] < " << fAttrActivationAlpha[direction * 3]
1110 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i] = 0.;\n";
1111 out <<
SP <<
SP <<
"}";
1112 }
else if (fAttrActivations[direction * 3] ==
"Elu") {
1113 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1114 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_forget_gate[i] < 0.)\n";
1115 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i] = " << fAttrActivationAlpha[direction * 3]
1116 <<
" * exp(" << OpName <<
"_forget_gate[i] - 1.);\n";
1117 out <<
SP <<
SP <<
"}\n";
1118 }
else if (fAttrActivations[direction * 3] ==
"Softsign") {
1119 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1120 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i] = " << OpName <<
"_forget_gate[i] / (1. + abs("
1121 << OpName <<
"_forget_gate[i]));\n";
1122 out <<
SP <<
SP <<
"}\n";
1124 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1125 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_forget_gate[i] = log(1. + exp(" << OpName
1126 <<
"_forget_gate[i]));\n";
1127 out <<
SP <<
SP <<
"}\n";
1132 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1133 out <<
SP <<
SP <<
SP << OpName <<
"_cell_state[i] = " << OpName <<
"_input_gate[i] * " << OpName
1134 <<
"_cell_gate[i];\n";
1135 out <<
SP <<
SP <<
"}\n";
1137 if (fAttrInputForget == 0) {
1138 out <<
SP <<
SP <<
"if (seq == 0) {\n";
1139 if (!fNInitial_c.empty()) {
1141 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " <<
size <<
"; i++) {\n";
1142 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_cell_state[i + offset] += " << OpName
1143 <<
"_forget_gate[i + offset] * " << OpName <<
"_initial_cell_state[i];\n";
1144 out <<
SP <<
SP <<
SP <<
"}\n";
1146 out <<
SP <<
SP <<
"} else {\n";
1148 if (direction == 0) {
1149 if (fAttrDirection ==
"backward") {
1150 out <<
SP <<
SP <<
SP <<
"size_t previous_offset = (index + 1) * "
1151 << num_directions * batch_size * fAttrHiddenSize <<
";\n";
1153 out <<
SP <<
SP <<
SP <<
"size_t previous_offset = (seq - 1) * "
1154 << num_directions * batch_size * fAttrHiddenSize <<
";\n";
1157 out <<
SP <<
SP <<
SP <<
"size_t previous_offset = (index + 1) * "
1158 << num_directions * batch_size * fAttrHiddenSize <<
" + " << batch_size * fAttrHiddenSize <<
";\n";
1160 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " <<
size <<
"; i++) {\n";
1161 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_cell_state[i + offset] += " << OpName
1162 <<
"_forget_gate[i + offset] * " << OpName <<
"_cell_state[i + previous_offset];\n";
1163 out <<
SP <<
SP <<
SP <<
"}\n";
1164 out <<
SP <<
SP <<
"}\n";
1169 if (direction == 0) {
1170 size_t p_offset = 2 * batch_size * fAttrHiddenSize;
1171 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " <<
size <<
"; i++) {\n";
1172 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_output_gate[i + offset] += tensor_" << fNP <<
"[i + " << p_offset
1173 <<
"] * " << OpName <<
"_cell_state[i + offset];\n";
1174 out <<
SP <<
SP <<
SP <<
"}\n";
1176 size_t p_offset = 3 * batch_size * fAttrHiddenSize + 2 * batch_size * fAttrHiddenSize;
1177 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " <<
size <<
"; i++) {\n";
1178 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_output_gate[i + offset] += tensor_" << fNP <<
"[i + " << p_offset
1179 <<
"] * " << OpName <<
"_cell_state[i + offset];\n";
1180 out <<
SP <<
SP <<
SP <<
"}\n";
1185 if (fAttrClip > .0) {
1186 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1187 if (fType ==
"float") {
1188 out <<
SP <<
SP <<
SP <<
"float x = (" << OpName <<
"_output_gate[i] > " << -fAttrClip <<
") ? " << OpName
1189 <<
"_output_gate[i] : " << -fAttrClip <<
";\n";
1191 out <<
SP <<
SP <<
SP << OpName <<
"_output_gate[i] = (x < " << fAttrClip <<
") ? x : " << fAttrClip <<
";\n";
1192 out <<
SP <<
SP <<
"}\n";
1195 if (fAttrActivations[direction * 3] ==
"Relu") {
1196 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1197 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_output_gate[i] < 0.)\n";
1198 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_output_gate[i] = 0.;\n";
1199 out <<
SP <<
SP <<
"}\n";
1200 }
else if (fAttrActivations[direction * 3] ==
"Tanh") {
1201 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1202 if (fType ==
"float") {
1203 out <<
SP <<
SP <<
SP <<
"float ex = exp(-2 * " << OpName <<
"_output_gate[i]);\n";
1205 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_output_gate[i] = (1. - ex) / (1. + ex);\n";
1206 out <<
SP <<
SP <<
"}\n";
1207 }
else if (fAttrActivations[direction * 3] ==
"Sigmoid") {
1208 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1209 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_output_gate[i] = 1. / (1. + exp(-" << OpName
1210 <<
"_output_gate[i]));\n";
1211 out <<
SP <<
SP <<
"}\n";
1212 }
else if (fAttrActivations[direction * 3] ==
"Affine") {
1213 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1214 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_output_gate[i] = " << fAttrActivationAlpha[direction * 3] <<
" * "
1215 << OpName <<
"_output_gate[i] + " << fAttrActivationBeta[direction * 3] <<
";\n";
1216 out <<
SP <<
SP <<
"}\n";
1217 }
else if (fAttrActivations[direction * 3] ==
"ScaledTanh") {
1218 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1219 if (fType ==
"float") {
1220 out <<
SP <<
SP <<
SP <<
"float ex = exp(-2 * " << fAttrActivationBeta[direction * 3] <<
" * " << OpName
1221 <<
"_output_gate[i]);\n";
1223 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_output_gate[i] = " << fAttrActivationAlpha[direction * 3]
1224 <<
" * (1. - ex) / (1. + ex);\n";
1225 out <<
SP <<
SP <<
"}\n";
1226 }
else if (fAttrActivations[direction * 3] ==
"HardSigmoid") {
1227 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1228 if (fType ==
"float") {
1229 out <<
SP <<
SP <<
SP <<
"float a = " << fAttrActivationAlpha[direction * 3] <<
" * " << OpName
1230 <<
"_output_gate[i] + " << fAttrActivationBeta[direction * 3] <<
";\n";
1231 out <<
SP <<
SP <<
SP <<
"float b = (a > 0.) ? a : 0.;\n";
1233 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_output_gate[i] = (b < 1.) ? b : 1.;\n";
1234 out <<
SP <<
SP <<
"}\n";
1235 }
else if (fAttrActivations[direction * 3] ==
"LeakyRelu") {
1236 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1237 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_output_gate[i] < 0.)\n";
1238 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_output_gate[i] = " << fAttrActivationAlpha[direction * 3] <<
" * "
1239 << OpName <<
"_output_gate[i];\n";
1240 out <<
SP <<
SP <<
"}\n";
1241 }
else if (fAttrActivations[direction * 3] ==
"ThresholdRelu") {
1242 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1243 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_output_gate[i] < " << fAttrActivationAlpha[direction * 3]
1245 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_output_gate[i] = 0.;\n";
1246 out <<
SP <<
SP <<
"}";
1247 }
else if (fAttrActivations[direction * 3] ==
"Elu") {
1248 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1249 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_output_gate[i] < 0.)\n";
1250 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_output_gate[i] = " << fAttrActivationAlpha[direction * 3]
1251 <<
" * exp(" << OpName <<
"_output_gate[i] - 1.);\n";
1252 out <<
SP <<
SP <<
"}\n";
1253 }
else if (fAttrActivations[direction * 3] ==
"Softsign") {
1254 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1255 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_output_gate[i] = " << OpName <<
"_output_gate[i] / (1. + abs("
1256 << OpName <<
"_output_gate[i]));\n";
1257 out <<
SP <<
SP <<
"}\n";
1259 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1260 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_output_gate[i] = log(1. + exp(" << OpName <<
"_output_gate[i]));\n";
1261 out <<
SP <<
SP <<
"}\n";
1265 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_cell_state + offset, " << OpName <<
"_cell_state + offset + "
1266 <<
size <<
", " << OpName <<
"_new_cell_state + offset);\n";
1268 if (fAttrClip > .0) {
1269 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1270 if (fType ==
"float") {
1271 out <<
SP <<
SP <<
SP <<
"float x = (" << OpName <<
"_new_cell_state[i] > " << -fAttrClip <<
") ? "
1272 << OpName <<
"_new_cell_state[i] : " << -fAttrClip <<
";\n";
1274 out <<
SP <<
SP <<
SP << OpName <<
"_new_cell_state[i] = (x < " << fAttrClip <<
") ? x : " << fAttrClip
1276 out <<
SP <<
SP <<
"}\n";
1279 if (fAttrActivations[direction * 3 + 2] ==
"Relu") {
1280 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1281 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_new_cell_state[i] < 0.)\n";
1282 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_new_cell_state[i] = 0.;\n";
1283 out <<
SP <<
SP <<
"}\n";
1284 }
else if (fAttrActivations[direction * 3 + 2] ==
"Tanh") {
1285 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1286 if (fType ==
"float") {
1287 out <<
SP <<
SP <<
SP <<
"float ex = exp(-2 * " << OpName <<
"_new_cell_state[i]);\n";
1289 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_new_cell_state[i] = (1. - ex) / (1. + ex);\n";
1290 out <<
SP <<
SP <<
"}\n";
1291 }
else if (fAttrActivations[direction * 3 + 2] ==
"Sigmoid") {
1292 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1293 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_new_cell_state[i] = 1. / (1. + exp(-" << OpName
1294 <<
"_new_cell_state[i]));\n";
1295 out <<
SP <<
SP <<
"}\n";
1296 }
else if (fAttrActivations[direction * 3 + 2] ==
"Affine") {
1297 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1298 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_new_cell_state[i] = " << fAttrActivationAlpha[direction * 3 + 2]
1299 <<
" * " << OpName <<
"_new_cell_state[i] + " << fAttrActivationBeta[direction * 3 + 2] <<
";\n";
1300 out <<
SP <<
SP <<
"}\n";
1301 }
else if (fAttrActivations[direction * 3 + 2] ==
"ScaledTanh") {
1302 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1303 if (fType ==
"float") {
1304 out <<
SP <<
SP <<
SP <<
"float ex = exp(-2 * " << fAttrActivationBeta[direction * 3 + 2] <<
" * " << OpName
1305 <<
"_new_cell_state[i]);\n";
1307 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_new_cell_state[i] = " << fAttrActivationAlpha[direction * 3 + 2]
1308 <<
" * (1. - ex) / (1. + ex);\n";
1309 out <<
SP <<
SP <<
"}\n";
1310 }
else if (fAttrActivations[direction * 3 + 2] ==
"HardSigmoid") {
1311 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1312 if (fType ==
"float") {
1313 out <<
SP <<
SP <<
SP <<
"float a = " << fAttrActivationAlpha[direction * 3 + 2] <<
" * " << OpName
1314 <<
"_new_cell_state[i] + " << fAttrActivationBeta[direction * 3 + 2] <<
";\n";
1315 out <<
SP <<
SP <<
SP <<
"float b = (a > 0.) ? a : 0.;\n";
1317 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_new_cell_state[i] = (b < 1.) ? b : 1.;\n";
1318 out <<
SP <<
SP <<
"}\n";
1319 }
else if (fAttrActivations[direction * 3 + 2] ==
"LeakyRelu") {
1320 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1321 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_new_cell_state[i] < 0.)\n";
1322 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_new_cell_state[i] = " << fAttrActivationAlpha[direction * 3 + 2]
1323 <<
" * " << OpName <<
"_new_cell_state[i];\n";
1324 out <<
SP <<
SP <<
"}\n";
1325 }
else if (fAttrActivations[direction * 3 + 2] ==
"ThresholdRelu") {
1326 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1327 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_new_cell_state[i] < " << fAttrActivationAlpha[direction * 3 + 2]
1329 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_new_cell_state[i] = 0.;\n";
1330 out <<
SP <<
SP <<
"}";
1331 }
else if (fAttrActivations[direction * 3 + 2] ==
"Elu") {
1332 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1333 out <<
SP <<
SP <<
SP <<
"if (" << OpName <<
"_new_cell_state[i] < 0.)\n";
1334 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_new_cell_state[i] = " << fAttrActivationAlpha[direction * 3 + 2]
1335 <<
" * exp(" << OpName <<
"_new_cell_state[i] - 1.);\n";
1336 out <<
SP <<
SP <<
"}\n";
1337 }
else if (fAttrActivations[direction * 3 + 2] ==
"Softsign") {
1338 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1339 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_new_cell_state[i] = " << OpName <<
"_new_cell_state[i] / (1. + abs("
1340 << OpName <<
"_new_cell_state[i]));\n";
1341 out <<
SP <<
SP <<
"}\n";
1343 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1344 out <<
SP <<
SP <<
SP <<
SP << OpName <<
"_new_cell_state[i] = log(1. + exp(" << OpName
1345 <<
"_new_cell_state[i]));\n";
1346 out <<
SP <<
SP <<
"}\n";
1350 out <<
SP <<
SP <<
"for (size_t i = offset; i < offset + " <<
size <<
"; i++) {\n";
1351 out <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[i] = " << OpName <<
"_output_gate[i] * " << OpName
1352 <<
"_new_cell_state[i];\n";
1353 out <<
SP <<
SP <<
"}\n";
1358 if (!fNSequence_lens.empty()) {
1359 out <<
SP <<
"for (size_t seq = 0; seq < " << seq_length <<
"; seq++) {\n";
1360 out <<
SP <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
1361 out <<
SP <<
SP <<
SP <<
"if (seq >= tensor_" << fNSequence_lens <<
"[batch]) {\n";
1362 for (
size_t direction = 0; direction < num_directions; direction++) {
1363 out <<
SP <<
SP <<
SP <<
SP <<
SP <<
"for (size_t h = 0; h < " << fAttrHiddenSize <<
"; h++) {\n";
1364 out <<
SP <<
SP <<
SP <<
SP <<
SP <<
SP <<
"size_t idx = seq * "
1365 << num_directions * batch_size * fAttrHiddenSize + direction * batch_size * fAttrHiddenSize
1366 <<
" + batch * " << fAttrHiddenSize <<
" + h;\n";
1367 out <<
SP <<
SP <<
SP <<
SP <<
SP <<
SP << OpName <<
"_cell_state[idx] = 0.;\n";
1368 out <<
SP <<
SP <<
SP <<
SP <<
SP <<
SP << OpName <<
"_hidden_state[idx] = 0.;\n";
1371 out <<
SP <<
SP <<
SP <<
"}\n";
1372 out <<
SP <<
SP <<
"}\n";
1377 if (fAttrLayout == 0) {
1378 if (!fNY_h.empty()) {
1380 if (fNSequence_lens.empty()) {
1381 size_t y_h_size = batch_size * fAttrHiddenSize;
1382 if (fAttrDirection ==
"backward") {
1383 out <<
SP <<
"std::copy(" << OpName <<
"_hidden_state, " << OpName <<
"_hidden_state + " << y_h_size
1384 <<
", tensor_" << fNY_h <<
");\n";
1386 size_t offset = (seq_length - 1) * num_directions * batch_size * fAttrHiddenSize;
1387 out <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + " <<
offset <<
", " << OpName
1388 <<
"_hidden_state + " <<
offset <<
" + " << y_h_size <<
", tensor_" << fNY_h <<
");\n";
1390 if (num_directions == 2) {
1391 out <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + " << y_h_size <<
", " << OpName
1392 <<
"_hidden_state + " << 2 * y_h_size <<
", tensor_" << fNY_h <<
" + " << y_h_size <<
");\n";
1395 if (fAttrDirection ==
"backward") {
1396 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
1397 out <<
SP <<
SP <<
"size_t offset = batch * " << fAttrHiddenSize <<
";\n";
1398 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + offset, " << OpName
1399 <<
"_hidden_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_h <<
" + offset);\n";
1402 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
1403 out <<
SP <<
SP <<
"size_t seq = " <<
"tensor_" << fNSequence_lens <<
"[batch] - 1;\n";
1404 out <<
SP <<
SP <<
"size_t offset = seq * " << num_directions * batch_size * fAttrHiddenSize
1405 <<
" + batch * " << fAttrHiddenSize <<
";\n";
1406 out <<
SP <<
SP <<
"size_t y_h_offset = batch * " << fAttrHiddenSize <<
";\n";
1407 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + offset, " << OpName
1408 <<
"_hidden_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_h <<
" + y_h_offset);\n";
1411 if (num_directions == 2) {
1412 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
1413 out <<
SP <<
SP <<
"size_t offset = " << batch_size * fAttrHiddenSize <<
" + batch * " << fAttrHiddenSize
1415 out <<
SP <<
SP <<
"size_t y_h_offset = " << batch_size * fAttrHiddenSize <<
" + batch * "
1416 << fAttrHiddenSize <<
";\n";
1417 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + offset, " << OpName
1418 <<
"_hidden_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_h <<
" + y_h_offset);\n";
1423 if (!fNY_c.empty()) {
1425 if (fNSequence_lens.empty()) {
1426 size_t y_h_size = batch_size * fAttrHiddenSize;
1427 if (fAttrDirection ==
"backward") {
1428 out <<
SP <<
"std::copy(" << OpName <<
"_cell_state, " << OpName <<
"_hidden_state + " << y_h_size
1429 <<
", tensor_" << fNY_c <<
");\n";
1431 size_t offset = (seq_length - 1) * num_directions * batch_size * fAttrHiddenSize;
1432 out <<
SP <<
"std::copy(" << OpName <<
"_cell_state + " <<
offset <<
", " << OpName <<
"_cell_state + "
1433 <<
offset <<
" + " << y_h_size <<
", tensor_" << fNY_c <<
");\n";
1435 if (num_directions == 2) {
1436 out <<
SP <<
"std::copy(" << OpName <<
"_cell_state + " << y_h_size <<
", " << OpName <<
"_cell_state + "
1437 << 2 * y_h_size <<
", tensor_" << fNY_c <<
" + " << y_h_size <<
");\n";
1440 if (fAttrDirection ==
"backward") {
1441 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
1442 out <<
SP <<
SP <<
"size_t offset = batch * " << fAttrHiddenSize <<
";\n";
1443 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_cell_state + offset, " << OpName
1444 <<
"_cell_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_c <<
" + offset);\n";
1447 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
1448 out <<
SP <<
SP <<
"size_t seq = " <<
"tensor_" << fNSequence_lens <<
"[batch] - 1;\n";
1449 out <<
SP <<
SP <<
"size_t offset = seq * " << num_directions * batch_size * fAttrHiddenSize
1450 <<
" + batch * " << fAttrHiddenSize <<
";\n";
1451 out <<
SP <<
SP <<
"size_t y_h_offset = batch * " << fAttrHiddenSize <<
";\n";
1452 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_cell_state + offset, " << OpName
1453 <<
"_cell_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_c <<
" + y_h_offset);\n";
1456 if (num_directions == 2) {
1457 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
1458 out <<
SP <<
SP <<
"size_t offset = " << batch_size * fAttrHiddenSize <<
" + batch * " << fAttrHiddenSize
1460 out <<
SP <<
SP <<
"size_t y_h_offset = " << batch_size * fAttrHiddenSize <<
" + batch * "
1461 << fAttrHiddenSize <<
";\n";
1462 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_cell_state + offset, " << OpName
1463 <<
"_cell_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_c <<
" + y_h_offset);\n";
1471 for (
size_t direction = 0; direction < num_directions; direction++) {
1472 out <<
SP <<
"for (size_t seq = 0; seq < " << seq_length <<
"; seq++) {\n";
1473 out <<
SP <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
1474 out <<
SP <<
SP <<
SP <<
"size_t offset = seq * " << num_directions * batch_size * fAttrHiddenSize <<
" + "
1475 << direction * batch_size * fAttrHiddenSize <<
" + batch * " << fAttrHiddenSize <<
";\n";
1476 out <<
SP <<
SP <<
SP <<
"size_t y_offset = batch * " << seq_length * num_directions * fAttrHiddenSize
1477 <<
" + seq * " << num_directions * fAttrHiddenSize <<
" + " << direction * fAttrHiddenSize <<
";\n";
1478 out <<
SP <<
SP <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + offset, " << OpName
1479 <<
"_hidden_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY <<
" + y_offset);\n";
1480 out <<
SP <<
SP <<
"}\n";
1484 if (!fNY_h.empty()) {
1486 if (fAttrDirection ==
"backward") {
1487 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
1488 out <<
SP <<
SP <<
"size_t offset = batch * " << fAttrHiddenSize <<
";\n";
1489 out <<
SP <<
SP <<
"size_t y_h_offset = batch * " << num_directions * fAttrHiddenSize <<
";\n";
1490 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + offset, " << OpName
1491 <<
"_hidden_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_h <<
" + y_h_offset);\n";
1494 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
1495 if (fNSequence_lens.empty()) {
1496 out <<
SP <<
SP <<
"size_t seq = " << seq_length - 1 <<
";\n";
1498 out <<
SP <<
SP <<
"size_t seq = " <<
"tensor_" << fNSequence_lens <<
"[batch] - 1;\n";
1500 out <<
SP <<
SP <<
"size_t offset = seq * " << num_directions * batch_size * fAttrHiddenSize
1501 <<
" + batch * " << fAttrHiddenSize <<
";\n";
1502 out <<
SP <<
SP <<
"size_t y_h_offset = batch * " << num_directions * fAttrHiddenSize <<
";\n";
1503 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + offset, " << OpName
1504 <<
"_hidden_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_h <<
" + y_h_offset);\n";
1507 if (num_directions == 2) {
1508 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
1509 out <<
SP <<
SP <<
"size_t offset = " << batch_size * fAttrHiddenSize <<
" + batch * " << fAttrHiddenSize
1511 out <<
SP <<
SP <<
"size_t y_h_offset = batch * " << num_directions * fAttrHiddenSize <<
" + "
1512 << fAttrHiddenSize <<
";\n";
1513 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_hidden_state + offset, " << OpName
1514 <<
"_hidden_state + offset + " << fAttrHiddenSize <<
", tensor_" << fNY_h <<
" + y_h_offset);\n";
1519 if (!fNY_c.empty()) {
1521 if (fAttrDirection ==
"backward") {
1522 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
1523 out <<
SP <<
SP <<
"size_t offset = batch * " << fAttrHiddenSize <<
";\n";
1524 out <<
SP <<
SP <<
"size_t y_h_offset = batch * " << num_directions * fAttrHiddenSize <<
";\n";
1525 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_cell_state + offset, " << OpName <<
"_cell_state + offset + "
1526 << fAttrHiddenSize <<
", tensor_" << fNY_c <<
" + y_h_offset);\n";
1529 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
1530 if (fNSequence_lens.empty()) {
1531 out <<
SP <<
SP <<
"size_t seq = " << seq_length - 1 <<
";\n";
1533 out <<
SP <<
SP <<
"size_t seq = " <<
"tensor_" << fNSequence_lens <<
"[batch] - 1;\n";
1535 out <<
SP <<
SP <<
"size_t offset = seq * " << num_directions * batch_size * fAttrHiddenSize
1536 <<
" + batch * " << fAttrHiddenSize <<
";\n";
1537 out <<
SP <<
SP <<
"size_t y_h_offset = batch * " << num_directions * fAttrHiddenSize <<
";\n";
1538 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_cell_state + offset, " << OpName <<
"_cell_state + offset + "
1539 << fAttrHiddenSize <<
", tensor_" << fNY_c <<
" + y_h_offset);\n";
1542 if (num_directions == 2) {
1543 out <<
SP <<
"for (size_t batch = 0; batch < " << batch_size <<
"; batch++) {\n";
1544 out <<
SP <<
SP <<
"size_t offset = " << batch_size * fAttrHiddenSize <<
" + batch * " << fAttrHiddenSize
1546 out <<
SP <<
SP <<
"size_t y_h_offset = batch * " << num_directions * fAttrHiddenSize <<
" + "
1547 << fAttrHiddenSize <<
";\n";
1548 out <<
SP <<
SP <<
"std::copy(" << OpName <<
"_cell_state + offset, " << OpName <<
"_cell_state + offset + "
1549 << fAttrHiddenSize <<
", tensor_" << fNY_c <<
" + y_h_offset);\n";