| 840 | } |
| 841 | |
| 842 | void Compute(OpKernelContext* ctx) override { |
| 843 | const Tensor* seq_len_max_tensor = nullptr; |
| 844 | OP_REQUIRES_OK(ctx, ctx->input("seq_len_max", &seq_len_max_tensor)); |
| 845 | |
| 846 | const Tensor* x; |
| 847 | OP_REQUIRES_OK(ctx, ctx->input("x", &x)); |
| 848 | OP_REQUIRES(ctx, x->dims() == 3, errors::InvalidArgument("x must be 3D")); |
| 849 | const int64 timelen = x->dim_size(0); |
| 850 | const int64 batch_size = x->dim_size(1); |
| 851 | const int64 input_size = x->dim_size(2); |
| 852 | |
| 853 | const Tensor* cs_prev_tensor = nullptr; |
| 854 | OP_REQUIRES_OK(ctx, ctx->input("cs_prev", &cs_prev_tensor)); |
| 855 | OP_REQUIRES(ctx, cs_prev_tensor->dims() == 2, |
| 856 | errors::InvalidArgument("cs_prev must be 2D")); |
| 857 | OP_REQUIRES(ctx, cs_prev_tensor->dim_size(0) == batch_size, |
| 858 | errors::InvalidArgument("cs_prev.dims(0) != batch_size: ", |
| 859 | cs_prev_tensor->dim_size(0), " vs. ", |
| 860 | batch_size)); |
| 861 | const int64 cell_size = cs_prev_tensor->dim_size(1); |
| 862 | |
| 863 | if (batch_size * input_size % 2 == 1) { |
| 864 | LOG(WARNING) << "BlockLSTMOp is inefficient when both batch_size and " |
| 865 | << "input_size are odd. You are using: batch_size=" |
| 866 | << batch_size << ", input_size=" << input_size; |
| 867 | } |
| 868 | if (batch_size * cell_size % 2 == 1) { |
| 869 | LOG(WARNING) << "BlockLSTMOp is inefficient when both batch_size and " |
| 870 | << "cell_size are odd. You are using: batch_size=" |
| 871 | << batch_size << ", cell_size=" << cell_size; |
| 872 | } |
| 873 | |
| 874 | const Tensor* h_prev_tensor = nullptr; |
| 875 | OP_REQUIRES_OK(ctx, ctx->input("h_prev", &h_prev_tensor)); |
| 876 | OP_REQUIRES(ctx, h_prev_tensor->dims() == 2, |
| 877 | errors::InvalidArgument("h_prev must be 2D")); |
| 878 | OP_REQUIRES(ctx, h_prev_tensor->dim_size(0) == batch_size, |
| 879 | errors::InvalidArgument("h_prev.dims(0) != batch_size: ", |
| 880 | h_prev_tensor->dim_size(0), " vs. ", |
| 881 | batch_size)); |
| 882 | OP_REQUIRES(ctx, h_prev_tensor->dim_size(1) == cell_size, |
| 883 | errors::InvalidArgument( |
| 884 | "h_prev.dims(1) != cell_size: ", h_prev_tensor->dim_size(1), |
| 885 | " vs. ", cell_size)); |
| 886 | |
| 887 | const Tensor* w_tensor = nullptr; |
| 888 | OP_REQUIRES_OK(ctx, ctx->input("w", &w_tensor)); |
| 889 | OP_REQUIRES(ctx, w_tensor->dims() == 2, |
| 890 | errors::InvalidArgument("w must be 2D")); |
| 891 | OP_REQUIRES(ctx, w_tensor->dim_size(0) == input_size + cell_size, |
| 892 | errors::InvalidArgument( |
| 893 | "w.dim_size(0) != input_size + cell_size: ", |
| 894 | w_tensor->dim_size(0), " vs. ", input_size + cell_size)); |
| 895 | OP_REQUIRES(ctx, w_tensor->dim_size(1) == cell_size * 4, |
| 896 | errors::InvalidArgument( |
| 897 | "w.dim_size(1) != cell_size * 4: ", w_tensor->dim_size(1), |
| 898 | " vs. ", cell_size * 4)); |
| 899 |
nothing calls this directly
no test coverage detected