MutableArithmetics

Interface for arithmetics on mutable types in Julia

https://github.com/jump-dev/mutablearithmetics.jl

Science Score: 57.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
    Found CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
    Found 8 DOI reference(s) in README
  • Academic publication links
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (10.6%) to scientific vocabulary

Keywords from Contributors

optim automatic-differentiation polynomials interior-point-method unconstrained-optimization unconstrained-optimisation optimisation fluxes precision floating-point
Last synced: 6 months ago · JSON representation ·

Repository

Interface for arithmetics on mutable types in Julia

Basic Info
Statistics
  • Stars: 52
  • Watchers: 3
  • Forks: 10
  • Open Issues: 18
  • Releases: 59
Created over 6 years ago · Last pushed 7 months ago
Metadata Files
Readme License Citation

README.md

MutableArithmetics.jl

Stable Dev Build Status Codecov deps version pkgeval DOI

MutableArithmetics (MA for short) is a Julia package which allows: * for mutable types to implement mutable arithmetics * for algorithms that could exploit mutable arithmetics to exploit them while still being completely generic.

While in some cases, similar features have been included in packages idiosyncratically, the goal of MutableArithmetics is to provide a generic interface to allow anyone to make use of mutability when desired.

The package allows a type to declare itself mutable through the MA.mutability trait. Then the user can use the MA.operate!! function to write generic code that works for arbitrary type while exploiting mutability of the type if possible. More precisely: * The MA.operate!!(op::Function, x, args...) redirects to op(x, args...) if x is not mutable or if the result of the operation cannot be stored in x. Otherwise, it redirects to MA.operate!(op, x, args...). * MA.operate!(op::Function, x, args...) stores the result of the operation in x. It is a MethodError if x is not mutable or if the result of the operation cannot be stored in x.

So from a generic code perspective, MA.operate!! can be used when the value of x is not used anywhere else. This allows the code to both work for mutable and for non-mutable type.

When the type is known to be mutable, MA.operate! can be used to make sure the operation is done in-place. If it is not possible, the MethodError allows one to easily fix the issue while MA.operate!! would have silently fallen back to the non-mutating function.

In conclusion, the distinction between MA.operate!! and MA.operate! covers all use case while having an universal convention accross all operations.

Implementations

The following types and packages implement the MutableArithmetics API:

In addition, the implementation of the following Base functionalities are reimplemented using the MA API: * Matrix-matrix, matrix-vector and array-scalar multiplication including SparseArrays.AbstractSparseArray, LinearAlgebra.Adjoint, LinearAlgebra.Transpose, LinearAlgebra.Symmetric. * Base.sum, LinearAlgebra.dot and LinearAlgebra.diagm.

These methods are reimplemented in this package for several reasons: * The implementation in Base does not exploit the mutability of the type (except for sum(::Vector{BigInt}) which has a specialized method) and are hence much slower. * Some implementations in Base assume the following for the types S, T used satisfy: - typeof(zero(T)) == T, typeof(one(T)) == T, typeof(S + T) == promote_type(S, T) or typeof(S * T) == promote_type(S, T) which is not true for instance if T is a polynomial variable or the decision variable of an optimization model. - The multiplication between elements of type S and T is commutative which is not true for matrices or non-commutative polynomial variables.

The trait defined in this package cannot make the methods for the functions defined in Base to be dispatched to the implementations of this package. For these to be used for a given type, it needs to inherit from MA.AbstractMutable. Not that subtypes of MA.AbstractMutable are not necessarily mutable, for instance, polynomial variables and the decision variable of an optimization model are subtypes of MA.AbstractMutable but are not mutable. The only purpose of this abstract type is to have Base methods to be dispatched to the implementations of this package. See src/dispatch.jl for more details.

Quick Example & Benchmark

```julia using BenchmarkTools using MutableArithmetics const MA = MutableArithmetics

n = 200 A = rand(-10:10, n, n) b = rand(-10:10, n) c = rand(-10:10, n)

MA.mul works for arbitrary types

MA.mul(A, b)

A2 = big.(A) b2 = big.(b) c2 = big.(c) ```

