| 196 | // REQUIRES: If you pass in variable->tensor(), *variable->mu() must be held. |
| 197 | template <typename Device, typename T> |
| 198 | Status PrepareToUpdateVariable(OpKernelContext* ctx, Tensor* tensor, |
| 199 | bool copy_on_read_mode) { |
| 200 | if (copy_on_read_mode || !tensor->RefCountIsOne()) { |
| 201 | // Tensor's buffer is in use by some read, so we need to copy before |
| 202 | // updating. |
| 203 | PersistentTensor unused; |
| 204 | Tensor* tmp; |
| 205 | if (std::is_same<T, Variant>::value) { |
| 206 | AllocatorAttributes attr; |
| 207 | attr.set_on_host(true); |
| 208 | TF_RETURN_IF_ERROR(ctx->allocate_persistent( |
| 209 | tensor->dtype(), tensor->shape(), &unused, &tmp, attr)); |
| 210 | |
| 211 | const auto elements_in = tensor->flat<Variant>(); |
| 212 | auto elements_out = tmp->flat<Variant>(); |
| 213 | for (int64 i = 0; i < elements_in.size(); ++i) { |
| 214 | elements_out(i) = elements_in(i); |
| 215 | } |
| 216 | } else { |
| 217 | AllocatorAttributes attr; |
| 218 | attr.set_gpu_compatible(true); |
| 219 | attr.set_nic_compatible(true); |
| 220 | TF_RETURN_IF_ERROR(ctx->allocate_persistent( |
| 221 | tensor->dtype(), tensor->shape(), &unused, &tmp, attr)); |
| 222 | functor::DenseUpdate<Device, T, ASSIGN> copy_functor; |
| 223 | copy_functor(ctx->eigen_device<Device>(), tmp->flat<T>(), |
| 224 | const_cast<const Tensor*>(tensor)->flat<T>()); |
| 225 | } |
| 226 | *tensor = *tmp; |
| 227 | } |
| 228 | return Status::OK(); |
| 229 | } |
| 230 | |
| 231 | // This gives you `*out`, a tensor you can update, corresponding to a variable |
| 232 | // passed as input index `input`. This handles the differences between |
nothing calls this directly
no test coverage detected