| 2066 | } |
| 2067 | |
| 2068 | void TF_AddGradientsWithPrefix(TF_Graph* g, const char* prefix, TF_Output* y, |
| 2069 | int ny, TF_Output* x, int nx, TF_Output* dx, |
| 2070 | TF_Status* status, TF_Output* dy) { |
| 2071 | #if defined(IS_MOBILE_PLATFORM) || defined(IS_SLIM_BUILD) |
| 2072 | status->status = tensorflow::errors::Unimplemented( |
| 2073 | "Adding gradients is not supported on mobile. File a bug at " |
| 2074 | "https://github.com/tensorflow/tensorflow/issues if this feature is " |
| 2075 | "important to you"); |
| 2076 | #else |
| 2077 | std::vector<tensorflow::Output> y_arg = OutputsFromTFOutputs(y, ny); |
| 2078 | std::vector<tensorflow::Output> x_arg = OutputsFromTFOutputs(x, nx); |
| 2079 | std::vector<tensorflow::Output> dy_arg; |
| 2080 | |
| 2081 | { |
| 2082 | // We need to hold on to the lock while we have a scope that uses TF_Graph. |
| 2083 | mutex_lock graph_lock(g->mu); |
| 2084 | |
| 2085 | const int first_new_node_id = g->graph.num_node_ids(); |
| 2086 | |
| 2087 | string prefix_cmp; |
| 2088 | const char* child_scope_name; |
| 2089 | if (prefix == nullptr) { |
| 2090 | child_scope_name = "gradients"; |
| 2091 | } else { |
| 2092 | prefix_cmp = string(prefix) + "/"; |
| 2093 | // The operation should fail if the provided name prefix has already been |
| 2094 | // used in this graph |
| 2095 | for (const auto& pair : g->name_map) { |
| 2096 | const string& name = pair.first; |
| 2097 | if ((name == prefix) || absl::StartsWith(name, prefix_cmp)) { |
| 2098 | status->status = InvalidArgument( |
| 2099 | "prefix [", prefix, |
| 2100 | "] conflicts with existing node in the graph named [", name, "]"); |
| 2101 | return; |
| 2102 | } |
| 2103 | } |
| 2104 | child_scope_name = prefix; |
| 2105 | } |
| 2106 | tensorflow::Scope scope = |
| 2107 | NewInternalScope(&g->graph, &status->status, &g->refiner) |
| 2108 | .NewSubScope(child_scope_name); |
| 2109 | |
| 2110 | if (dx != nullptr) { |
| 2111 | std::vector<tensorflow::Output> dx_arg = OutputsFromTFOutputs(dx, ny); |
| 2112 | status->status = |
| 2113 | AddSymbolicGradients(scope, y_arg, x_arg, dx_arg, &dy_arg); |
| 2114 | } else { |
| 2115 | status->status = AddSymbolicGradients(scope, y_arg, x_arg, &dy_arg); |
| 2116 | } |
| 2117 | |
| 2118 | // Update g->name_map with the name_map from the scope, which will contain |
| 2119 | // the new gradient ops. |
| 2120 | for (int i = first_new_node_id; i < g->graph.num_node_ids(); ++i) { |
| 2121 | Node* n = g->graph.FindNodeId(i); |
| 2122 | if (n == nullptr) continue; |
| 2123 | |
| 2124 | // Adding the gradients to the graph can alter the prefix to prevent |
| 2125 | // name collisions only if this prefix has not been provided explicitly |