https://github.com/clima/multibroadcastfusion.jl
A Julia package for fusing multiple broadcast expressions together
Science Score: 13.0%
This score indicates how likely this project is to be science-related based on various indicators:
-
○CITATION.cff file
-
✓codemeta.json file
Found codemeta.json file -
○.zenodo.json file
-
○DOI references
-
○Academic publication links
-
○Academic email domains
-
○Institutional organization owner
-
○JOSS paper metadata
-
○Scientific vocabulary similarity
Low similarity (7.1%) to scientific vocabulary
Repository
A Julia package for fusing multiple broadcast expressions together
Basic Info
- Host: GitHub
- Owner: CliMA
- License: mit
- Language: Julia
- Default Branch: main
- Size: 94.7 KB
Statistics
- Stars: 11
- Watchers: 2
- Forks: 1
- Open Issues: 13
- Releases: 4
Metadata Files
README.md
MultiBroadcastFusion.jl
A Julia package for fusing multiple broadcast expressions together.
A motivating example of this package is the following:
```julia x1 = rand(3,3) x2 = rand(3,3) x3 = rand(3,3) x4 = rand(3,3) y1 = rand(3,3) y2 = rand(3,3)
2 writes, 4 unique reads, but 8 reads including redundant ones
@. y1 = x1 * x2 + x3 * x4 @. y2 = x1 * x3 + x2 * x4 ```
In this example, there are 4 unique reads, and 2 writes. However, because the reads are in two separate broadcast expressions, there are 8 reads total, including redundant ones. Another important note is that y1 and y2 are stored separately in memory. Fusing these operations can be achieved by changing the memory layout, and adjusting the implementation. For example:
```julia X = map(x->Tuple(rand(4)),zeros(3,3)); Y = map(x->Tuple(rand(2)),zeros(3,3));
foo(x) = (x[1] * x[2] + x[3] * x[4], x[1] * x[3] + x[2] * x[4])
4 reads, 2 writes
@. Y = foo(X) ```
However, this is not an objectively better solution:
- The memory layout, and code implementation, had to be changed in order to make this work, and this can be very difficult for a complex codebase.
- Memory acces of
XandYis now strided, which could result in less performant code than a single fused loop with more contiguous memory.
Ideally, we would like for the loops to be fused with the more contiguous data layouts:
```julia x1 = rand(3,3) x2 = rand(3,3) x3 = rand(3,3) x4 = rand(3,3) y1 = rand(3,3) y2 = rand(3,3)
2 writes, 4 unique reads. The compiler can hoist the redundant memory reads here.
for i in eachindex(x1,x2,x3,x4,y1,y2) y1[i] = x1[i] * x2[i] + x3[i] * x4[i] y2[i] = x1[i] * x3[i] + x2[i] * x4[i] end ```
With this package, we can apply @fused_direct to reduce the number of reads and preserve the memory layout:
```julia import MultiBroadcastFusion as MBF x1 = rand(3,3) x2 = rand(3,3) x3 = rand(3,3) x4 = rand(3,3) y1 = rand(3,3) y2 = rand(3,3)
4 reads, 2 writes
MBF.@fused_direct begin @. y1 = x1 * x2 + x3 * x4 @. y2 = x1 * x3 + x2 * x4 end ```
This is achieved by fusing the loops and inlining with the given data, resulting in the compiler being able to perform Common-SubExpression Elimination (CSE) on the memory loads.
Custom implementations
Users can write custom implementations, using the @make_type and @make_fused macros, and then defining Base.copyto! on the type you've defined
```julia import MultiBroadcastFusion as MBF import MultiBroadcastFusion: fused_direct
MBF.@maketype MyFusedMultiBroadcast MBF.@makefused fuseddirect MyFusedMultiBroadcast myfused
Now, @fused_direct will call Base.copyto!(::MyFusedMultiBroadcast). Let's define it:
function Base.copyto!(fmb::MyFusedMultiBroadcast)
pairs = fmb.pairs
destinations = map(x->x.first, pairs)
@inbounds for i in eachindex(destinations)
# does @inline pair.first[i] = pair.second[i] for all pairs
MBF.rcopyto_at!(pairs, i)
end
return nothing
end
x1 = rand(3,3) x2 = rand(3,3) x3 = rand(3,3) x4 = rand(3,3) y1 = rand(3,3) y2 = rand(3,3)
4 reads, 2 writes
@my_fused begin @. y1 = x1 * x2 + x3 * x4 @. y2 = x1 * x3 + x2 * x4 end ```
Writing custom macros
Users can also write custom macros with, for example,
```julia import MultiBroadcastFusion as MBF
struct FusedMultiBroadcast{T} pairs::T end macro getfusedmultibroadcast(expr) _pairs = gensym() quote $pairs = $(esc(MBF.fuseddirect(expr))) FusedMultiBroadcast($pairs) end end ```
This can be helpful for inspecting multibroadcast objects.
Owner
- Name: Climate Modeling Alliance
- Login: CliMA
- Kind: organization
- Email: clima@caltech.edu
- Website: https://clima.caltech.edu
- Repositories: 67
- Profile: https://github.com/CliMA
An alliance of scientists, engineers and applied mathematicians, dedicated to pioneering a new, data-informed approach to climate modeling
GitHub Events
Total
- Create event: 4
- Commit comment event: 2
- Issues event: 7
- Watch event: 3
- Issue comment event: 7
- Push event: 11
- Pull request event: 4
- Fork event: 1
Last Year
- Create event: 4
- Commit comment event: 2
- Issues event: 7
- Watch event: 3
- Issue comment event: 7
- Push event: 11
- Pull request event: 4
- Fork event: 1
Packages
- Total packages: 1
-
Total downloads:
- julia 94 total
- Total dependent packages: 1
- Total dependent repositories: 0
- Total versions: 7
juliahub.com: MultiBroadcastFusion
A Julia package for fusing multiple broadcast expressions together
- Documentation: https://docs.juliahub.com/General/MultiBroadcastFusion/stable/
- License: MIT
-
Latest release: 0.3.3
published over 1 year ago
Rankings
Dependencies
- actions/checkout v4 composite
- codecov/codecov-action v3 composite
- julia-actions/setup-julia latest composite
- actions/checkout v4 composite
- dorny/paths-filter v2 composite
- julia-actions/setup-julia latest composite
- styfle/cancel-workflow-action 0.4.0 composite
- JuliaRegistries/TagBot v1 composite
- actions/cache v1 composite
- actions/checkout v4 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
- actions/checkout v4 composite
- julia-actions/julia-buildpkg v1 composite
- julia-actions/julia-invalidations v1 composite
- julia-actions/setup-julia v1 composite