| 247 | } |
| 248 | |
| 249 | Status XRTExecuteOp::DoWork(OpKernelContext* context) { |
| 250 | VLOG(1) << "XRTExecuteOp::Compute"; |
| 251 | ResourceMgr* rm; |
| 252 | TF_RETURN_IF_ERROR( |
| 253 | XRTGenericDeviceAccessor::GetResourceManager(context, &rm)); |
| 254 | |
| 255 | const Tensor& execution_input = context->input(0); |
| 256 | TF_RET_CHECK(TensorShapeUtils::IsScalar(execution_input.shape())); |
| 257 | int64 compilation_handle = execution_input.scalar<int64>()(); |
| 258 | |
| 259 | const Tensor& execution_config = context->input(1); |
| 260 | TF_RET_CHECK(TensorShapeUtils::IsScalar(execution_config.shape())); |
| 261 | xrt::XRTExecutionConfig config_proto; |
| 262 | TF_RET_CHECK( |
| 263 | config_proto.ParseFromString(execution_config.scalar<tstring>()())); |
| 264 | |
| 265 | int core_index_in_replica = config_proto.core_index_in_replica(); |
| 266 | TF_RET_CHECK(core_index_in_replica == 0); |
| 267 | bool release_inputs = config_proto.release_input_handles(); |
| 268 | bool release_compilation = config_proto.release_compilation_handle(); |
| 269 | |
| 270 | XRTCompilationCache* cache; |
| 271 | TF_RETURN_IF_ERROR(rm->Lookup<XRTCompilationCache>( |
| 272 | rm->default_container(), kXRTCompilationCacheResourceName, &cache)); |
| 273 | core::ScopedUnref cache_unref(cache); |
| 274 | |
| 275 | // We are guaranteed that the underlying device object won't be deleted out |
| 276 | // from under us, while the ScopedRef is live. |
| 277 | class XRTGenericDeviceAccessor::ScopedRef device_ref; |
| 278 | TF_RETURN_IF_ERROR( |
| 279 | XRTGenericDeviceAccessor::InitScopedRef(context, 0, &device_ref)); |
| 280 | |
| 281 | int rng_seed = config_proto.rng_seed(); |
| 282 | if (rng_seed == 0) { |
| 283 | rng_seed = GetXLARandomSeed(); |
| 284 | } |
| 285 | |
| 286 | se::Stream* stream = context->op_device_context() |
| 287 | ? context->op_device_context()->stream() |
| 288 | : nullptr; |
| 289 | RefPtr<XRTMemoryManager> memory_manager = XRTMemoryManager::Get(rm); |
| 290 | TF_ASSIGN_OR_RETURN(std::vector<InputCoords> input_coords, |
| 291 | GetComputationInputs(context, "input_handles")); |
| 292 | |
| 293 | std::unique_ptr<XRTCompilationCacheEntryRef> entry; |
| 294 | TF_RETURN_IF_ERROR(cache->Lookup(compilation_handle, &entry)); |
| 295 | xla::LocalExecutable* executable = entry->get().get_executable(); |
| 296 | if (release_compilation) { |
| 297 | // Process-wide cache of XLA executables. |
| 298 | TF_RETURN_IF_ERROR(cache->Release(compilation_handle)); |
| 299 | VLOG(2) << "Released compilation handle " << compilation_handle; |
| 300 | } |
| 301 | |
| 302 | TF_ASSIGN_OR_RETURN( |
| 303 | RefPtr<XRTTupleAllocation> output_tuple, |
| 304 | ExecuteComputation(context, memory_manager, &device_ref, executable, |
| 305 | input_coords, release_inputs, stream, rng_seed)); |
| 306 | |