Tạo một loại dịch vụ mới

Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.

Tài liệu này giải thích cách mở rộng Cung cấp TensorFlow với một loại dịch vụ mới. Phần lớn loại thể phân phát nổi bật là SavedModelBundle , nhưng nó có thể hữu ích để xác định các loại servables, để phục vụ dữ liệu mà đi cùng với mô hình của bạn. Ví dụ bao gồm: bảng tra cứu từ vựng, logic chuyển đổi tính năng. Bất kỳ lớp C ++ có thể là một thể phân phát, ví dụ như int , std::map<string, int> hoặc bất kỳ lớp được định nghĩa trong nhị phân của bạn - chúng ta hãy gọi nó là YourServable .

Xác định một LoaderSourceAdapter cho YourServable

Để kích hoạt TensorFlow Phục vụ để quản lý và phục vụ YourServable , bạn cần xác định hai điều:

  1. Một Loader lớp sẽ tải, cho phép truy cập, và trút được một thể hiện của YourServable .

  2. Một SourceAdapter mà instantiates bộ tải từ đường dẫn tập tin hệ thống một số định dạng dữ liệu cơ bản ví dụ. Để thay thế cho một SourceAdapter , bạn có thể viết một hoàn Source . Tuy nhiên, kể từ khi SourceAdapter cách tiếp cận phổ biến hơn và mô-đun hơn, chúng tôi tập trung vào nó ở đây.

Các Loader trừu tượng được định nghĩa trong core/loader.h . Nó yêu cầu bạn xác định các phương thức để tải, truy cập và dỡ bỏ loại dịch vụ của bạn. Dữ liệu mà từ đó dịch vụ được tải có thể đến từ bất kỳ đâu, nhưng nó thường đến từ một đường dẫn hệ thống lưu trữ. Chúng ta hãy giả định đó là trường hợp cho YourServable . Hãy để chúng tôi tiếp tục giả sử bạn đã có một Source<StoragePath> mà bạn đang hài lòng với (nếu không muốn nói, xem Tuỳ Nguồn tài liệu).

Ngoài bạn Loader , bạn sẽ cần phải xác định một SourceAdapter mà instantiates một Loader từ một đường dẫn lưu trữ nhất định. Hầu hết đơn giản trường hợp sử dụng có thể xác định hai đối tượng chính xác với SimpleLoaderSourceAdapter lớp (trong core/simple_loader.h ). Nâng cao trường hợp sử dụng có thể lựa chọn để xác định LoaderSourceAdapter lớp riêng biệt sử dụng các API cấp thấp hơn, ví dụ như nếu SourceAdapter cần phải giữ lại một số tiểu bang, và / hoặc nếu nhu cầu nhà nước để được chia sẻ giữa Loader trường.

Có một thực hiện tham chiếu của một thể phân phát hashmap đơn giản mà sử dụng SimpleLoaderSourceAdapter trong servables/hashmap/hashmap_source_adapter.cc . Bạn có thể tìm thấy nó thuận tiện để tạo một bản sao của HashmapSourceAdapter và sau đó sửa đổi nó cho phù hợp với nhu cầu của bạn.

Việc thực hiện HashmapSourceAdapter có hai phần:

  1. Logic để tải một hashmap từ một tập tin, trong LoadHashmapFromFile() .

  2. Việc sử dụng SimpleLoaderSourceAdapter để xác định một SourceAdapter mà phát ra HashMap bộ tải dựa trên LoadHashmapFromFile() . Mới SourceAdapter có thể được khởi tạo từ một thông điệp giao thức cấu hình của loại HashmapSourceAdapterConfig . Hiện tại, thông báo cấu hình chỉ chứa định dạng tệp và cho mục đích triển khai tham chiếu chỉ hỗ trợ một định dạng đơn giản duy nhất.

    Lưu ý các cuộc gọi đến Detach() trong destructor. Lệnh gọi này là bắt buộc để tránh các cuộc chạy đua giữa trạng thái xé nhỏ và bất kỳ lệnh gọi nào đang diễn ra của lambda Creator trong các chuỗi khác. (Mặc dù bộ điều hợp nguồn đơn giản này không có bất kỳ trạng thái nào, nhưng lớp cơ sở vẫn thực thi mà Detach () được gọi.)

Bố trí cho YourServable các đối tượng được nạp trong một nhà quản lý

Dưới đây là làm thế nào để treo mới của bạn SourceAdapter cho YourServable bộ tải một nguồn tin cơ bản của đường dẫn lưu trữ, và một người quản lý (với xử lý lỗi xấu; mã thực nên cẩn thận hơn):

Đầu tiên, hãy tạo một người quản lý:

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

Sau đó, tạo một YourServable bộ chuyển đổi nguồn và cắm nó vào người quản lý:

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

Cuối cùng, tạo một nguồn đường dẫn đơn giản và cắm nó vào bộ điều hợp của bạn:

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

Truy cập nạp YourServable đối tượng

Dưới đây là làm thế nào để có được một xử lý cho một nạp YourServable , và sử dụng nó:

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

Nâng cao: Sắp xếp cho nhiều phiên bản dịch vụ để chia sẻ trạng thái

SourceAdapters có thể chứa trạng thái được chia sẻ giữa nhiều dịch vụ được phát ra. Ví dụ:

  • Nhóm luồng được chia sẻ hoặc tài nguyên khác mà nhiều dịch vụ sử dụng.

  • Một cấu trúc dữ liệu chỉ đọc được chia sẻ mà nhiều dịch vụ sử dụng, để tránh tốn thời gian và không gian khi sao chép cấu trúc dữ liệu trong mỗi phiên bản dịch vụ.

Trạng thái chia sẻ có thời gian và kích thước khởi tạo không đáng kể (ví dụ: nhóm luồng) có thể được tạo sẵn bởi SourceAdapter, sau đó nhúng một con trỏ tới nó trong mỗi bộ tải dịch vụ được phát ra. Việc tạo trạng thái chia sẻ lớn hoặc đắt tiền nên được hoãn lại cho lệnh gọi Loader :: Load () áp dụng đầu tiên, tức là do trình quản lý điều chỉnh. Đối xứng, lệnh gọi Loader :: Unload () đến dịch vụ cuối cùng sử dụng trạng thái chia sẻ lớn / đắt tiền sẽ loại bỏ nó.