| 2174 | } |
| 2175 | |
| 2176 | TF_Session* TF_LoadSessionFromSavedModel( |
| 2177 | const TF_SessionOptions* session_options, const TF_Buffer* run_options, |
| 2178 | const char* export_dir, const char* const* tags, int tags_len, |
| 2179 | TF_Graph* graph, TF_Buffer* meta_graph_def, TF_Status* status) { |
| 2180 | // TODO(sjr): Remove the IS_MOBILE_PLATFORM guard. This will require ensuring |
| 2181 | // that the tensorflow/cc/saved_model:loader build target is mobile friendly. |
| 2182 | #if defined(IS_MOBILE_PLATFORM) || defined(IS_SLIM_BUILD) |
| 2183 | status->status = tensorflow::errors::Unimplemented( |
| 2184 | "Loading a SavedModel is not supported on mobile. File a bug at " |
| 2185 | "https://github.com/tensorflow/tensorflow/issues if this feature is " |
| 2186 | "important to you"); |
| 2187 | return nullptr; |
| 2188 | #else |
| 2189 | mutex_lock l(graph->mu); |
| 2190 | if (!graph->name_map.empty()) { |
| 2191 | status->status = InvalidArgument("Graph is non-empty."); |
| 2192 | return nullptr; |
| 2193 | } |
| 2194 | |
| 2195 | RunOptions run_options_proto; |
| 2196 | if (run_options != nullptr && !run_options_proto.ParseFromArray( |
| 2197 | run_options->data, run_options->length)) { |
| 2198 | status->status = InvalidArgument("Unparseable RunOptions proto"); |
| 2199 | return nullptr; |
| 2200 | } |
| 2201 | |
| 2202 | std::unordered_set<string> tag_set; |
| 2203 | for (int i = 0; i < tags_len; i++) { |
| 2204 | tag_set.insert(string(tags[i])); |
| 2205 | } |
| 2206 | |
| 2207 | tensorflow::SavedModelBundle bundle; |
| 2208 | status->status = |
| 2209 | tensorflow::LoadSavedModel(session_options->options, run_options_proto, |
| 2210 | export_dir, tag_set, &bundle); |
| 2211 | if (TF_GetCode(status) != TF_OK) return nullptr; |
| 2212 | |
| 2213 | // Create a TF_Graph from the MetaGraphDef. This is safe as long as Session |
| 2214 | // extends using GraphDefs. The Graph instance is different, but equivalent |
| 2215 | // to the one used to create the session. |
| 2216 | // |
| 2217 | // TODO(jhseu): When Session is modified to take Graphs instead of |
| 2218 | // GraphDefs, return the Graph generated in LoadSavedModel(). |
| 2219 | TF_ImportGraphDefOptions* import_opts = TF_NewImportGraphDefOptions(); |
| 2220 | TF_ImportGraphDefResults results; |
| 2221 | GraphImportGraphDefLocked(graph, bundle.meta_graph_def.graph_def(), |
| 2222 | import_opts, &results, status); |
| 2223 | TF_DeleteImportGraphDefOptions(import_opts); |
| 2224 | if (TF_GetCode(status) != TF_OK) return nullptr; |
| 2225 | |
| 2226 | if (meta_graph_def != nullptr) { |
| 2227 | status->status = MessageToBuffer(bundle.meta_graph_def, meta_graph_def); |
| 2228 | if (TF_GetCode(status) != TF_OK) return nullptr; |
| 2229 | } |
| 2230 | |
| 2231 | TF_Session* session = new TF_Session(bundle.session.release(), graph); |
| 2232 | |
| 2233 | graph->sessions[session] = ""; |