एक नए प्रकार का सर्व करने योग्य बनाना

यह दस्तावेज़ बताता है कि एक नए प्रकार के सर्वेबल के साथ TensorFlow सर्विंग को कैसे बढ़ाया जाए। सबसे प्रमुख सर्व करने योग्य प्रकार SavedModelBundle है, लेकिन यह आपके मॉडल के साथ आने वाले डेटा की सेवा के लिए अन्य प्रकार के सर्वेबल्स को परिभाषित करने के लिए उपयोगी हो सकता है। उदाहरणों में शामिल हैं: एक शब्दावली लुकअप तालिका, सुविधा परिवर्तन तर्क। कोई भी C++ क्लास सर्व करने योग्य हो सकती है, उदाहरण के लिए int , std::map<string, int> या आपके बाइनरी में परिभाषित कोई भी क्लास - आइए हम इसे YourServable कहते हैं।

YourServable के लिए Loader और SourceAdapter को परिभाषित करना

YourServable प्रबंधित और परोसने के लिए TensorFlow सर्विंग को सक्षम करने के लिए, आपको दो चीजों को परिभाषित करने की आवश्यकता है:

  1. एक Loader वर्ग जो YourServable के एक उदाहरण को लोड करता है, उस तक पहुंच प्रदान करता है और अनलोड करता है।

  2. एक SourceAdapter जो कुछ अंतर्निहित डेटा प्रारूप जैसे फ़ाइल-सिस्टम पथ से लोडर को इंस्टेंटिएट करता है। SourceAdapter के विकल्प के रूप में, आप एक संपूर्ण Source लिख सकते हैं। हालाँकि, चूंकि SourceAdapter दृष्टिकोण अधिक सामान्य और अधिक मॉड्यूलर है, इसलिए हम यहां इस पर ध्यान केंद्रित करते हैं।

Loader एब्स्ट्रैक्शन को core/loader.h में परिभाषित किया गया है। इसके लिए आपको अपने प्रकार के सर्व करने योग्य को लोड करने, एक्सेस करने और अनलोड करने के तरीकों को परिभाषित करने की आवश्यकता है। जिस डेटा से सर्व करने योग्य लोड किया गया है वह कहीं से भी आ सकता है, लेकिन इसका स्टोरेज-सिस्टम पथ से आना आम बात है। आइए मान लें कि यह YourServable का मामला है। आइए आगे मान लें कि आपके पास पहले से ही एक Source<StoragePath> है जिससे आप खुश हैं (यदि नहीं, तो कस्टम सोर्स दस्तावेज़ देखें)।

आपके Loader के अलावा, आपको एक SourceAdapter परिभाषित करने की आवश्यकता होगी जो किसी दिए गए स्टोरेज पथ से Loader तुरंत चालू करता है। अधिकांश सरल उपयोग-मामले SimpleLoaderSourceAdapter वर्ग ( core/simple_loader.h में) के साथ दो वस्तुओं को संक्षिप्त रूप से निर्दिष्ट कर सकते हैं। उन्नत उपयोग-मामले निम्न-स्तरीय एपीआई का उपयोग करके Loader और SourceAdapter कक्षाओं को अलग-अलग निर्दिष्ट करने का विकल्प चुन सकते हैं, उदाहरण के लिए यदि SourceAdapter कुछ स्थिति बनाए रखने की आवश्यकता है, और/या यदि स्थिति को Loader उदाहरणों के बीच साझा करने की आवश्यकता है।

एक सरल हैशमैप सर्वेबल का एक संदर्भ कार्यान्वयन है जो servables/hashmap/hashmap_source_adapter.cc में SimpleLoaderSourceAdapter उपयोग करता है। आपको HashmapSourceAdapter की एक प्रति बनाना और फिर अपनी आवश्यकताओं के अनुरूप इसे संशोधित करना सुविधाजनक लग सकता है।

