-
Notifications
You must be signed in to change notification settings - Fork 14
n2tiled-improved-scaling-on-multithread #252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
HarshitNagpal29
wants to merge
8
commits into
JuliaHEP:main
Choose a base branch
from
HarshitNagpal29:n2tiled-production-workspace
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
dd20123
n2tiled-improved-scaling-on-multithread
HarshitNagpal29 46d7822
Apply JuliaFormatter
HarshitNagpal29 9926f63
fix formatting
m-fila 21a33a3
polishing changes
HarshitNagpal29 493995d
adding test file
HarshitNagpal29 8c98ee2
implementing-suggestions
HarshitNagpal29 8991c9a
fixing codecv issue
HarshitNagpal29 b51be3b
final changes
HarshitNagpal29 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| #! /usr/bin/env julia | ||
|
|
||
| """ | ||
| Process independent events concurrently with one reusable N2Tiled workspace | ||
| owned by each long-lived worker task. | ||
|
|
||
| Run with, for example: | ||
|
|
||
| ```sh | ||
| julia --threads=auto --project=examples examples/n2tiled-multithreaded.jl \ | ||
| --maxevents=100 test/data/events.pp13TeV.hepmc3.zst | ||
| ``` | ||
| """ | ||
|
|
||
| using ArgParse | ||
| using JetReconstruction | ||
| using LorentzVectorHEP | ||
|
|
||
| """ | ||
| threaded_n2tiled_reconstruction(events; R=0.4, ptmin=5.0) | ||
|
|
||
| Reconstruct `events` using dynamically scheduled worker tasks. Each worker owns | ||
| one `N2TiledWorkspace`; only independently owned inclusive-jet selections are | ||
| stored after the callback returns. | ||
| """ | ||
| function threaded_n2tiled_reconstruction(events; | ||
| R::Real = 0.4, | ||
| ptmin::Real = 5.0) | ||
| selected_jets = Vector{Vector{LorentzVector{Float64}}}(undef, length(events)) | ||
| isempty(events) && return selected_jets | ||
|
|
||
| nworkers = min(Threads.nthreads(), length(events)) | ||
|
|
||
| # A shared channel balances events dynamically. Workspaces belong to the | ||
| # tasks below rather than to thread IDs, so task migration is safe. | ||
| jobs = Channel{Int}(length(events)) | ||
| for event_index in eachindex(events) | ||
| put!(jobs, event_index) | ||
| end | ||
| close(jobs) | ||
|
|
||
| @sync for _ in 1:nworkers | ||
| Threads.@spawn begin | ||
| workspace = N2TiledWorkspace() | ||
|
|
||
| for event_index in jobs | ||
| selected_jets[event_index] = with_n2tiled_reconstruction(workspace, | ||
| events[event_index]; | ||
| algorithm = JetAlgorithm.AntiKt, | ||
| R = R,) do clusterseq | ||
| # `inclusive_jets` returns an independently owned vector. | ||
| # Use `deepcopy(clusterseq)` here instead when the complete | ||
| # clustering sequence must outlive this callback. | ||
| inclusive_jets(clusterseq; ptmin = ptmin) | ||
| end | ||
| end | ||
| end | ||
| end | ||
|
|
||
| return selected_jets | ||
| end | ||
|
|
||
| function parse_command_line(args) | ||
| settings = ArgParseSettings(autofix_names = true) | ||
| @add_arg_table! settings begin | ||
| "--maxevents", "-n" | ||
| help = "Maximum number of events to read; -1 reads all events." | ||
| arg_type = Int | ||
| default = -1 | ||
|
|
||
| "--ptmin" | ||
| help = "Minimum transverse momentum for inclusive jets." | ||
| arg_type = Float64 | ||
| default = 5.0 | ||
|
|
||
| "--distance", "-R" | ||
| help = "Jet radius parameter." | ||
| arg_type = Float64 | ||
| default = 0.4 | ||
|
|
||
| "file" | ||
| help = "HepMC3 event file to read." | ||
| required = true | ||
| end | ||
|
|
||
| return parse_args(args, settings; as_symbols = true) | ||
| end | ||
|
|
||
| function main(args = ARGS) | ||
| options = parse_command_line(args) | ||
| events = read_final_state_particles(options[:file], PseudoJet; | ||
| maxevents = options[:maxevents]) | ||
|
|
||
| selected_jets = threaded_n2tiled_reconstruction(events; | ||
| R = options[:distance], | ||
| ptmin = options[:ptmin]) | ||
|
|
||
| println("Processed $(length(events)) events with $(Threads.nthreads()) Julia threads; " * | ||
| "selected $(sum(length, selected_jets)) jets.") | ||
|
|
||
| return nothing | ||
| end | ||
|
|
||
| if abspath(PROGRAM_FILE) == @__FILE__ | ||
| main() | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,22 @@ const NonexistentParent = -2 | |
| "Cluster recombined with beam" | ||
| const BeamJet = -1 | ||
|
|
||
| # Julia 1.11 introduced the `shrink` keyword for `sizehint!`. Disable shrinking | ||
| # when that keyword is available. Older Julia versions have no public no-shrink | ||
| # sizehint API, so leave their capacity untouched and let `resize!`/`push!` grow | ||
| # it as needed. | ||
| @inline function _sizehint_for_reuse!(buffer::Vector, | ||
| requested::Integer) | ||
| requested >= 0 || | ||
| throw(ArgumentError("requested capacity must be non-negative, got $requested")) | ||
|
|
||
| @static if VERSION >= v"1.11" | ||
| sizehint!(buffer, requested; shrink = false) | ||
| end | ||
|
|
||
| return buffer | ||
| end | ||
|
|
||
| """ | ||
| struct HistoryElement | ||
|
|
||
|
|
@@ -69,35 +85,53 @@ function HistoryElement(jetp_index) | |
| end | ||
|
|
||
| """ | ||
| initial_history(particles) | ||
| initial_history!( | ||
| history::Vector{HistoryElement}, | ||
| particles, | ||
| ) | ||
|
|
||
| Create an initial history for the given particles. | ||
| Reset and initialise reusable clustering-history storage for `particles`. | ||
|
|
||
| # Arguments | ||
| - `particles`: The initial vector of stable particles. | ||
| The vector's logical length is reset to the number of initial particles while | ||
| retaining any capacity already owned by the vector. | ||
|
|
||
| # Returns | ||
| - `history`: An array of `HistoryElement` objects. | ||
| - `Qtot`: The total energy in the event. | ||
| The returned history vector is borrowed storage owned by the caller. | ||
| """ | ||
| function initial_history(particles) | ||
| # reserve sufficient space for everything | ||
| history = Vector{HistoryElement}(undef, length(particles)) | ||
| sizehint!(history, 2 * length(particles)) | ||
| function initial_history!(history::Vector{HistoryElement}, | ||
| particles) | ||
| N = length(particles) | ||
|
|
||
| Qtot::Float64 = 0 | ||
| # Establish exactly N active initial-history slots. All slots are | ||
| # overwritten below, and `resize!` retains any existing excess capacity. | ||
| resize!(history, N) | ||
|
|
||
| for i in eachindex(particles) | ||
| Qtot::Float64 = 0.0 | ||
|
|
||
| @inbounds for i in eachindex(particles) | ||
| history[i] = HistoryElement(i) | ||
|
|
||
| # get cross-referencing right from the Jets | ||
| # particles[i]._cluster_hist_index = i | ||
| @assert cluster_hist_index(particles[i])==i "Cluster history index should match jet's index in the input vector. Expected $(i), got $(cluster_hist_index(particles[i]))" | ||
| @assert cluster_hist_index(particles[i])==i ("Cluster history index should match jet's index in the input vector. "* | ||
| "Expected $(i), got $(cluster_hist_index(particles[i]))") | ||
|
|
||
| # determine the total energy in the event | ||
| Qtot += particles[i].E | ||
| end | ||
| history, Qtot | ||
|
|
||
| return history, Qtot | ||
| end | ||
|
|
||
| """ | ||
| initial_history(particles) | ||
|
|
||
| Create independently owned initial clustering-history storage. | ||
| """ | ||
| function initial_history(particles) | ||
| # This is newly owned storage, so requesting the complete sequence size | ||
| # cannot discard reusable capacity. Preserve the original eager allocation | ||
| # on Julia versions that do not support `sizehint!(...; shrink=false)`. | ||
| history = Vector{HistoryElement}(undef, length(particles)) | ||
| sizehint!(history, 2 * length(particles)) | ||
|
|
||
| return initial_history!(history, particles) | ||
| end | ||
|
|
||
| """ | ||
|
|
@@ -216,29 +250,20 @@ function add_step_to_history!(clusterseq::ClusterSequence, parent1, parent2, jet | |
| end | ||
|
|
||
| """ | ||
| inclusive_jets(clusterseq::ClusterSequence{U}, ::Type{T} = LorentzVectorCyl{Float64}; ptmin = 0.0) where {T, U} | ||
| inclusive_jets( | ||
| clusterseq::ClusterSequence{U}, | ||
| ::Type{T}=LorentzVector{Float64}; | ||
| ptmin=0.0, | ||
| ) | ||
|
|
||
| Return all inclusive jets of a ClusterSequence with pt > ptmin. | ||
| Return all inclusive jets of a `ClusterSequence` with transverse momentum | ||
| greater than or equal to `ptmin`. | ||
|
|
||
| # Arguments | ||
| - `clusterseq::ClusterSequence`: The `ClusterSequence` object containing the | ||
| clustering history and jets. | ||
| - `::Type{T} = LorentzVectorCyl{Float64}`: The return type used for the selected jets. | ||
| - `ptmin::Float64 = 0.0`: The minimum transverse momentum (pt) threshold for the | ||
| inclusive jets. | ||
|
|
||
| # Returns | ||
| An array of `T` objects representing the inclusive jets. | ||
|
|
||
| # Description | ||
| This function computes the inclusive jets from a given `ClusterSequence` object. | ||
| It iterates over the clustering history and checks the transverse momentum of | ||
| each parent jet. If the transverse momentum is greater than or equal to `ptmin`, | ||
| the jet is added to the array of inclusive jets. | ||
| Valid return types are `LorentzVector`, `LorentzVectorCyl`, or the jet type of | ||
| the input `clusterseq` (`U`, either `PseudoJet` or `EEJet` depending on the | ||
| algorithm). | ||
|
|
||
| Valid return types are `LorentzVector` `LorentzVectorCyl` or the jet type of the | ||
| input `clusterseq` (`U` - either `PseudoJet` or `EEJet` depending which | ||
| algorithm was used). | ||
| The returned vector is independently owned. | ||
|
Comment on lines
252
to
+266
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since there are no changes to |
||
|
|
||
| # Example | ||
| ```julia | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would here add an example or a link to a parallel processing example - that's the main use case that we envisage.