| 673 | } |
| 674 | |
| 675 | Status FunctionLibraryRuntimeImpl::InstantiateSymbolicGradient( |
| 676 | const NameAttrList& func, const FunctionLibraryDefinition* lib_def, |
| 677 | std::unique_ptr<FunctionBody>* g_body) { |
| 678 | const FunctionDef* fdef = lib_def->Find(func.name()); |
| 679 | if (fdef == nullptr) { |
| 680 | // f is a primitive op. |
| 681 | gradient::Creator creator; |
| 682 | TF_RETURN_IF_ERROR(gradient::GetOpGradientCreator(func.name(), &creator)); |
| 683 | if (creator == nullptr) { |
| 684 | return errors::InvalidArgument("No gradient is defined for ", |
| 685 | func.name()); |
| 686 | } |
| 687 | FunctionDef grad_fdef; |
| 688 | // TODO(josh11b): Should filter out the attrs from func that aren't used |
| 689 | // by the gradient function. |
| 690 | TF_RETURN_IF_ERROR(creator(AttrSlice(&func.attr()), &grad_fdef)); |
| 691 | TF_RETURN_IF_ERROR( |
| 692 | FunctionDefToBody(grad_fdef, AttrSlice(&func.attr()), lib_def, g_body)); |
| 693 | } else { |
| 694 | // f is a user-defined function. |
| 695 | InstantiateOptions options; |
| 696 | if (lib_def != base_lib_def_) { |
| 697 | options.lib_def = lib_def; |
| 698 | } |
| 699 | Handle f_handle; |
| 700 | TF_RETURN_IF_ERROR( |
| 701 | Instantiate(func.name(), AttrSlice(&func.attr()), options, &f_handle)); |
| 702 | const FunctionBody* f_body = GetFunctionBody(f_handle); |
| 703 | CHECK_NOTNULL(f_body); |
| 704 | *g_body = SymbolicGradient(*f_body); |
| 705 | } |
| 706 | return Status::OK(); |
| 707 | } |
| 708 | |
| 709 | bool FunctionLibraryRuntimeImpl::IsLocalTarget( |
| 710 | const InstantiateOptions& options) const { |
nothing calls this directly
no test coverage detected