יצירת סוג חדש של הגשה

מסמך זה מסביר כיצד להרחיב את TensorFlow Serving עם סוג חדש של הגשה. סוג servable הבולט הוא SavedModelBundle , אבל זה יכול להיות שימושי כדי להגדיר סוגים אחרים של servables, לשרת נתונים שהולכים יחד עם המודל שלך. דוגמאות כוללות: טבלת חיפוש אוצר מילים, לוגיקה של שינוי תכונות. כל C ++ בכיתה יכול להיות servable, למשל int , std::map<string, int> או כל מעמד מוגדר הבינארי - נכנה אותו YourServable .

הגדרת Loader ו SourceAdapter עבור YourServable

כדי לאפשר TensorFlow הגשה לנהל ומגישים YourServable , אתה צריך להגדיר שני דברים:

  1. Loader בכיתה שנטען, מספק גישה, ופורק מופע של YourServable .

  2. SourceAdapter כי מעמיסי instantiates מכמה נתיבי מערכת קבצים למשל בפורמט נתונים בסיסי. כחלופה ל SourceAdapter , אתה יכול לכתוב שלם Source . עם זאת, מאז SourceAdapter הגישה נפוצה יותר ויותר מודולרי, אנו מתמקדים כאן.

Loader ההפשטה מוגדרת core/loader.h . זה דורש ממך להגדיר שיטות לטעינה, גישה ופריקה של סוג ההגשה שלך. הנתונים שמהם נטען ה-servable יכולים להגיע מכל מקום, אבל מקובל שהם מגיעים מנתיב מערכת אחסון. הבה נניח כי זהו המקרה עבור YourServable . תן לנו עוד להניח שכבר יש לך Source<StoragePath> כי אתה מרוצה (אם לא, לראות את המקור המותאם אישית מסמך).

בנוסף שלך Loader , תצטרך להגדיר SourceAdapter כי instantiates Loader מנתיב אחסון נתון. רוב-דוגמאות פשוטות ניתן לציין שני האובייקטים תמציתי עם SimpleLoaderSourceAdapter בכיתה (ב core/simple_loader.h ). שימוש-במקרים מתקדמים יכולים לבחור כדי לציין Loader ו SourceAdapter כיתות בנפרד באמצעות ממשקי API ברמה נמוכה יותר, למשל אם SourceAdapter צריך לשמור על כמה המדינה, ו / או אם הצרכים המדינה להיות משותף בין Loader מקרים.

ישנו יישום התייחסות של servable HashMap פשוטה המשתמשת SimpleLoaderSourceAdapter ב servables/hashmap/hashmap_source_adapter.cc . אתה עלול למצוא את זה נוח כדי ליצור עותק של HashmapSourceAdapter ואז לשנות אותו כדי שיתאים לצרכים שלך.

יישום HashmapSourceAdapter מורכב משני חלקים:

  1. ההיגיון לטעון HashMap מקובץ, ב LoadHashmapFromFile() .

  2. שימוש SimpleLoaderSourceAdapter להגדיר SourceAdapter פולט HashMap מעמיס מבוסס על LoadHashmapFromFile() . החדש SourceAdapter ניתן מופעים מהודעת פרוטוקול תצורת הסוג HashmapSourceAdapterConfig . נכון לעכשיו, הודעת התצורה מכילה רק את פורמט הקובץ, ולצורך יישום הפניה נתמך רק פורמט פשוט יחיד.

    הערת קריאת Detach() ב וההורס. קריאה זו נדרשת כדי להימנע ממרוצים בין מצב הרס לבין כל קריאות מתמשכות של הבורא למבדה בשרשורים אחרים. (למרות שלמתאם המקור הפשוט הזה אין שום מצב, מחלקת הבסיס בכל זאת אוכפת שה-Detach() נקרא.)

הסדרת YourServable מתנגד לטעון מנהל

הנה איך לחבר החדש שלך SourceAdapter עבור YourServable מעמיס למקור בסיסי של נתיבי אחסון, ואת המנהל (עם טיפול בשגיאות רע; קוד אמיתי צריך להיות יותר זהיר):

ראשית, צור מנהל:

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();

מתקדם: ארגון של מספר מופעים שניתנים להגשה לשיתוף מצב

מתאמי מקור יכולים להכיל מצב המשותף בין מספר שרתים שנפלטים. לדוגמה:

  • מאגר שרשורים משותף או משאב אחר שבו משתמשים רבים שניתן להגיש.

  • מבנה נתונים משותף לקריאה-בלבד שבו משתמשים רבים שניתן להגשה, כדי למנוע את הזמן והמקום של שכפול מבנה הנתונים בכל מופע שניתן להגשה.

מצב משותף שזמן האתחול שלו וגודלו זניחים (למשל בריכות שרשורים) יכול להיווצר בשקיקה על ידי ה-SourceAdapter, אשר לאחר מכן מטמיע אליו מצביע בכל מטעין הניתן להגשה שנפלט. יש לדחות את היצירה של מצב משותף יקר או גדול לקריאת Loader::Load() הרלוונטית הראשונה, כלומר מנוהלת על ידי המנהל. באופן סימטרי, הקריאה Loader::Unload() לשרת הסופי באמצעות המצב המשותף יקר/גדול אמורה להרוס אותו.