เอกสารนี้จะอธิบายวิธีขยายการให้บริการ TensorFlow ด้วยการให้บริการรูปแบบใหม่ ประเภทที่ให้บริการที่โดดเด่นที่สุดคือ SavedModelBundle
แต่จะมีประโยชน์ในการกำหนดการให้บริการประเภทอื่นๆ เพื่อแสดงข้อมูลที่สอดคล้องกับโมเดลของคุณ ตัวอย่างได้แก่ ตารางค้นหาคำศัพท์ ตรรกะการแปลงคุณลักษณะ คลาส C++ ใดๆ ก็สามารถให้บริการได้ เช่น int
, std::map<string, int>
หรือคลาสใดๆ ที่กำหนดไว้ในไบนารี่ของคุณ -- ให้เราเรียกมันว่า YourServable
การกำหนด Loader
และ SourceAdapter
สำหรับ YourServable
หากต้องการเปิดใช้งาน TensorFlow Serving เพื่อจัดการและให้บริการ YourServable
คุณต้องกำหนดสองสิ่ง:
คลาส
Loader
ที่โหลด ให้การเข้าถึง และยกเลิกการโหลดอินสแตนซ์ของYourServable
SourceAdapter
ที่สร้างอินสแตนซ์ของตัวโหลดจากรูปแบบข้อมูลพื้นฐานบางรูปแบบ เช่น เส้นทางของระบบไฟล์ อีกทางเลือกหนึ่งแทน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() ไปยังบริการสุดท้ายโดยใช้สถานะการแชร์ที่มีราคาแพง/ขนาดใหญ่ควรทำลายมันลง