forked from wjakob/nanobind
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
91 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
Copyright (c) 2022 Wenzel Jakob <[email protected]>, All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are met: | ||
|
||
1. Redistributions of source code must retain the above copyright notice, this | ||
list of conditions and the following disclaimer. | ||
|
||
2. Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimer in the documentation | ||
and/or other materials provided with the distribution. | ||
|
||
3. Neither the name of the copyright holder nor the names of its contributors | ||
may be used to endorse or promote products derived from this software | ||
without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,68 +1,93 @@ | ||
# nanobind — Seamless operability between C++17 and Python | ||
|
||
**nanobind** is a small binding library that exposes C++ types in Python and | ||
_nanobind_ is a small binding library that exposes C++ types in Python and | ||
vice versa. It is reminiscent of | ||
[Boost.Python](http://www.boost.org/doc/libs/1_58_0/libs/python/doc) and | ||
[pybind11](http://github.com/pybind/pybind11) and uses near-identical syntax. | ||
|
||
## Historical context: why _yet another_ binding library? | ||
|
||
The author of this library started the | ||
[pybind11](http://github.com/pybind/pybind11) project in back in 2015 to | ||
improve the efficiency of C++ ↔ Python bindings. pybind11 is now widely used: | ||
the repository is cloned more than 100.000 times per day, and it has become a | ||
core dependency of software across the world including flagship projects like | ||
PyTorch, Tensorflow, etc. Many extensions and generalizations were added by | ||
users and core developers over the years to address use cases of this diverse | ||
audience. The downside of this success was a growth in code complexity along | ||
with significant compile- and runtime overheads. | ||
|
||
Ironically, the situation feels just like 2015: bindings are once again | ||
extremely slow to compile with existing tools (Boost.Python, pybind11), and a | ||
new C++ standard has come along with the potential to dramatically simplify | ||
things. I feel compelled to do this one last time.. | ||
_[Boost.Python](http://www.boost.org/doc/libs/1_58_0/libs/python/doc)_ and | ||
_[pybind11](http://github.com/pybind/pybind11)_ and uses near-identical syntax. | ||
|
||
## Why _yet another_ binding library? | ||
|
||
I started the _[pybind11](http://github.com/pybind/pybind11)_ project in back in | ||
2015 to improve the efficiency of C++/Python bindings. Thanks to many amazing | ||
contributions by others, _pybind11_ has become a core dependency of software | ||
across the world including flagship projects like PyTorch, Tensorflow, etc. The | ||
repository is cloned more than 100.000 times _per day_. Many extensions and | ||
generalizations were added by users and core developers over the years to | ||
address use cases of this diverse audience. However, all of this success also | ||
came with _costs_: the complexity of the library grew tremendously, causing | ||
overheads on binary size, compilation time, and runtime performance. | ||
|
||
Ironically, the situation feels just like 2015: bindings are once again slow to | ||
compile with existing tools (_Boost.Python_, _pybind11_), and a new C++ | ||
standard has come along with the potential to dramatically simplify things. It | ||
seems I need to do this one more time.. | ||
|
||
## Talk is cheap, show me the numbers. | ||
|
||
TBD | ||
|
||
## Differences between `nanobind` and `pybind11` | ||
## What are differences between _nanobind_ and _pybind11_? | ||
|
||
The main difference is philosophical: _pybind11_ must deal with *all of C++* to | ||
bind complex legacy codebases, while _nanobind_ targets a smaller C++ subset. | ||
The codebase has to adapt to the binding tool and not the other way around. | ||
Pull requests with extensions and generalizations were welcomed in pybind11, | ||
while they will likely be rejected in this project. | ||
**The codebase has to adapt to the binding tool and not the other way around!** | ||
Pull requests with extensions and generalizations were welcomed in _pybind11_, | ||
but they will likely be rejected in this project. | ||
|
||
### Removed features | ||
|
||
Support for _multiple inheritance_ was a persistent source of complexity in | ||
pybind11, and it is one of the main casualties in creating _nanobind_. Besides | ||
this, the following features were removed: | ||
Support for multiple inheritance was a persistent source of complexity in | ||
_pybind11_, and it is one of the main casualties in creating _nanobind_. | ||
Besides this, the following features were removed: | ||
|
||
- Binding of classes with overloaded `operator new` / `operator delete`. | ||
- Module-local types or exceptions. | ||
- Eigen and NumPy integration. | ||
- Nested exceptions | ||
- Pickling | ||
- ``kw_only`` / ``pos_only`` argument annotations | ||
- Nested exceptions. | ||
- Pickling. | ||
- ``kw_only`` / ``pos_only`` argument annotations. | ||
- MyPy-compatible docstrings. | ||
- The `options` class for customizing docstring generation. | ||
|
||
Some of these may be reintroduced eventually, but it will need to be done in an | ||
opt-in manner that does not affect binary size and compilation/runtime | ||
performance of the base case. | ||
|
||
### Optimizations | ||
|
||
TBD | ||
Besides removing features, the rewrite was an opportunity to address | ||
long-standing performance issues with _pybind11_: | ||
|
||
- C++ objects are co-located with the Python object whenever | ||
possible (less pointer chasing). | ||
- C++ function binding information is co-located with the Python function | ||
object (less pointer chasing). | ||
- C++ type binding information is co-located with the Python type object (less | ||
pointer chasing, fewer hashtable lookups). | ||
- _nanobind_ internally replaces `std::unordered_map` with a more efficient hash | ||
table ([tsl::robin_map](https://github.com/Tessil/robin-map), which is | ||
included as a git submodule). | ||
- function calls from/to Python are realized using [vector | ||
calls](https://www.python.org/dev/peps/pep-0590), which gives a nice speed | ||
boost. The main function dispatch loop no longer allocates heap memory. | ||
- _pybind11_ was designed as a header-only library, which is generally a good | ||
thing because it simplifies the compilation workflow. However, one major | ||
downside of this is that a large amount of redundant code has to be compiled | ||
in each binding file (e.g., the function dispatch loop and all of the related | ||
internal data structures). _nanobind_ compiles a separate shared or static | ||
support library `libnanobind.so` and links it against the binding code to | ||
avoid redundant compilation. When using the CMake ``nanobind_add_module()`` | ||
function, this all happens automatically. | ||
|
||
|
||
### Dependencies | ||
|
||
nanobind depends on very recent versions of everything: | ||
|
||
- C++17 | ||
* ``if constexpr`` is crucial to simplify the internal meta-templating. | ||
- Python 3.8+ | ||
* nanobind heavily relies on [vector calls](https://www.python.org/dev/peps/pep-0590) | ||
that were introduced in version 3.8.. | ||
- CMake 3.17+ | ||
* Recent CMake versions include important improvements to `FindPython` | ||
that this project depends on. | ||
|
||
- **C++17**: The ``if constexpr`` feature was crucial to simplify the internal | ||
meta-templating of this library. | ||
- **Python 3.8+**: _nanobind_ heavily relies on [vector | ||
calls](https://www.python.org/dev/peps/pep-0590) that were introduced in | ||
version 3.8. | ||
- **CMake 3.17+**: Recent CMake versions include important improvements to | ||
`FindPython` that this project depends on. |