The default implementation LinearAlgebra.generic_matvecmul! does not exploit the mutability of BigInt is quite slow and allocates a lot: ```julia using LinearAlgebra trial = @benchmark LinearAlgebra.mul!($c2, $A2, $b2) display(trial)

output

BenchmarkTools.Trial: 407 samples with 1 evaluation. Range (min … max): 5.268 ms … 161.929 ms ┊ GC (min … max): 0.00% … 73.90% Time (median): 5.900 ms ┊ GC (median): 0.00% Time (mean ± σ): 12.286 ms ± 21.539 ms ┊ GC (mean ± σ): 29.47% ± 14.50%

█▃ ██▄▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▅█▆▇▅▅ ▆ 5.27 ms Histogram: log(frequency) by time 80.6 ms <

Memory estimate: 3.66 MiB, allocs estimate: 197732. ```

In MA.operate!(::typeof(MA.add_mul), ::Vector, ::Matrix, ::Vector), we exploit the mutability of BigInt through the MutableArithmetics API. This provides a significant speedup and a drastic reduction of memory usage: ```julia trial2 = @benchmark MA.add_mul!!($c2, $A2, $b2) display(trial2)

output

BenchmarkTools.Trial: 4878 samples with 1 evaluation. Range (min … max): 908.860 μs … 1.758 ms ┊ GC (min … max): 0.00% … 0.00% Time (median): 1.001 ms ┊ GC (median): 0.00% Time (mean ± σ): 1.021 ms ± 102.381 μs ┊ GC (mean ± σ): 0.00% ± 0.00%

█▅ ██▂▂▂▇▅▇▇▅▅▅▇▅▆▄▄▅▄▄▃▄▄▃▃▂▃▃▂▃▂▂▂▂▂▂▂▂▂▂▂▁▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▂ 909 μs Histogram: frequency by time 1.36 ms <

Memory estimate: 48 bytes, allocs estimate: 3. ```

There is still 48 bytes that are allocated, where does this come from ? MA.operate!(::typeof(MA.add_mul), ::BigInt, ::BigInt, ::BigInt) allocates a temporary BigInt to hold the result of the multiplication. This buffer is allocated only once for the whole matrix-vector multiplication through the system of buffers of MutableArithmetics. If may Matrix-Vector products need to be computed, the buffer can even be allocated outside of the matrix-vector product as follows: ```julia buffer = MA.bufferfor(MA.addmul, typeof(c2), typeof(A2), typeof(b2)) trial3 = @benchmark MA.bufferedoperate!!($buffer, MA.addmul, $c2, $A2, $b2) display(trial3)

output

BenchmarkTools.Trial: 4910 samples with 1 evaluation. Range (min … max): 908.414 μs … 1.774 ms ┊ GC (min … max): 0.00% … 0.00% Time (median): 990.964 μs ┊ GC (median): 0.00% Time (mean ± σ): 1.014 ms ± 103.364 μs ┊ GC (mean ± σ): 0.00% ± 0.00%

█▂ ██▃▂▂▄▄▅▆▃▄▄▅▄▄▃▃▄▃▃▃▃▃▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▂ 908 μs Histogram: frequency by time 1.35 ms <

Memory estimate: 0 bytes, allocs estimate: 0. ``` Note that there are now 0 allocations.

Related projects

For related projects, see:

  • https://github.com/JuliaFolds/BangBang.jl
  • https://github.com/tkluck/InPlace.jl

Citing MutableArithmetics

