Skip to content

Commit d13a095

Browse files
committed
Document JIT compiling and PyTorch handling behavior
1 parent ba87413 commit d13a095

File tree

7 files changed

+140
-0
lines changed

7 files changed

+140
-0
lines changed

docs/conf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,5 @@
7979
# html_css_files = []
8080

8181
html_copy_source = False
82+
83+
# suppress_warnings = ["myst.domains"]

docs/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
:hidden:
1212
1313
Overview <self>
14+
src/jit_compiling
15+
src/pytorch_handling
1416
```
1517

1618
```{toctree}

docs/src/jit_compiling.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# JIT Compiling
2+
3+
CharonLoad executes the following steps to JIT compile the C++/CUDA extension:
4+
5+
## 1. (Optional) Clean
6+
7+
Removes any existing old files in the [build directory](#ResolvedConfig.full_build_directory). This optional step can be controlled by setting the [``clean_build``](#ResolvedConfig.clean_build) flag of <project:#ResolvedConfig>.
8+
9+
In addition, cleaning is **automatically** performed if at least one of these conditions are fulfilled:
10+
- CMake Configure step *failed*.
11+
- CharonLoad version used in previous run is *incompatible* with current version.
12+
(Same minor version, e.g. 0.3.X is considered incompatible to 0.4.Y.)
13+
- PyTorch version has *changed* since the previous run.
14+
15+
16+
## 2. Initialize
17+
18+
Prepares internal state and places ``.gitignore`` into [build directory](#ResolvedConfig.full_build_directory) to minimize noise.
19+
20+
21+
## 3. CMake Configure
22+
23+
Runs CMake on the specified [project directory](#ResolvedConfig.full_project_directory). Additional arguments to the command can be passed via [``cmake_options``](#ResolvedConfig.cmake_options) of <project:#ResolvedConfig>.
24+
25+
Skipped automatically if CMake configuration has not changed from previous run.
26+
27+
28+
## 4. Build
29+
30+
Performs parallel compilation of the configured project. If project source files have not changed between runs, the underlying native build tool usually skips unnecessary compilations on its own.
31+
32+
33+
## 5. (Optional) Stub Generation
34+
35+
Analyzes the compiled C++/CUDA extension and generates Python stub files. This is useful to enable syntax highlighting and auto-completion of the bindings in VS Code. This optional step can be enabled by specifying the [stubs directory](#ResolvedConfig.full_stubs_directory) of <project:#ResolvedConfig>.
36+
37+
Skipped automatically if the compiled extension file has not changed from a previous run, i.e. the build step did not alter the file.
38+
39+
40+
## 6. Import Path
41+
42+
Extends Python's module search paths with the location of the compiled extension to enable ``import`` calls to it. On Windows, the DLL search paths are also extended by the list of shared/dynamic libraries to which the extension links.

docs/src/pytorch_handling.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# PyTorch Handling
2+
3+
In addition to JIT Compiling, CharonLoad also provides native support for finding and linking against the PyTorch C++ library which is installed as part of the Python package ``torch``. To this end, the CMake function <project:#charonload_add_torch_library> is provided as a thin wrapper around [add_library()](<inv:cmake.org#command/add_library>).
4+
5+
However, the PyTorch C++ API comes with several non-trivial usage requirements that linking libraries must fulfill. Not meeting these requirements will lead to potentially obscure and hard-to-debug compiler and linker errors. Thus, CharonLoad automatically detects these usage requirements and adds them to the CMake target created by <project:#charonload_add_torch_library>.
6+
7+
In particular, the following PyTorch properties are handled:
8+
9+
10+
:::::{grid} 2 2 3 3
11+
:gutter: 3 3 4 4
12+
13+
::::{grid-item-card}
14+
:link: pytorch_handling/cpp_standard
15+
:link-type: doc
16+
17+
**C++ Standard**
18+
^^^
19+
Set minimum C++ standard for using PyTorch.
20+
21+
::::
22+
23+
::::{grid-item-card}
24+
:link: pytorch_handling/cpp11_abi
25+
:link-type: doc
26+
27+
**C++11 ABI**
28+
^^^
29+
Set correct C++11 ABI for linking.
30+
31+
::::
32+
33+
::::{grid-item-card}
34+
:link: pytorch_handling/position_independent_code
35+
:link-type: doc
36+
37+
**Position-Independent Code (PIC)**
38+
^^^
39+
Set required PIC flag for linking.
40+
41+
::::
42+
43+
:::::
44+
45+
46+
```{toctree}
47+
:hidden:
48+
49+
pytorch_handling/cpp_standard
50+
pytorch_handling/cpp11_abi
51+
pytorch_handling/position_independent_code
52+
```
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# C++11 ABI
2+
3+
:::{admonition} Hint
4+
:class: hint
5+
6+
This behavior is exclusive to Linux and the GCC compiler.
7+
:::
8+
9+
On Linux, the default C++ compiler is typically set to GCC. With the release of GCC 5 in 2017, its standard library introduced several [breaking ABI (Application Binary Interface) changes](https://gcc.gnu.org/wiki/Cxx11AbiCompatibility) between C++11 (and future standards) and C++98. While this may look irrelevant these days, PyTorch is built with great compatibility in mind such that even recent versions support Python's `manylinux2014` platform ([PEP 599](https://peps.python.org/pep-0599/)) which requires compatibility with GCC 4.8.
10+
11+
This, in turn, means that the PyTorch C++ library must adhere to and compile against the **old CXX11 ABI**. Consequently, projects linking against PyTorch also need to specify the respective compiler flag `_GLIBCXX_USE_CXX11_ABI=0`. This even extends to **all** other 3rd-party dependencies and often needs manual adjustment to their CMake scripts. Not meeting these requirements will lead to strange linker errors containing the mangled names of the incompatible C++ standard library classes.
12+
13+
CharonLoad automatically detects the CXX11 ABI flag used in PyTorch, transitively scans for all dependencies, and patches each of the respective CMake targets to make use of the ABI flag.
14+
15+
16+
:::{admonition} Note
17+
:class: note
18+
19+
Future versions of PyTorch, starting with [PyTorch 2.7](https://github.com/pytorch/pytorch/issues/149044), will switch to the **new CXX11 ABI**. Thus, compilation will work without CharonLoad's target patching.
20+
:::
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# C++ Standard
2+
3+
Like many projects, the PyTorch C++ library regularly adapts its minimum required C++ standard version to newer versions in order to benefit from the respective language and standard library improvements. In the past, the C++ standard has been numped for the following releases:
4+
5+
- C++11 &rarr; C++14: PyTorch 1.5 (see [release announcement](https://github.com/pytorch/pytorch/releases/tag/v1.4.0))
6+
- C++14 &rarr; C++17: PyTorch 2.1 (see [release announcement](https://github.com/pytorch/pytorch/releases/tag/v2.1.0))
7+
8+
Future versions may further increase the used standard to, e.g., C++20.
9+
10+
However, the PyTorch C++ library does not publicly expose this requirement to projects linking against it which may lead to compiler errors in the following cases:
11+
12+
- The project explicitly only needs a lower standard, e.g. `set(CMAKE_CXX_STANDARD 11)` for C++11
13+
- The project relies on the default standard selected of the compiler, e.g. C++14 for MSVC
14+
15+
CharonLoad automatically detects the minimum required C++ standard in order to use the PyTorch C++ library and sets the corresponding [CMake Compile Feature](https://cmake.org/cmake/help/latest/manual/cmake-compile-features.7.html#requiring-language-standards).
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Position-Independent Code (PIC)
2+
3+
Since extension modules are dynamically loaded by the Python interpreter, their actual code will be loaded at runtime and needs to work from any address in memory, i.e. cannot use fixed addresses. While this is automatically ensured during compilation for extension modules (and shared libraries), this requirement is not needed for static libraries which will be directly linked into the executable at compile time and can, in turn, use fixed addresses.
4+
5+
Similar to many C++ projects, developing a C++/CUDA extension may involve the help of external 3rd-party dependencies which may be linked as **static libraries**. However, this may lead to linker errors as code from the dependency cannot be relocated to an arbitrary address.
6+
7+
CharonLoad automatically scans for all transitive *static* dependencies, and patches each of the respective CMake targets to enable [``POSITION_INDEPENDENT_CODE``](<inv:cmake.org#prop_tgt/POSITION_INDEPENDENT_CODE>).

0 commit comments

Comments
 (0)