extension-cpp, and the same custom op written two ways
C++ extensions in PyTorch
At a glance
- What is it?
- This repository holds two example PyTorch C++ extensions that do the same thing, a mymuladd custom op with a CPU and a CUDA kernel. The interesting part is the difference between them: one uses the standard ATen and LibTorch API, the other uses the LibTorch Stable ABI so the built example can run without recompilation across PyTorch versions 2.10.0 and newer.
- Who is it for?
- Adopt this repository as a template if you are writing a PyTorch custom op in C++ or CUDA and want a working example of the build, the binding and the test in one place. Do not treat it as a library, since it contains no reusable component, and do not use the standard API example if you need your extension to survive a PyTorch upgrade, because that is exactly the problem the stable ABI example exists to demonstrate.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 31 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- pytorch/extension-cpp1,203 ★ · +0
| Repository | 2026-10-20 | 2026-11-07 |
|---|---|---|
| pytorch/extension-cpp | 1.2k | 1.2k |
0 Stars in the last 18 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Two extensions, one operation, and a deliberate difference
This repository contains two example C++ and CUDA extensions for PyTorch, and the pair is the point.
The first is extension_cpp, which uses the standard ATen and LibTorch API. The description calls this the traditional way of writing PyTorch extensions, and it points at the PyTorch tutorial on custom C++ operations for more detail.
The second is extension_cpp_stable, which uses the LibTorch Stable ABI. The Stable ABI exists to ensure that the extension built can be run with any version of PyTorch from 2.10.0 onwards, without needing to recompile for each PyTorch version.
Both extensions demonstrate how to write an example mymuladd custom op that has both custom CPU and CUDA kernels. So the operation is identical, the kernels are identical, and the difference is entirely in how the extension binds to the framework.
That makes this repository unusually useful as a reference, because a single feature is implemented twice and the two implementations can be read side by side. Most examples of a technique show you one way to do it, and a reader has to take the design on trust. Here the alternative is in the next directory.
The authors are Peter Goldsborough and Richard Zou, and the repository is under the pytorch organisation, which is what tells you these are reference examples rather than a supported product.
The Stable ABI, and the recompilation problem it removes
The stable variant is the more consequential of the two, so it is worth being precise about what it buys.
An extension built against the standard ATen and LibTorch API is bound to the headers and the ABI of the PyTorch version it was compiled against. The C++ API of a deep learning framework is not a stable interface in the way a C library is, and when the framework changes, an extension that was compiled against the older version can fail to load, or load and misbehave, or fail to build against the newer one.
The Stable ABI narrows that surface. The project description says the extension built with extension_cpp_stable can be run with any version of PyTorch from 2.10.0 onwards without needing to recompile for each PyTorch version, and that the stable examples require PyTorch 2.10 or newer.
So the trade is between two things. The standard API gives you the whole ATen surface, which is a lot of capability, and the price is a recompile for each PyTorch version. The Stable ABI gives you a restricted, frozen interface, and the price is that some of what ATen offers is not available and that you need a recent enough PyTorch to begin with.
For an extension that ships to users as a binary wheel, this is the difference between a package that keeps working and a package that has to be rebuilt for every release of the framework. For a developer working inside one environment, the standard API is the simpler choice, and that is why both examples exist.
Building, and why build isolation is turned off
The build section is three commands, and the flag in them is the part that matters.
For the standard API extension, you change into its directory and install it in editable mode with build isolation disabled.
cd extension_cpp
pip install --no-build-isolation -e .For the stable ABI extension, the same two steps in its own directory.
cd extension_cpp_stable
pip install --no-build-isolation -e .The --no-build-isolation flag is the significant detail. Normally, pip builds a package in a fresh, isolated environment with its own temporary dependencies, and for a PyTorch extension that is a problem, because the build has to find the installed torch to compile against. With isolation on, the build environment has no torch in it, and the extension either fails to configure or, worse, builds against something it should not.
The editable install is the other half. The -e flag means the extension is compiled in place and linked against the source tree, so a change to the C++ or CUDA source is picked up without reinstalling, which is what you want in a development loop where you are iterating on a kernel.
The result is that both examples are built the same way, and the difference between them appears at compile time in how they bind, not in how you build them.
One test script for both, and the layout that makes it work
Testing both extensions is a single command.
python test/test_extension.pyOne script covering both, which is a good sign about the design. If the two extensions had diverged in their interfaces, the test would have to know which one it was exercising, and the point of the repository, that the same op is implemented twice, would be lost.
The repository layout is small and mirrors the structure exactly. There are the two extension directories, extension_cpp and extension_cpp_stable, a test directory at the top level with the test script, a .github directory, a .gitignore and the README.
So the test lives at the root rather than inside either extension, which is what allows it to run against both. That is a small organisational decision, and it is the one that makes the comparison legible.
The operation itself is mymuladd, a multiply and add, and the description says both extensions demonstrate it with custom CPU and CUDA kernels. So the example covers the whole path a custom op takes: the kernel for the CPU, the kernel for the GPU, the dispatch between them, the binding that makes the op visible from Python, and the test that checks the result matches what PyTorch would have produced with its own operators.
That last point is worth stating, because it is what makes such an example trustworthy. An extension that computes the right answer only for the cases its test happens to cover is not much of a reference.
Two directories, a README, and a repository with no releases
The top level of the repository holds almost nothing, and what is there is worth naming because it tells you what kind of artefact this is.
There is the .github directory, a .gitignore and a README. There is no package manifest at the root, no build script, no changelog and no documentation site. The two extension directories are self contained, and the test directory is the only thing that spans them.
The maintenance state is modest, and it is normal for a reference repository. There are no GitHub releases, the last push was on 2026-10-07, and the repository is not archived. The licence is recorded as unknown, with the licence file to be consulted, which for a repository inside the pytorch organisation is a question about the parent project rather than about these two examples.
What the repository is, then, is a small, well chosen teaching artefact. Two implementations of one operation, one built on the traditional API and one built on the stable interface, with the build commands and a test that runs against both. For someone about to write their first PyTorch custom op in C++ or CUDA, that is a smaller and more useful thing than a framework guide, because it is the shape of a real extension, from the kernel to the editable install to the test.
For the more adventurous case, where the extension is going to be shipped to users as a binary, the stable variant is the one to study, and the reason is in the project description: it is built so that it can be run with any PyTorch version from 2.10.0 onwards without recompiling for each one.
Editorial conclusion
Adopt this repository as a template if you are writing a PyTorch custom op in C++ or CUDA and want a working example of the build, the binding and the test in one place. Do not treat it as a library, since it contains no reusable component, and do not use the standard API example if you need your extension to survive a PyTorch upgrade, because that is exactly the problem the stable ABI example exists to demonstrate. Before you copy anything, check whether the stable ABI route is available in the PyTorch version you target, since the project states the stable examples require PyTorch 2.10 or newer, and build with --no-build-isolation so the extension links against the torch you actually have installed.
Frequently asked questions
What is in the pytorch extension-cpp repository?
Two example C++ and CUDA extensions for PyTorch that both implement a mymuladd custom op with custom CPU and CUDA kernels: extension_cpp using the standard ATen and LibTorch API, and extension_cpp_stable using the LibTorch Stable ABI.
What does the LibTorch Stable ABI give an extension?
It ensures that the extension built can be run with any version of PyTorch from 2.10.0 onwards, without needing to recompile for each PyTorch version, which matters most for an extension distributed as a binary.
How do I build the examples?
Change into the extension directory and install it in editable mode with build isolation disabled, with `cd extension_cpp` followed by `pip install --no-build-isolation -e .`, or the same two steps in extension_cpp_stable for the stable ABI version.
How do I test the extensions?
With `python test/test_extension.py` from the repository root. The test lives at the top level and covers both extensions.
Who wrote these examples and how current are they?
The authors are Peter Goldsborough and Richard Zou. The repository publishes no GitHub releases, the last push was on 2026-10-07, and the stable ABI examples require PyTorch 2.10 or newer.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pytorch-extension-cpp)Star history chart for your README
[](https://hysenlabs.com/projects/pytorch-extension-cpp)Was this useful?