Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: load customized OP library in the C++ interface #4073

Merged
merged 2 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions doc/development/create-a-model-pt.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,15 @@ If you place `SomeDescript` and `descrpt_some_args` into different modules, you

After you install your new package, you can now use `dp train` to run your new model.

### Package customized C++ OPs

You may need to use customized PyTorch C++ OPs in the new model.
Follow [PyTorch documentation](https://pytorch.org/tutorials/advanced/torch_script_custom_ops.html) to create one library.

When using your customized C++ OPs in the Python interface, use {py:meth}`torch.ops.load_library` to load the OP library in the module defined in `entry_points`.

When using your customized C++ OPs in the C++ library, define the environment variable {envvar}`DP_PLUGIN_PATH` to load the OP library.

## Unit tests

### Universal tests
Expand Down
9 changes: 9 additions & 0 deletions doc/development/create-a-model-tf.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,12 @@ where `deepmd_some_descrtpt` is the module of your codes. It is equivalent to `f
If you place `SomeDescript` and `descrpt_some_args` into different modules, you are also expected to add `descrpt_some_args` to `entry_points`.

After you install your new package, you can now use `dp train` to run your new model.

### Package customized C++ OPs

You may need to use customized TensorFlow C++ OPs in the new model.
Follow [TensorFlow documentation](https://www.tensorflow.org/guide/create_op) to create one library.

When using your customized C++ OPs in the Python interface, use {py:meth}`tf.load_op_library` to load the OP library in the module defined in `entry_points`.

When using your customized C++ OPs in the C++ library, define the environment variable {envvar}`DP_PLUGIN_PATH` to load the OP library.
12 changes: 12 additions & 0 deletions doc/env.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,15 @@ Default backend.
See [PyTorch documentation](https://pytorch.org/docs/stable/data.html) for details.

:::

## C++ interface only

These environment variables also apply to third-party programs using the C++ interface, such as [LAMMPS](./third-party/lammps-command.md).

:::{envvar} DP_PLUGIN_PATH

**Type**: List of paths, split by `:` on Unix and `;` on Windows

List of customized OP plugin libraries to load, such as `/path/to/plugin1.so:/path/to/plugin2.so` on Linux and `/path/to/plugin1.dll;/path/to/plugin2.dll` on Windows.

:::
30 changes: 27 additions & 3 deletions source/api_cc/src/common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -377,12 +377,10 @@
}
}

static inline void _load_single_op_library(std::string library_name) {
static inline void _load_library_path(std::string dso_path) {
#if defined(_WIN32)
std::string dso_path = library_name + ".dll";
void* dso_handle = LoadLibrary(dso_path.c_str());
#else
std::string dso_path = "lib" + library_name + ".so";
void* dso_handle = dlopen(dso_path.c_str(), RTLD_NOW | RTLD_LOCAL);
#endif
if (!dso_handle) {
Expand All @@ -392,13 +390,39 @@
}
}

static inline void _load_single_op_library(std::string library_name) {
#if defined(_WIN32)
std::string dso_path = library_name + ".dll";
#else
std::string dso_path = "lib" + library_name + ".so";
#endif
_load_library_path(dso_path);
}

void deepmd::load_op_library() {
#ifdef BUILD_TENSORFLOW
_load_single_op_library("deepmd_op");
#endif
#ifdef BUILD_PYTORCH
_load_single_op_library("deepmd_op_pt");
#endif
// load customized plugins
const char* env_customized_plugins = std::getenv("DP_PLUGIN_PATH");
if (env_customized_plugins) {
#if !defined(_WIN32)
// note: ":" is a string and ':' is a char
std::string pathvarsep = ":";

Check warning on line 414 in source/api_cc/src/common.cc

View check run for this annotation

Codecov / codecov/patch

source/api_cc/src/common.cc#L414

Added line #L414 was not covered by tests
#else
std::string pathvarsep = ";";
#endif
std::string plugin_path(env_customized_plugins);
std::vector<std::string> plugin_paths = split(plugin_path, pathvarsep);

Check warning on line 419 in source/api_cc/src/common.cc

View check run for this annotation

Codecov / codecov/patch

source/api_cc/src/common.cc#L418-L419

Added lines #L418 - L419 were not covered by tests
for (const auto& plugin : plugin_paths) {
std::cerr << "Loading customized plugin defined in DP_PLUGIN_PATH: "
<< plugin << std::endl;
_load_library_path(plugin);

Check warning on line 423 in source/api_cc/src/common.cc

View check run for this annotation

Codecov / codecov/patch

source/api_cc/src/common.cc#L422-L423

Added lines #L422 - L423 were not covered by tests
}
}
njzjz marked this conversation as resolved.
Show resolved Hide resolved
}

std::string deepmd::name_prefix(const std::string& scope) {
Expand Down