| 1023 | } |
| 1024 | |
| 1025 | void Compute(OpKernelContext* c) override { |
| 1026 | const Tensor& input = c->input(1); |
| 1027 | OP_REQUIRES(c, element_dtype_ == input.dtype(), |
| 1028 | errors::InvalidArgument("Invalid data types; list elements ", |
| 1029 | DataTypeString(element_dtype_), |
| 1030 | " but tried to append ", |
| 1031 | DataTypeString(input.dtype()))); |
| 1032 | OP_REQUIRES(c, TensorShapeUtils::IsVectorOrHigher(input.shape()), |
| 1033 | errors::InvalidArgument( |
| 1034 | "Expected tensor to be at least a vector, but saw shape: ", |
| 1035 | input.shape().DebugString())); |
| 1036 | |
| 1037 | const TensorShape& tls_shape = c->input(0).shape(); |
| 1038 | |
| 1039 | // For purposes of input forwarding, we want the least restrictive |
| 1040 | // AllocatorAttributes possible. If we need to allocate later, |
| 1041 | // we'll request the DT_VARIANT be allocated on host. |
| 1042 | AllocatorAttributes attr; |
| 1043 | |
| 1044 | std::unique_ptr<Tensor> tls_alias = c->forward_input( |
| 1045 | 0 /*input_index*/, 0 /*output_index*/, DT_VARIANT, tls_shape, |
| 1046 | DEVICE_MEMORY /* input is always on DEVICE_MEMORY */, attr); |
| 1047 | |
| 1048 | bool ok_to_alias = tls_alias != nullptr; |
| 1049 | if (tls_alias && tls_alias->dtype() == DT_VARIANT && |
| 1050 | tls_alias->NumElements() > 0) { |
| 1051 | auto alias_t = tls_alias->flat<Variant>(); |
| 1052 | for (int i = 0; i < tls_alias->NumElements(); ++i) { |
| 1053 | TensorList* tl_i = alias_t(i).get<TensorList>(); |
| 1054 | if (tl_i == nullptr || !tl_i->RefCountIsOne()) { |
| 1055 | ok_to_alias = false; |
| 1056 | break; |
| 1057 | } |
| 1058 | } |
| 1059 | } |
| 1060 | const Tensor& tls = ok_to_alias ? *tls_alias : c->input(0); |
| 1061 | |
| 1062 | OP_REQUIRES(c, tls.dtype() == DT_VARIANT, |
| 1063 | errors::InvalidArgument( |
| 1064 | "Expected input_handles dtype to be Variant, but saw: ", |
| 1065 | DataTypeString(tls.dtype()))); |
| 1066 | OP_REQUIRES(c, TensorShapeUtils::IsVector(tls_shape), |
| 1067 | errors::InvalidArgument( |
| 1068 | "Expected input_handles to be a vector, but saw shape: ", |
| 1069 | tls_shape.DebugString())); |
| 1070 | const int64 batch_size = tls.NumElements(); |
| 1071 | OP_REQUIRES(c, input.dim_size(0) == batch_size, |
| 1072 | errors::InvalidArgument( |
| 1073 | "Expected tensor.shape[0] == input_handles.size, but saw ", |
| 1074 | input.dim_size(0), " vs. ", batch_size)); |
| 1075 | auto tls_t = tls.vec<Variant>(); |
| 1076 | |
| 1077 | TensorShape input_element_shape = input.shape(); |
| 1078 | input_element_shape.RemoveDim(0); |
| 1079 | std::vector<const TensorList*> tl_batch; |
| 1080 | for (int64 b = 0; b < batch_size; ++b) { |
| 1081 | const TensorList* l = tls_t(b).get<TensorList>(); |
| 1082 | OP_REQUIRES(c, l != nullptr, |
nothing calls this directly
no test coverage detected