| 81 | } |
| 82 | |
| 83 | void exec( |
| 84 | _megdnn_tensor_in input, _megdnn_tensor_in weight_ih, _megdnn_tensor_in bias_ih, |
| 85 | _megdnn_tensor_in hx, _megdnn_tensor_in weight_hh, _megdnn_tensor_in bias_hh, |
| 86 | _megdnn_tensor_out dst, _megdnn_workspace workspace, |
| 87 | param::RNNCell::NonlineMode nonline_mode, Handle* handle) { |
| 88 | TensorND tmp{static_cast<void*>(workspace.raw_ptr), dst.layout}; |
| 89 | _megdnn_workspace new_workspace = { |
| 90 | workspace.raw_ptr + dst.layout.span().dist_byte(), |
| 91 | workspace.size - dst.layout.span().dist_byte()}; |
| 92 | auto opr = handle->create_operator<MatrixMulForward>(); |
| 93 | opr->param().transposeB = true; |
| 94 | opr->exec(input, weight_ih, tmp, new_workspace); |
| 95 | opr->exec(hx, weight_hh, dst, new_workspace); |
| 96 | auto add_opr = handle->create_operator<ElemwiseForward>(); |
| 97 | add_opr->param().mode = Elemwise::Param::Mode::ADD; |
| 98 | add_opr->exec({dst, tmp}, dst); |
| 99 | add_opr->exec({dst, bias_ih}, dst); |
| 100 | add_opr->exec({dst, bias_hh}, dst); |
| 101 | |
| 102 | // activation |
| 103 | using NonlineMode = param::RNNCell::NonlineMode; |
| 104 | |
| 105 | switch (nonline_mode) { |
| 106 | #define cb(_mode) \ |
| 107 | case NonlineMode::_mode: { \ |
| 108 | auto nonlinear = handle->create_operator<ElemwiseForward>(); \ |
| 109 | nonlinear->param().mode = Elemwise::Param::Mode::_mode; \ |
| 110 | nonlinear->exec({dst}, dst); \ |
| 111 | break; \ |
| 112 | } |
| 113 | cb(RELU); |
| 114 | cb(TANH); |
| 115 | #undef cb |
| 116 | case NonlineMode::IDENTITY: |
| 117 | break; |
| 118 | default: |
| 119 | megdnn_assert(false); |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | } // namespace rnn_cell |
| 124 | } // namespace megdnn |