เอกสารนี้จะอธิบายวิธีขยายการให้บริการ TensorFlow ด้วยการให้บริการรูปแบบใหม่ ประเภทที่ให้บริการที่โดดเด่นที่สุดคือ SavedModelBundle แต่จะมีประโยชน์ในการกำหนดการให้บริการประเภทอื่นๆ เพื่อแสดงข้อมูลที่สอดคล้องกับโมเดลของคุณ ตัวอย่างได้แก่ ตารางค้นหาคำศัพท์ ตรรกะการแปลงคุณลักษณะ คลาส C++ ใดๆ ก็สามารถให้บริการได้ เช่น int , std::map<string, int> หรือคลาสใดๆ ที่กำหนดไว้ในไบนารี่ของคุณ -- ให้เราเรียกมันว่า YourServable
การกำหนด Loader และ SourceAdapter สำหรับ YourServable
หากต้องการเปิดใช้งาน TensorFlow Serving เพื่อจัดการและให้บริการ YourServable คุณต้องกำหนดสองสิ่ง:
คลาส
Loaderที่โหลด ให้การเข้าถึง และยกเลิกการโหลดอินสแตนซ์ของYourServableSourceAdapterที่สร้างอินสแตนซ์ของตัวโหลดจากรูปแบบข้อมูลพื้นฐานบางรูปแบบ เช่น เส้นทางของระบบไฟล์ อีกทางเลือกหนึ่งแทนSourceAdapterคุณสามารถเขียนSourceแบบเต็มได้ อย่างไรก็ตาม เนื่องจากแนวทางSourceAdapterเป็นแบบทั่วไปและแบบโมดูลาร์มากกว่า เราจึงเน้นที่แนวทางนี้ที่นี่
นามธรรม Loader ถูกกำหนดไว้ใน core/loader.h โดยคุณจะต้องกำหนดวิธีการในการโหลด เข้าถึง และยกเลิกการโหลดประเภทบริการของคุณ ข้อมูลที่ใช้ในการโหลดบริการสามารถมาจากที่ใดก็ได้ แต่เป็นเรื่องปกติที่จะมาจากเส้นทางของระบบจัดเก็บข้อมูล ให้เราสมมติว่าเป็นกรณีของ YourServable ให้เราสมมติว่าคุณมี Source<StoragePath> ที่คุณพอใจอยู่แล้ว (หากไม่ โปรดดูเอกสาร แหล่งที่มาที่กำหนดเอง )
นอกจาก Loader ของคุณแล้ว คุณจะต้องกำหนด SourceAdapter ที่สร้างอินสแตนซ์ของ Loader จากพาธพื้นที่จัดเก็บข้อมูลที่กำหนด กรณีการใช้งานที่เรียบง่ายส่วนใหญ่สามารถระบุวัตถุทั้งสองได้อย่างกระชับด้วยคลาส SimpleLoaderSourceAdapter (ใน core/simple_loader.h ) กรณีการใช้งานขั้นสูงอาจเลือกที่จะระบุคลาส Loader และ SourceAdapter แยกกันโดยใช้ API ระดับล่าง เช่น หาก SourceAdapter จำเป็นต้องคงสถานะบางอย่างไว้ และ/หรือหากจำเป็นต้องแชร์สถานะระหว่างอินสแตนซ์ Loader
มีการใช้งานอ้างอิงของ hashmap servable แบบง่ายที่ใช้ SimpleLoaderSourceAdapter ใน servables/hashmap/hashmap_source_adapter.cc คุณอาจพบว่าสะดวกที่จะทำสำเนา HashmapSourceAdapter แล้วแก้ไขให้เหมาะกับความต้องการของคุณ
การใช้งาน HashmapSourceAdapter มีสองส่วน:
ตรรกะในการโหลดแฮชแมปจากไฟล์ใน
LoadHashmapFromFile()การใช้
SimpleLoaderSourceAdapterเพื่อกำหนดSourceAdapterที่ปล่อยตัวโหลด hashmap ตามLoadHashmapFromFile()SourceAdapterใหม่สามารถสร้างอินสแตนซ์ได้จากข้อความโปรโตคอลการกำหนดค่าประเภทHashmapSourceAdapterConfigในปัจจุบัน ข้อความการกำหนดค่ามีเพียงรูปแบบไฟล์ และเพื่อวัตถุประสงค์ในการใช้งานอ้างอิง รองรับเพียงรูปแบบง่ายๆ เพียงรูปแบบเดียวสังเกตการเรียก
Detach()ใน destructor การเรียกนี้จำเป็นเพื่อหลีกเลี่ยงการแข่งขันระหว่างการแยกสถานะและการเรียกใช้แลมบ์ดาของ Creator ในเธรดอื่น ๆ (แม้ว่าอะแดปเตอร์ต้นทางแบบธรรมดานี้ไม่มีสถานะใด ๆ แต่คลาสพื้นฐานยังคงบังคับใช้ 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();
ขั้นสูง: การจัดเรียงอินสแตนซ์ที่ให้บริการหลายรายการเพื่อแชร์สถานะ
SourceAdapters สามารถกำหนดสถานะที่แชร์ระหว่างบริการที่ปล่อยออกมาหลายรายการ ตัวอย่างเช่น:
เธรดพูลที่ใช้ร่วมกันหรือทรัพยากรอื่น ๆ ที่ใช้งานหลายรายการได้
โครงสร้างข้อมูลแบบอ่านอย่างเดียวที่ใช้ร่วมกันซึ่งหลายบริการใช้ เพื่อหลีกเลี่ยงเวลาและพื้นที่โอเวอร์เฮดในการจำลองโครงสร้างข้อมูลในแต่ละอินสแตนซ์ที่ให้บริการ
สถานะที่ใช้ร่วมกันซึ่งเวลาและขนาดการเริ่มต้นไม่สำคัญ (เช่น เธรดพูล) สามารถสร้างได้อย่างกระตือรือร้นโดย SourceAdapter ซึ่งจะฝังตัวชี้ไว้ในโหลดเดอร์ที่ให้บริการแต่ละตัวที่ปล่อยออกมา การสร้างสถานะที่ใช้ร่วมกันที่มีราคาแพงหรือขนาดใหญ่ควรถูกเลื่อนออกไปเป็นการเรียก Loader::Load() ที่เกี่ยวข้องครั้งแรก เช่น ควบคุมโดยผู้จัดการ ในเชิงสมมาตร การเรียก Loader::Unload() ไปยังบริการสุดท้ายโดยใช้สถานะการแชร์ที่มีราคาแพง/ขนาดใหญ่ควรทำลายมันลง