https://github.com/fluxml/mjolnir.jl
A little less conversation, a little more abstraction
https://github.com/fluxml/mjolnir.jl
Last synced: 3 months ago
JSON representation
A little less conversation, a little more abstraction
- Host: GitHub
- URL: https://github.com/fluxml/mjolnir.jl
- Owner: FluxML
- License: other
- Created: 2020-03-03T17:13:19.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2021-12-10T20:14:10.000Z (over 4 years ago)
- Last Synced: 2026-03-04T22:03:05.667Z (4 months ago)
- Language: Julia
- Homepage:
- Size: 169 KB
- Stars: 87
- Watchers: 20
- Forks: 13
- Open Issues: 17
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
⚠️ This project was experimental and is not currently maintained. It may be picked up at some point in the future, but for now it is both incomplete and likely non-functional on newer versions of Julia. For a discussion of why development has not continued, see [this thread](https://github.com/FluxML/Mjolnir.jl/pull/34#issuecomment-952526860).
# Mjolnir
[](https://travis-ci.org/FluxML/Mjolnir.jl)
[](https://github.com/SciML/ColPrac)
Mjolnir is a hybrid approach to partial evaluation / abstract interpretation,
with an implementation in Julia. It can be thought of as a blend of
operator-overloading based tracing (as in JAX, PyTorch Script, staged
programming systems etc.) and dataflow-based abstract interpretation (as in the
type inference systems of Julia, TypeScript and Crystal). It is aimed at package
developers rather than Julia end-users.
Mjolnir can reproduce the compact, linear traces (aka computation graphs or
Wengert lists) of tracing systems.
```julia
julia> function pow(x, n)
r = 1
while n > 0
n -= 1
r *= x
end
return r
end
pow (generic function with 1 method)
julia> using Mjolnir
julia> @trace pow(::Int, 3)
1: (%1 :: const(pow), %2 :: Int64, %3 :: const(3))
%4 = (*)(1, %2) :: Int64
%5 = (*)(%4, %2) :: Int64
%6 = (*)(%5, %2) :: Int64
return %6
```
However, it avoids several of the downsides of those systems. It supports
arbitrary Julia types (not just 'tensors' but also strings and structs). It
supports value-dependent control flow (as it can encode branches in the trace).
It supports side effects and mutating operators. Functions like `println` don't
have to be evaluated at compile time. It can enforce its assumptions (i.e.
referential transparency) rather than making the user responsible for them, and
can generate diagnostics when there are issues. Mjolnir can thus compile a much
wider range of Julia programs than OO approaches.
```julia
julia> @trace pow(::Int, ::Int)
1: (%1 :: const(pow), %2 :: Int64, %3 :: Int64)
%4 = (>)(%3, 0) :: Bool
br 3 (1) unless %4
br 2 (%3, 1)
2: (%5 :: Int64, %6 :: Int64)
%7 = (-)(%5, 1) :: Int64
%8 = (*)(%6, %2) :: Int64
%9 = (>)(%7, 0) :: Bool
br 3 (%8) unless %9
br 2 (%7, %8)
3: (%10 :: Int64)
return %10
```
```julia
julia> function pow(x, n)
r = 1
while n > 0
n -= 1
r *= x
@show r
end
return r
end
pow (generic function with 1 method)
julia> @trace pow(2, 3)
1: (%1 :: const(pow), %2 :: const(2), %3 :: const(3))
%4 = (println)("r = ", "2") :: Nothing
%5 = (println)("r = ", "4") :: Nothing
%6 = (println)("r = ", "8") :: Nothing
return 8
```
Mjolnir is designed to be [highly
customisable](https://github.com/MikeInnes/Mjolnir.jl/blob/master/docs/types.md),
and to give as much control as possible to packages that build on it.