HashmapSourceAdapter के कार्यान्वयन के दो भाग हैं:

  1. LoadHashmapFromFile() में किसी फ़ाइल से हैशमैप लोड करने का तर्क।

  2. एक SourceAdapter को परिभाषित करने के लिए SimpleLoaderSourceAdapter का उपयोग जो LoadHashmapFromFile() के आधार पर हैशमैप लोडर उत्सर्जित करता है। नए SourceAdapter HashmapSourceAdapterConfig प्रकार के कॉन्फ़िगरेशन प्रोटोकॉल संदेश से इंस्टेंट किया जा सकता है। वर्तमान में, कॉन्फ़िगरेशन संदेश में केवल फ़ाइल प्रारूप शामिल है, और संदर्भ कार्यान्वयन के उद्देश्य के लिए केवल एक सरल प्रारूप समर्थित है।

    डिस्ट्रक्टर में Detach() पर कॉल नोट करें। राज्य को तोड़ने और अन्य थ्रेड्स में निर्माता लैम्ब्डा के किसी भी चल रहे आह्वान के बीच दौड़ से बचने के लिए यह कॉल आवश्यक है। (भले ही इस सरल स्रोत एडॉप्टर में कोई स्थिति नहीं है, फिर भी बेस क्लास यह लागू करता है कि Detach() को कॉल किया जाता है।)

YourServable ऑब्जेक्ट को प्रबंधक में लोड करने की व्यवस्था करना

यहां बताया गया है कि YourServable लोडर के लिए अपने नए SourceAdapter स्टोरेज पथों के मूल स्रोत और एक प्रबंधक से कैसे जोड़ा जाए (खराब त्रुटि प्रबंधन के साथ; वास्तविक कोड अधिक सावधान रहना चाहिए):

सबसे पहले, एक प्रबंधक बनाएँ:

std::unique_ptr<AspiredVersionsManager> manager = ...;

फिर, एक YourServable स्रोत एडाप्टर बनाएं और इसे प्रबंधक में प्लग करें:

auto your_adapter = new YourServableSourceAdapter(...);
ConnectSourceToTarget(your_adapter, manager.get());

अंत में, एक सरल पथ स्रोत बनाएं और इसे अपने एडाप्टर में प्लग करें:

std::unique_ptr<FileSystemStoragePathSource> path_source;
// Here are some FileSystemStoragePathSource config settings that ought to get
// it working, but for details please see its documentation.
FileSystemStoragePathSourceConfig config;
// We just have a single servable stream. Call it "default".
config.set_servable_name("default");
config.set_base_path(FLAGS::base_path /* base path for our servable files */);
config.set_file_system_poll_wait_seconds(1);
TF_CHECK_OK(FileSystemStoragePathSource::Create(config, &path_source));
ConnectSourceToTarget(path_source.get(), your_adapter.get());

लोड की गई YourServable ऑब्जेक्ट तक पहुंच

यहां बताया गया है कि लोड किए गए YourServable का हैंडल कैसे प्राप्त करें और उसका उपयोग कैसे करें:

auto handle_request = serving::ServableRequest::Latest("default");
ServableHandle<YourServable*> servable;
Status status = manager->GetServableHandle(handle_request, &servable);
if (!status.ok()) {
  LOG(INFO) << "Zero versions of 'default' servable have been loaded so far";
  return;
}
// Use the servable.
(*servable)->SomeYourServableMethod();

उन्नत: स्थिति साझा करने के लिए एकाधिक सर्व करने योग्य उदाहरणों की व्यवस्था करना

सोर्स एडेप्टर उस स्थिति को रख सकते हैं जिसे कई उत्सर्जित सर्वेबल्स के बीच साझा किया जाता है। उदाहरण के लिए:

  • एक साझा थ्रेड पूल या अन्य संसाधन जिसका उपयोग एकाधिक सर्वेबल्स करते हैं।

  • एक साझा रीड-ओनली डेटा संरचना जिसका उपयोग कई सर्व करने योग्य उदाहरण में डेटा संरचना की नकल करने के समय और स्थान के ओवरहेड से बचने के लिए करते हैं।

साझा स्थिति जिसका आरंभीकरण समय और आकार नगण्य है (उदाहरण के लिए थ्रेड पूल) को सोर्स एडाप्टर द्वारा उत्सुकता से बनाया जा सकता है, जो फिर प्रत्येक उत्सर्जित सर्व करने योग्य लोडर में एक पॉइंटर को एम्बेड करता है। महंगे या बड़े साझा राज्य का निर्माण पहले लागू लोडर::लोड() कॉल के लिए स्थगित किया जाना चाहिए, यानी प्रबंधक द्वारा शासित। सममित रूप से, महंगी/बड़ी साझा स्थिति का उपयोग करके अंतिम सर्व करने योग्य लोडर::अनलोड() कॉल को इसे तोड़ देना चाहिए।