Skip to content

Commit cd68026

Browse files
authored
Add logic to handle Python-based backends instead of platform handlers (triton-inference-server#303)
1 parent 67ca860 commit cd68026

File tree

10 files changed

+99
-1023
lines changed

10 files changed

+99
-1023
lines changed

CMakeLists.txt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -309,13 +309,6 @@ install(
309309
${INSTALL_CONFIGDIR}
310310
)
311311

312-
install(
313-
DIRECTORY
314-
src/resources/platform_handlers
315-
DESTINATION
316-
${CMAKE_INSTALL_PREFIX}/backends/python
317-
)
318-
319312
install(
320313
FILES
321314
src/resources/triton_python_backend_utils.py

src/pb_stub.cc

Lines changed: 20 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,10 @@ Stub::Instantiate(
8282
const std::string& shm_region_name, const std::string& model_path,
8383
const std::string& model_version, const std::string& triton_install_path,
8484
bi::managed_external_buffer::handle_t ipc_control_handle,
85-
const std::string& name, const std::string& platform)
85+
const std::string& name, const std::string& python_runtime_model)
8686
{
87-
model_context_.Init(model_path, platform, triton_install_path, model_version);
87+
model_context_.Init(
88+
model_path, python_runtime_model, triton_install_path, model_version);
8889
name_ = name;
8990
health_mutex_ = nullptr;
9091
initialized_ = false;
@@ -1659,57 +1660,29 @@ PYBIND11_EMBEDDED_MODULE(c_python_backend_utils, module)
16591660

16601661
void
16611662
ModelContext::Init(
1662-
const std::string& model_path, const std::string& platform,
1663+
const std::string& model_path, const std::string& runtime_modeldir,
16631664
const std::string& triton_install_path, const std::string& model_version)
16641665
{
1665-
bool python_model_found = false;
1666-
std::string platform_model_path;
1667-
1668-
if (platform != "NONE") {
1669-
platform_model_path =
1670-
triton_install_path + "/platform_handlers/" + platform + "/model.py";
1671-
// Check if model file exists in the path.
1672-
struct stat buffer;
1673-
if (stat(platform_model_path.c_str(), &buffer) == 0) {
1674-
// Use the Platform model for serving the model.
1675-
python_model_found = true;
1676-
type_ = ModelType::PLATFORM;
1677-
python_model_path_ = platform_model_path;
1678-
// Trimming the model name from the model path, the platform model
1679-
// will populate the expected default model file name into model_path_.
1680-
model_dir_ = model_path.substr(0, model_path.find_last_of("\\/"));
1681-
} else {
1682-
LOG_WARN << "Unable to find model(handler) \'" << platform_model_path
1683-
<< "\' for platform field \'" << platform << "\'";
1684-
}
1685-
}
1686-
1687-
if (!python_model_found) {
1666+
type_ = ModelType::DEFAULT;
1667+
if (runtime_modeldir != "DEFAULT") {
1668+
// For python based backends, existence of `model.py` in the corresponding
1669+
// backend folder happens on the core side, so we can omit this check here.
1670+
python_model_path_ = runtime_modeldir + "/model.py";
1671+
type_ = ModelType::BACKEND;
1672+
} else {
16881673
python_model_path_ = model_path;
16891674
// Check if model file exists in this path.
16901675
struct stat buffer;
1691-
if (stat(python_model_path_.c_str(), &buffer) == 0) {
1692-
python_model_found = true;
1693-
type_ = ModelType::DEFAULT;
1694-
}
1695-
// Initializing here for consistency with platform model case.
1696-
model_dir_ = model_path.substr(0, model_path.find_last_of("\\/"));
1697-
}
1698-
1699-
if (!python_model_found) {
1700-
if (platform != "NONE") {
1701-
throw PythonBackendException(
1702-
("Python model file not found in neither \'" + platform_model_path +
1703-
"\' nor \'" + model_path + "\'"));
1704-
} else {
1676+
if (stat(python_model_path_.c_str(), &buffer) != 0) {
17051677
throw PythonBackendException(
17061678
("Python model file not found in \'" + model_path + "\'"));
17071679
}
17081680
}
17091681

1682+
model_dir_ = model_path.substr(0, model_path.find_last_of("\\/"));
17101683
python_backend_folder_ = triton_install_path;
17111684
model_version_ = model_version;
1712-
platform_ = platform;
1685+
runtime_modeldir_ = runtime_modeldir;
17131686
}
17141687

17151688
void
@@ -1740,9 +1713,10 @@ ModelContext::StubSetup(py::module& sys)
17401713
sys = py::module_::import(
17411714
(std::string(model_version_) + "." + model_name_trimmed).c_str());
17421715
} else {
1743-
std::string platform_model_dir(
1744-
python_backend_folder_ + "/platform_handlers/" + platform_ + "/");
1745-
sys.attr("path").attr("append")(platform_model_dir);
1716+
std::string model_path_parent =
1717+
python_model_path_.substr(0, python_model_path_.find_last_of("/"));
1718+
std::string backend_model_dir(model_path_parent);
1719+
sys.attr("path").attr("append")(backend_model_dir);
17461720
sys.attr("path").attr("append")(python_backend_folder_);
17471721
sys = py::module_::import(model_name_trimmed.c_str());
17481722
}
@@ -1791,14 +1765,14 @@ main(int argc, char** argv)
17911765
int64_t shm_growth_size = std::stol(argv[4]);
17921766
std::string triton_install_path = argv[6];
17931767
std::string name = argv[8];
1794-
std::string platform = argv[9];
1768+
std::string runtime_modeldir = argv[9];
17951769

17961770
std::unique_ptr<Stub>& stub = Stub::GetOrCreateInstance();
17971771
try {
17981772
stub->Instantiate(
17991773
shm_growth_size, shm_default_size, shm_region_name, model_path,
18001774
model_version, argv[6] /* triton install path */,
1801-
std::stoi(argv[7]) /* IPCControl handle */, name, platform);
1775+
std::stoi(argv[7]) /* IPCControl handle */, name, runtime_modeldir);
18021776
}
18031777
catch (const PythonBackendException& pb_exception) {
18041778
LOG_INFO << "Failed to preinitialize Python stub: " << pb_exception.what();

src/pb_stub.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,15 @@ class ModelContext {
180180
std::string model_dir_;
181181
std::string model_version_;
182182
std::string python_backend_folder_;
183-
std::string platform_;
184-
185-
enum ModelType { DEFAULT, PLATFORM };
183+
std::string runtime_modeldir_;
184+
185+
// Triton supports python-based backends,
186+
// i.e. backends that provide common `model.py`, that can be re-used
187+
// between different models. `ModelType` helps to differentiate
188+
// between models running with c++ python backend (ModelType::DEFAULT)
189+
// and models running with python-based backend (ModelType::BACKEND)
190+
// at the time of ModelContext::StubSetup to properly set up paths.
191+
enum ModelType { DEFAULT, BACKEND };
186192
ModelType type_;
187193
};
188194

@@ -210,7 +216,8 @@ class Stub {
210216
const std::string& shm_region_name, const std::string& model_path,
211217
const std::string& model_version, const std::string& triton_install_path,
212218
bi::managed_external_buffer::handle_t ipc_control_handle,
213-
const std::string& model_instance_name, const std::string& platform);
219+
const std::string& model_instance_name,
220+
const std::string& runtime_modeldir);
214221

215222
/// Get the health of the stub process.
216223
bool& Health();

src/python_be.cc

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,11 +1771,12 @@ ModelState::ModelState(TRITONBACKEND_Model* triton_model)
17711771
python_execution_env_ = "";
17721772
force_cpu_only_input_tensors_ = true;
17731773
decoupled_ = false;
1774-
platform_ = "";
17751774

17761775
void* bstate;
17771776
THROW_IF_BACKEND_MODEL_ERROR(TRITONBACKEND_BackendState(backend, &bstate));
17781777
backend_state_ = reinterpret_cast<BackendState*>(bstate);
1778+
1779+
runtime_modeldir_ = backend_state_->runtime_modeldir;
17791780
triton::common::TritonJson::Value params;
17801781
common::TritonJson::Value model_config;
17811782
if (model_config_.Find("parameters", &params)) {
@@ -1812,14 +1813,6 @@ ModelState::ModelState(TRITONBACKEND_Model* triton_model)
18121813
}
18131814
}
18141815

1815-
triton::common::TritonJson::Value platform;
1816-
if (model_config_.Find("platform", &platform)) {
1817-
auto error = platform.AsString(&platform_);
1818-
if (error != nullptr) {
1819-
throw BackendModelException(error);
1820-
}
1821-
}
1822-
18231816
// Skip the FORCE_CPU_ONLY_INPUT_TENSORS variable if it doesn't exits.
18241817
std::string force_cpu_only_input_tensor;
18251818
error = nullptr;
@@ -1948,8 +1941,11 @@ TRITONBACKEND_Initialize(TRITONBACKEND_Backend* backend)
19481941
backend_state->shm_message_queue_size = 1000;
19491942
backend_state->number_of_instance_inits = 0;
19501943
backend_state->thread_pool_size = 32;
1944+
// Initialize shared memory region prefix to include backend's name
1945+
// to avoid collision between python backend and python-based backends.
19511946
backend_state->shared_memory_region_prefix =
1952-
"triton_python_backend_shm_region_";
1947+
"triton_" + name + "_backend_shm_region_";
1948+
std::string default_backend_dir_string;
19531949

19541950
if (backend_config.Find("cmdline", &cmdline)) {
19551951
triton::common::TritonJson::Value shm_growth_size;
@@ -2059,6 +2055,12 @@ TRITONBACKEND_Initialize(TRITONBACKEND_Backend* backend)
20592055
return TRITONSERVER_ErrorNew(TRITONSERVER_ERROR_INVALID_ARG, ia.what());
20602056
}
20612057
}
2058+
2059+
triton::common::TritonJson::Value default_backend_dir;
2060+
if (cmdline.Find("backend-directory", &default_backend_dir)) {
2061+
RETURN_IF_ERROR(
2062+
default_backend_dir.AsString(&default_backend_dir_string));
2063+
}
20622064
}
20632065

