Tài liệu này giải thích cách mở rộng Dịch vụ TensorFlow để giám sát các hệ thống lưu trữ khác nhau nhằm khám phá các mô hình hoặc dữ liệu (phiên bản) mới để phân phát. Cụ thể, nó bao gồm cách tạo và sử dụng mô-đun giám sát đường dẫn hệ thống lưu trữ để biết sự xuất hiện của các đường dẫn phụ mới, trong đó mỗi đường dẫn phụ đại diện cho một phiên bản có thể phân phát mới để tải. Loại mô-đun đó được gọi là Source<StoragePath>
, vì nó phát ra các đối tượng thuộc loại StoragePath
(được đánh máy thành string
). Nó có thể được cấu tạo bằng SourceAdapter
để tạo một Loader
có thể phục vụ được từ một đường dẫn nhất định mà nguồn phát hiện ra.
Đầu tiên, lưu ý về tính tổng quát
Không cần sử dụng đường dẫn làm tay cầm cho dữ liệu có thể phân phát; nó chỉ minh họa một cách để đưa các thành phần có thể phân phát vào hệ thống. Ngay cả khi môi trường của bạn không đóng gói dữ liệu có thể phục vụ trong các đường dẫn, tài liệu này sẽ giúp bạn làm quen với các khái niệm trừu tượng chính. Bạn có tùy chọn tạo mô-đun Source<T>
và SourceAdapter<T1, T2>
cho các loại phù hợp với môi trường của bạn (ví dụ: RPC hoặc thông báo pub/sub, bản ghi cơ sở dữ liệu) hoặc chỉ đơn giản là tạo một Source<std::unique_ptr<Loader>>
nguyên khối Source<std::unique_ptr<Loader>>
phát trực tiếp các bộ tải có thể phục vụ được.
Tất nhiên, bất kể loại dữ liệu nào mà nguồn của bạn phát ra (cho dù đó là đường dẫn POSIX, đường dẫn Google Cloud Storage hay bộ xử lý RPC), đều cần có (các) mô-đun đi kèm có thể tải các dịch vụ dựa trên đó. Các mô-đun như vậy được gọi là SourceAdapters
. Việc tạo một tùy chỉnh được mô tả trong tài liệu Có thể phân phát tùy chỉnh . Dịch vụ TensorFlow đi kèm với một công cụ để khởi tạo các phiên TensorFlow dựa trên đường dẫn trong hệ thống tệp mà TensorFlow hỗ trợ. Người ta có thể thêm hỗ trợ cho các hệ thống tệp bổ sung vào TensorFlow bằng cách mở rộng tính trừu tượng RandomAccessFile
( tensorflow/core/public/env.h
).
Tài liệu này tập trung vào việc tạo nguồn phát ra đường dẫn trong hệ thống tệp được TensorFlow hỗ trợ. Nó kết thúc bằng phần hướng dẫn cách sử dụng nguồn của bạn kết hợp với các mô-đun có sẵn để phục vụ các mô hình TensorFlow.
Tạo nguồn của bạn
Chúng tôi có triển khai tham chiếu Source<StoragePath>
, được gọi là FileSystemStoragePathSource
(tại sources/storage_path/file_system_storage_path_source*
). FileSystemStoragePathSource
giám sát một đường dẫn hệ thống tệp cụ thể, theo dõi các thư mục con bằng số và báo cáo phiên bản mới nhất trong số này là phiên bản mà nó mong muốn tải. Tài liệu này trình bày các khía cạnh nổi bật của FileSystemStoragePathSource
. Bạn có thể thấy thuận tiện khi tạo một bản sao của FileSystemStoragePathSource
và sau đó sửa đổi nó cho phù hợp với nhu cầu của mình.
Đầu tiên, FileSystemStoragePathSource
triển khai API Source<StoragePath>
, đây là một chuyên môn của API Source<T>
với T
được liên kết với StoragePath
. API bao gồm một phương thức duy nhất SetAspiredVersionsCallback()
, cung cấp một phương thức đóng mà nguồn có thể gọi để thông báo rằng nó muốn tải một tập hợp cụ thể các phiên bản có thể phân phát được.
FileSystemStoragePathSource
sử dụng lệnh gọi lại phiên bản mong muốn theo cách rất đơn giản: nó kiểm tra định kỳ hệ thống tệp (về cơ bản là thực hiện ls
) và nếu nó tìm thấy một hoặc nhiều đường dẫn trông giống như các phiên bản có thể phục vụ thì nó sẽ xác định đường dẫn nào là phiên bản mới nhất và gọi cuộc gọi lại với danh sách có kích thước một chỉ chứa phiên bản đó (theo cấu hình mặc định). Vì vậy, tại bất kỳ thời điểm nào FileSystemStoragePathSource
đều yêu cầu tải tối đa một có thể phân phát và việc triển khai nó tận dụng tính bình thường của lệnh gọi lại để giữ cho chính nó không có trạng thái (không có hại gì khi gọi lại lệnh gọi lại nhiều lần với cùng một đối số).
FileSystemStoragePathSource
có một nhà máy khởi tạo tĩnh (phương thức Create()
), nhận thông báo giao thức cấu hình. Thông báo cấu hình bao gồm các chi tiết như đường dẫn cơ sở để giám sát và khoảng thời gian giám sát. Nó cũng bao gồm tên của luồng có thể phân phát để phát ra. (Các phương pháp thay thế có thể trích xuất tên luồng có thể phân phát từ đường dẫn cơ sở để phát ra nhiều luồng có thể phân phát dựa trên việc quan sát hệ thống phân cấp thư mục sâu hơn; các biến thể đó nằm ngoài phạm vi triển khai tham chiếu.)
Phần lớn quá trình triển khai bao gồm một luồng kiểm tra định kỳ hệ thống tệp, cùng với một số logic để xác định và sắp xếp bất kỳ đường dẫn phụ bằng số nào mà nó phát hiện được. Chuỗi được khởi chạy bên trong SetAspiredVersionsCallback()
(không phải trong Create()
) vì đó là điểm mà nguồn sẽ "bắt đầu" và biết nơi gửi yêu cầu phiên bản mong muốn.
Sử dụng Nguồn của bạn để tải các phiên TensorFlow
Bạn có thể sẽ muốn sử dụng mô-đun nguồn mới của mình kết hợp với SavedModelBundleSourceAdapter
( servables/tensorflow/saved_model_bundle_source_adapter*
), mô-đun này sẽ diễn giải từng đường dẫn mà nguồn của bạn phát ra dưới dạng xuất TensorFlow và chuyển đổi từng đường dẫn thành một trình tải cho TensorFlow SavedModelBundle
có thể phân phát. Bạn có thể sẽ cắm bộ điều hợp SavedModelBundle
vào AspiredVersionsManager
, bộ điều hợp này sẽ đảm nhiệm việc thực sự tải và phân phát các dịch vụ. Bạn có thể tìm thấy một minh họa điển hình về việc kết hợp ba loại mô-đun này lại với nhau để có được một thư viện máy chủ hoạt động trong servables/tensorflow/simple_servers.cc
. Dưới đây là hướng dẫn chi tiết về luồng mã chính (có khả năng xử lý lỗi không tốt; mã thực nên cẩn thận hơn):
Đầu tiên, tạo người quản lý:
std::unique_ptr<AspiredVersionsManager> manager = ...;
Sau đó, tạo bộ điều hợp nguồn SavedModelBundle
và cắm nó vào trình quản lý:
std::unique_ptr<SavedModelBundleSourceAdapter> bundle_adapter;
SavedModelBundleSourceAdapterConfig config;
// ... populate 'config' with TensorFlow options.
TF_CHECK_OK(SavedModelBundleSourceAdapter::Create(config, &bundle_adapter));
ConnectSourceToTarget(bundle_adapter.get(), manager.get());
Cuối cùng, tạo nguồn đường dẫn của bạn và cắm nó vào bộ điều hợp SavedModelBundle
:
auto your_source = new YourPathSource(...);
ConnectSourceToTarget(your_source, bundle_adapter.get());
Hàm ConnectSourceToTarget()
(được xác định trong core/target.h
) chỉ gọi SetAspiredVersionsCallback()
để kết nối Source<T>
với Target<T>
( Target
là mô-đun nắm bắt các yêu cầu phiên bản mong muốn, tức là bộ điều hợp hoặc trình quản lý ).