If you find MutableArithmetics useful in your work, we kindly request that you cite the following paper: bibtex @article{Legat2024, doi = {10.21105/jcon.00093}, url = {https://doi.org/10.21105/jcon.00093}, year = {2024}, publisher = {The Open Journal}, volume = {6}, number = {58}, pages = {93}, author = {Benoît Legat}, title = {MutableArithmetics: An API for mutable operations}, journal = {Proceedings of the JuliaCon Conferences} }

Owner

  • Name: JuMP-dev
  • Login: jump-dev
  • Kind: organization

An organization for the JuMP modeling language and related repositories.

Citation (CITATION.bib)

@article{Legat2024,
  doi = {10.21105/jcon.00093},
  url = {https://doi.org/10.21105/jcon.00093},
  year = {2024},
  publisher = {The Open Journal},
  volume = {6},
  number = {58},
  pages = {93},
  author = {Benoît Legat},
  title = {MutableArithmetics: An API for mutable operations},
  journal = {Proceedings of the JuliaCon Conferences}
}

GitHub Events

Total
  • Create event: 24
  • Commit comment event: 9
  • Release event: 6
  • Issues event: 15
  • Watch event: 2
  • Delete event: 22
  • Issue comment event: 54
  • Push event: 69
  • Pull request event: 32
  • Pull request review event: 6
  • Pull request review comment event: 6
Last Year
  • Create event: 24
  • Commit comment event: 9
  • Release event: 6
  • Issues event: 15
  • Watch event: 2
  • Delete event: 22
  • Issue comment event: 54
  • Push event: 69
  • Pull request event: 32
  • Pull request review event: 6
  • Pull request review comment event: 6

Committers

Last synced: 8 months ago

All Time
  • Total Commits: 316
  • Total Committers: 15
  • Avg Commits per committer: 21.067
  • Development Distribution Score (DDS): 0.44
Past Year
  • Commits: 26
  • Committers: 3
  • Avg Commits per committer: 8.667
  • Development Distribution Score (DDS): 0.192
Top Committers
Name Email Commits
Benoît Legat b****t@g****m 177
Oscar Dowson o****w 105
Neven Sajko s@p****m 11
Gilles Peiffer g****r@o****m 11
Sascha Timme s****e@g****m 2
Ryan Walker 8****r 1
Miles Lubin m****n@g****m 1
Miha Zgubic m****c 1
Max Horn m****x@q****e 1
Kristoffer Carlsson k****9@g****m 1
Julia TagBot 5****t 1
Herman Sletmoen h****n@g****m 1
ExpandingMan s****o@p****m 1
Daniel Karrasch d****h@p****e 1
Benjamin Desef p****r 1
Committer Domains (Top 20 + Academic)

Issues and Pull Requests

Last synced: 6 months ago

All Time
  • Total issues: 74
  • Total pull requests: 146
  • Average time to close issues: 4 months
  • Average time to close pull requests: 13 days
  • Total issue authors: 20
  • Total pull request authors: 12
  • Average comments per issue: 3.35
  • Average comments per pull request: 1.91
  • Merged pull requests: 127
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 10
  • Pull requests: 37
  • Average time to close issues: 2 days
  • Average time to close pull requests: 12 days
  • Issue authors: 6
  • Pull request authors: 4
  • Average comments per issue: 1.4
  • Average comments per pull request: 1.51
  • Merged pull requests: 31
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • odow (17)
  • nsajko (15)
  • blegat (13)
  • matbesancon (5)
  • araujoms (4)
  • joaquimg (3)
  • ShuhuaGao (2)
  • kalmarek (2)
  • mattsignorelli (2)
  • ranocha (1)
  • PallHaraldsson (1)
  • LebedevRI (1)
  • longemen3000 (1)
  • projekter (1)
  • Vilin97 (1)
Pull Request Authors
  • odow (112)
  • blegat (48)
  • nsajko (12)
  • hersle (2)
  • joaquimg (2)
  • projekter (2)
  • kalmarek (1)
  • bowenszhu (1)
  • dkarrasch (1)
  • mzgubic (1)
  • AayushSabharwal (1)
  • araujoms (1)
Top Labels
Issue Labels
bug (9) Type: Performance (8) Type: Bug (4) enhancement (4)
Pull Request Labels
bug (2) breaking (1)

Packages

  • Total packages: 1
  • Total downloads:
    • julia 6,591 total
  • Total dependent packages: 29
  • Total dependent repositories: 0
  • Total versions: 59
juliahub.com: MutableArithmetics

Interface for arithmetics on mutable types in Julia

  • Versions: 59
  • Dependent Packages: 29
  • Dependent Repositories: 0
  • Downloads: 6,591 Total
Rankings
Dependent packages count: 2.7%
Dependent repos count: 9.9%
Average: 11.0%
Stargazers count: 15.0%
Forks count: 16.2%
Last synced: 6 months ago

Dependencies

.github/workflows/TagBot.yml actions
  • JuliaRegistries/TagBot v1 composite
.github/workflows/aqua.yml actions
  • actions/checkout v1 composite
  • julia-actions/setup-julia latest composite
.github/workflows/ci.yml actions
  • actions/cache v1 composite
  • actions/checkout v2 composite
  • codecov/codecov-action v1 composite
  • julia-actions/julia-buildpkg v1 composite
  • julia-actions/julia-processcoverage v1 composite
  • julia-actions/julia-runtest v1 composite
  • julia-actions/setup-julia v1 composite
.github/workflows/documentation.yml actions
  • actions/checkout v2 composite
  • julia-actions/setup-julia latest composite
.github/workflows/downstream.yml actions
  • actions/checkout v2 composite
  • julia-actions/julia-buildpkg latest composite
  • julia-actions/setup-julia v1 composite
.github/workflows/format_check.yml actions
  • actions/checkout v1 composite
  • julia-actions/setup-julia latest composite