20642066
LOG_MESSAGE(
@@ -2076,7 +2078,50 @@ TRITONBACKEND_Initialize(TRITONBACKEND_Backend* backend)
20762078
TRITONBACKEND_ArtifactType artifact_type;
20772079
RETURN_IF_ERROR(
20782080
TRITONBACKEND_BackendArtifacts(backend, &artifact_type, &location));
2079-
backend_state->python_lib = location;
2081+
2082+
// Check if `triton_python_backend_stub` and `triton_python_backend_utils.py`
2083+
// are located under `location`.
2084+
// DLIS-5596: Add forward slash to be platform agnostic
2085+
// (i.e. For Windows, we need to use backward slash).
2086+
std::string default_python_backend_dir =
2087+
default_backend_dir_string + "/python";
2088+
std::string backend_stub_path =
2089+
std::string(location) + "/triton_python_backend_stub";
2090+
std::string backend_utils =
2091+
std::string(location) + "/triton_python_backend_utils.py";
2092+
// Both, stub and utils should be in the same location
2093+
if (FileExists(backend_stub_path) && FileExists(backend_utils)) {
2094+
backend_state->python_lib = location;
2095+
// If `location` is default location of a python backend,
2096+
// then we are using default python backend.
2097+
if (default_python_backend_dir == std::string(location)) {
2098+
backend_state->runtime_modeldir = "";
2099+
} else {
2100+
// If `location` is not default location of a python backend,
2101+
// then we are using a python backend based backend and model.py stored
2102+
// in the received location.
2103+
backend_state->runtime_modeldir = location;
2104+
}
2105+
} else {
2106+
// If stub and utils are not found in received `location`,
2107+
// then we are using a python backend based backend and stub and utils are
2108+
// stored in the default python backend location.
2109+
if (!default_backend_dir_string.empty()) {
2110+
std::string backend_stub_path =
2111+
default_backend_dir_string + "/python/triton_python_backend_stub";
2112+
if (!FileExists(backend_stub_path)) {
2113+
return TRITONSERVER_ErrorNew(
2114+
TRITONSERVER_ERROR_NOT_FOUND,
2115+
(std::string("triton_python_backend_stub") +
2116+
" is not found. Searched paths: " + default_backend_dir_string +
2117+
"/python and" + std::string(location))
2118+
.c_str());
2119+
}
2120+
}
2121+
backend_state->runtime_modeldir = location;
2122+
backend_state->python_lib = default_backend_dir_string + "/python";
2123+
}
2124+
20802125
backend_state->env_manager = std::make_unique<EnvironmentManager>();
20812126

20822127
RETURN_IF_ERROR(TRITONBACKEND_BackendSetState(

src/python_be.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ struct BackendState {
218218
std::string shared_memory_region_prefix;
219219
int64_t thread_pool_size;
220220
std::unique_ptr<EnvironmentManager> env_manager;
221+
std::string runtime_modeldir;
221222
};
222223

223224
class ModelState : public BackendModel {
@@ -237,8 +238,8 @@ class ModelState : public BackendModel {
237238
// Is decoupled API being used.
238239
bool IsDecoupled() { return decoupled_; }
239240

240-
// Returns the value in the platform field
241-
std::string Platform() { return platform_; }
241+
// Returns the value in the `runtime_modeldir_` field
242+
std::string RuntimeModelDir() { return runtime_modeldir_; }
242243

243244
// Launch auto-complete stub process.
244245
TRITONSERVER_Error* LaunchAutoCompleteStubProcess();
@@ -255,7 +256,7 @@ class ModelState : public BackendModel {
255256
std::string python_execution_env_;
256257
bool force_cpu_only_input_tensors_;
257258
bool decoupled_;
258-
std::string platform_;
259+
std::string runtime_modeldir_;
259260
std::unique_ptr<StubLauncher> auto_complete_stub_;
260261
};
261262

0 commit comments

Comments
 (0)