Dr.Jit: a just-in-time compiler built for giant differentiable graphs
Dr.Jit — A Just-In-Time-Compiler for Differentiable Rendering
At a glance
- What is it?
- Dr.Jit records arithmetic into a computation graph, compiles that graph into fused kernels for Metal, CUDA or CPU vector units, and differentiates it with forward or reverse mode automatic differentiation. It was written for differentiable rendering, where graphs reach hundreds of thousands of trivial nodes, and that workload is where it differs from JAX, TensorFlow and PyTorch.
- Who is it for?
- Adopt Dr.Jit if you write differentiable renderer or similar code whose computation graph has hundreds of thousands of small nodes, if you need to mix C++ and Python in one traced program, or if you want a vector library that can drop the JIT entirely.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A compiler for programs that are graphs, not tensors
Dr.Jit started life as the numerical foundation of Mitsuba 3, a differentiable Monte Carlo renderer. It has since become a general-purpose tool for what the project calls ordinary and differentiable computation, and for other embarrassingly parallel problems.
The idea is simple to state. When you write an arithmetic operation such as a + b, Dr.Jit does not perform the operation immediately. It records it into a computation graph. Later, the graph is just-in-time compiled into fused kernels that target the hardware. On macOS the target is Metal, elsewhere it is CUDA, and for CPU execution the compiler goes through LLVM and can emit vector instructions such as AVX512 or NEON.
The word fused is where the performance argument lives. A graph node that would normally be a separate memory round trip becomes part of a larger kernel that keeps intermediate values in registers. The README states plainly that the generated kernels are very efficient, and the paper referenced by the project covers the design in detail.
There is a second mode worth knowing before you commit. Dr.Jit can also be used without JIT compilation, in which case the project becomes a header-only vector library with no external dependencies. That is a meaningful escape hatch, and it makes the library usable in environments where a compiler toolchain or a GPU is simply not available.
The audience is researchers and engineers doing differentiable rendering, inverse problems and adjacent numerical work, and the licence is BSD-3-Clause with the implementation in C++.
Why the graph size changes the design
The clearest explanation of Dr.Jit's purpose comes from the section comparing it to machine learning frameworks. The question the project asks is why it exists at all, given that dynamic derivative compilation is already possible with JAX, TensorFlow and PyTorch along with backends like XLA and TorchScript.
The answer is the shape of the workload. Machine learning involves smallish computation graphs built from arithmetically intense operations such as convolutions and matrix multiplications. Differentiable rendering, the application that motivated Dr.Jit, creates giant and messy computation graphs consisting of 100K to millions of trivial nodes, where the nodes are elementary arithmetic operations.
That difference matters because compilation backends have internal representations and optimization passes. The project states that ML compilation backends use representations that are too rich for this type of input, causing them to crash or time out during compilation. If you have seen a compiler run out of memory on a graph full of small operations, that is the problem Dr.Jit is built to survive.
So the real alternative here is not a competitor to JAX in general, it is a different compiler design for a different graph regime. A machine learning framework optimises a small number of expensive nodes. Dr.Jit optimises the compilation process itself for a huge number of cheap ones, which is the right trade when the arithmetic is trivial and the bookkeeping is not.
That framing also tells you when Dr.Jit is the wrong tool. If your workload is dense tensor algebra, the mainstream frameworks have better-tuned kernels for exactly that case, and Dr.Jit is not trying to compete there.
Differentiation that shares the tracing machinery
Automatic differentiation in Dr.Jit is not a separate subsystem bolted onto a vector library. The project describes differentiation and tracing as going hand in hand, producing specialised derivative evaluation code.
Both forward mode and reverse mode accumulation are supported, and the choice is the familiar one: forward mode propagates derivatives alongside the primal values and is efficient when you want one derivative per input, reverse mode is efficient when you want one derivative per output, which is the common case in an optimisation loop that differentiates a loss.
Because the graph already exists as a first class object, differentiating it is a matter of asking the same machinery for the derivative variant of that graph rather than re-recording the program in a second pass. The result is code specialised to the derivative computation, not a generic tape replay.
This is where the differentiable rendering origin shows. In a Monte Carlo renderer, the scene is described by parameters that you want to optimise, and the image is the result of a stochastic simulation. The graph is large because every light sample, every bounce and every pixel contributes arithmetic nodes, and the derivatives have to flow back through all of it. A compiler that chokes on the graph size is not a usable foundation for that problem.
One practical consequence for the user is that the derivative code is generated, not hand-written, so the cost of a wrong choice about forward or reverse mode shows up as compilation and evaluation time rather than as a subtle numerical bug.
Cloning the project with its submodules
Dr.Jit recursively depends on two other repositories. nanobind provides the Python bindings, and drjit-core provides the core components of the JIT compiler. Both are pulled in as submodules, which is why a plain clone is not enough.
The command the project gives is:
$ git clone --recursive https://github.com/mitsuba-renderer/drjitWithout the --recursive flag you end up with empty submodule directories and a build that cannot find the compiler core or the binding layer. The repository carries a .gitmodules file, so the recursive clone is the supported path.
For Python users the project also publishes a package. The README links a PyPI badge for the drjit package, and the packaging metadata in pyproject.toml shows how the wheel is assembled. It uses scikit-build-core as the build backend, with nanobind pinned to version 3.1.0, and it declares a Python floor:
[project]
name = "drjit"
dynamic = ["version", "readme"]
description = "Dr.Jit: A Just-In-Time Compiler for Differentiable Rendering"
dependencies = [
"typing_extensions;python_version<\"3.11\"",
"nanobind-backend>=1.0.0"
]
requires-python = ">=3.10"Two details in that block affect your rollout. The typing_extensions dependency is conditional on Python older than 3.11, so on a modern interpreter the package pulls in less. And the build configuration sets wheel.py-api to cp310, which the comment explains means one wheel per platform covers every supported Python version because the build targets the stable ABI.
The build itself goes through CMake, with CMakeLists.txt at the repository root and a scikit-build-core configuration pointing at a local build directory for caching.
C++ and Python in the same traced program
Dr.Jit types are accessible in C++17 and in Python, and the project makes a point of saying that code can be developed in either language, or even both at once. Combinations of Python and C++ code can be jointly traced and differentiated.
That is a real engineering constraint behind the design rather than a convenience. A renderer typically has a performance sensitive core and an experimental outer layer, and forcing both into one language is often unwelcome. Joint tracing means a Python function can call into a C++ function that itself performs traced arithmetic, and the resulting graph spans both.
The library also handles large programs with custom data structures, side effects and polymorphism, which is a much harder requirement than it sounds. A graph recorder that only copes with plain arrays and pure functions cannot express the control flow of a real renderer, and Dr.Jit claims to.
On top of that sits a mathematical support library. It includes transcendental functions and types such as vectors, matrices, complex numbers and quaternions, so the numeric building blocks a renderer needs are already present rather than something you assemble from another dependency.
The name itself carries history. Dr.Jit is the successor of the Enoki project, and the README notes that the high-level API still somewhat resembles Enoki even though the system evolved towards a different approach with an all-new implementation, which is why the project was renamed.
Where the JIT path is the wrong trade
The honest limits come from the same place as the strengths.
First, compilation is not free. Dr.Jit fixes the crash and timeout problem of general purpose backends, but it still compiles a graph before evaluating it. A workload with a tiny graph and a very short lifetime will spend more time in the compiler than in the arithmetic, and the header-only mode without JIT is the sensible answer there.
Second, the build is heavier than a normal Python dependency. The package needs a C++ toolchain and CMake, and the JIT path needs the compiler core from drjit-core. A CI image that only has Python and pip will not be enough without checking the build requirements for the platform you target.
Third, the hardware targets are specific. Metal on macOS, CUDA elsewhere for the GPU path, and CPU vectorisation through LLVM with AVX512 or NEON. A machine without a supported GPU falls back to the CPU path, which changes the performance profile of the same program.
Fourth, the repository layout makes the two-repository dependency visible to anyone building from source, and the recursive clone requirement is a genuine papercut for scripted setups that clone without submodules.
None of this makes the project unsuitable. It makes it a specialised tool, and the specialisation is stated rather than hidden.
Licence, release cadence and what the paper covers
The licence is BSD-3-Clause, and the pyproject classifiers confirm it as a BSD licensed project. BSD terms are permissive, so using Dr.Jit inside a commercial or academic codebase does not oblige you to publish anything derived from it, though this is not legal advice and your own review should confirm that for your use.
On maintenance, the repository is not archived and the last push was on 2026-10-17. Recent releases are v1.5.0 and v1.4.0, both dated 2026-08-07, and v1.3.1 from 2026-02-23. The project has an ongoing continuous integration setup hosted at rgl-ci.epfl.ch, which the README links through a build status badge, and the documentation is published on readthedocs.io.
There is no separate homepage for the project beyond the repository and the documentation site, and the README is written in reStructuredText, with README.rst as the file name rather than a Markdown one.
For anyone evaluating the design rather than just the API, the project points at the paper Dr.Jit: A Just-In-Time Compiler for Differentiable Rendering in the Transactions on Graphics, volume 41, number 4, with a video presentation available for the higher level explanation. The paper also covers the problem that motivated the project, which is the more useful half if you are deciding whether a graph of your own is the shape this compiler was built for.
Editorial conclusion
Adopt Dr.Jit if you write differentiable renderer or similar code whose computation graph has hundreds of thousands of small nodes, if you need to mix C++ and Python in one traced program, or if you want a vector library that can drop the JIT entirely. Do not adopt it for ordinary machine learning workloads on dense tensor operations, since the project positions itself against JAX, TensorFlow and PyTorch precisely on graph shape, and do not expect a pip-only workflow without reading the build configuration. Before you start, clone with git clone --recursive so that drjit-core and nanobind are present, and check that your Python is 3.10 or newer, since the project metadata requires it.
Frequently asked questions
How do I clone Dr.Jit with all its dependencies?
Use git clone --recursive https://github.com/mitsuba-renderer/drjit. The project recursively depends on nanobind for the Python bindings and drjit-core for the core compiler components, so a clone without submodules leaves both empty.
What GPU backends does Dr.Jit compile for?
The compiler targets Metal on macOS and CUDA on other platforms. For CPU execution it goes through LLVM and can use vector instruction sets such as AVX512 or NEON, and the project can also be used with no JIT compilation at all as a header-only vector library.
How does Dr.Jit differ from JAX, TensorFlow and PyTorch?
The project argues the difference is the workload. Machine learning frameworks optimise smallish graphs of expensive operations such as convolutions, while differentiable rendering produces graphs of 100K to millions of trivial nodes, and ML compilation backends with richer internal representations can crash or time out on those.
What Python version does the Dr.Jit package require?
The package metadata sets requires-python to >=3.10, uses scikit-build-core with nanobind 3.1.0, and depends on typing_extensions only for Python older than 3.11. The build targets the stable ABI so one wheel per platform covers the supported Python versions.
Does Dr.Jit support automatic differentiation and C++ at the same time?
Yes. It computes derivatives with forward or reverse mode automatic differentiation, and Dr.Jit types are accessible in C++17 and Python, where Python and C++ code can be jointly traced and differentiated. The project is the successor of Enoki and its high-level API still resembles Enoki's.
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/mitsuba-renderer-drjit)Was this useful?