Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
758ff95
Fix `@always_everywhere` not running on current worker processes
oschulz Jul 10, 2026
ecaca51
Fix deprecation replacements for workpartition and threadpartition
oschulz Jul 10, 2026
407fc6d
Fix read! on LockableIO forwarding to read instead of read!
oschulz Jul 10, 2026
41d13e6
Fix @onthreads for non-contiguous thread selections
oschulz Jul 10, 2026
2adde6f
Fix duplicated Julia flags in SLURM and HTCondor worker commands
oschulz Jul 10, 2026
2135e4e
Fix worker occupancy accounting in take!(::FlexWorkerPool)
oschulz Jul 10, 2026
56b403a
Fix missing hard_limit default in non-Linux memory_limit!
oschulz Jul 10, 2026
8130a67
Rename write_files keyword cache_dirname to cache_dir
oschulz Jul 10, 2026
eb9bff8
Minor cleanups: log interpolation, dead code
oschulz Jul 10, 2026
288a550
Fix docstrings and log messages
oschulz Jul 10, 2026
99d04ac
Expand test coverage
oschulz Jul 10, 2026
e9840aa
Expand test coverage further
oschulz Jul 10, 2026
32c37dc
Compute default addprocs parameters at runtime
oschulz Jul 10, 2026
c2f4ab4
Use @async instead of Threads.@async
oschulz Jul 10, 2026
88e18e1
Remove unreachable branch in _slurm_parse_shortopt
oschulz Jul 10, 2026
4844a0e
Remove stale test_readme_examples.jl
oschulz Jul 10, 2026
9e21c28
Support interactive threadpools in allthreads and ThreadLocal
oschulz Jul 10, 2026
acbf49f
Keep write_files test files in the test tempdir
oschulz Jul 10, 2026
2dd637f
Increase package version to v0.4.11
oschulz Jul 10, 2026
36c7150
Parse SLURM/HTCondor memory sizes as Int64
oschulz Jul 10, 2026
425382a
Pass explicit pattern to block-form @test_deprecated uses
oschulz Jul 10, 2026
9a57094
Detect method ambiguities recursively in submodules
oschulz Jul 10, 2026
eb3425f
Fix classic_addprocs ignoring its argument
oschulz Jul 10, 2026
99e50fd
Restructure the onworker retry engine
oschulz Jul 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "ParallelProcessingTools"
uuid = "8e8a01fc-6193-5ca1-a2f1-20776dae4199"
version = "0.4.10"
version = "0.4.11"

[deps]
ArgCheck = "dce04be8-c92d-5529-be00-80e4d2c0e197"
Expand Down
2 changes: 1 addition & 1 deletion ext/ParallelProcessingToolsThreadPinningExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -200,4 +200,4 @@ ThreadPinning.pinthreads(::ParallelProcessingTools.AutoThreadPinning) = nothing
end # if _threadpinning_supported


end # module ChangesOfVariablesInverseFunctionsExt
end # module ParallelProcessingToolsThreadPinningExt
8 changes: 4 additions & 4 deletions src/display.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@ const _g_unicode_occupancy = (


"""
ParallelProcessingTools.in_vscode_notebook():Bool
ParallelProcessingTools.in_vscode_notebook()::Bool

Test if running within a Visual Studio Code notebook.
"""
in_vscode_notebook() = haskey(ENV, "VSCODE_CWD")


"""
ParallelProcessingTools.printover(f_show::Function, io::IOBuffer)
ParallelProcessingTools.printover(f_show::Function, io::IO)

Runs `f_show(tmpio)` with an IO buffer, then clears the required number of
lines on `io` (typically `stdout`) and prints the output over them.
Runs `f_show(tmpio)` with a temporary IO buffer, then clears the required
number of lines on `io` (typically `stdout`) and prints the output over them.
"""
function printover(f_show, io)
vscode_nb_mode = in_vscode_notebook()
Expand Down
7 changes: 3 additions & 4 deletions src/exceptions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,8 @@ original_exception(err::RemoteException) = original_exception(err.captured.ex)
"""
ParallelProcessingTools.onlyfirst_exception(err)

Replaces `CompositeException`s with their first exception.

Also employs `inner_exception` if `simplify` is `true`.
Replaces `CompositeException`s with their first exception. Leaves other
exceptions unchanged.
"""
function onlyfirst_exception end
export onlyfirst_exception
Expand All @@ -54,7 +53,7 @@ If multiple exceptions originate from parallel code in `expr`, only one
is rethrown, and `TaskFailedException`s and `RemoteException`s are replaced
by the original exceptions that caused them.

See [`inner_exception`] and [`onlyfirst_exception`](@ref).
See [`inner_exception`](@ref) and [`onlyfirst_exception`](@ref).
"""
macro userfriendly_exceptions(expr)
quote
Expand Down
30 changes: 15 additions & 15 deletions src/fileio.jl
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ end
ParallelProcessingTools.default_cache_dir()::String

Returns the default cache directory, e.g. for [`write_files`](@ref) and
`read_files`(@ref).
[`read_files`](@ref).

See also [`default_cache_dir!`](@ref).
"""
Expand All @@ -114,7 +114,7 @@ end

Sets the default cache directory to `dir` and returns it.

See also [`default_cache_dir!`](@ref).
See also [`default_cache_dir`](@ref).
"""
function default_cache_dir!(dir::AbstractString)
lock(_g_default_cachedir_lock) do
Expand Down Expand Up @@ -180,8 +180,8 @@ _should_overwrite_if_necessary(::CreateOrIgnore) = false
"""
CreateNew() isa WriteMode

Indicates that new files should be created and to throw and eror if the files
already exist.
Indicates that new files should be created and that an error should be thrown
if the files already exist.

See [`WriteMode`](@ref) and [`write_files`](@ref).
"""
Expand All @@ -190,7 +190,7 @@ export CreateNew

function _already_done(::CreateNew, target_fnames::AbstractVector{<:String}, any_pre_existing::Bool, all_pre_existing::Bool, loglevel::LogLevel)
if any_pre_existing
throw(ErrorException("Some, but not all of $target_fnames exist, but not allowed to replace files"))
throw(ErrorException("Some or all of $target_fnames exist already, but not allowed to replace files"))
else
return false
end
Expand Down Expand Up @@ -220,7 +220,7 @@ _should_overwrite_if_necessary(::CreateOrReplace) = true


"""
CreateOrIgnore() isa WriteMode
CreateOrModify() isa WriteMode

Indicates that either new files should be created, or that existing files
should be modified.
Expand Down Expand Up @@ -279,7 +279,7 @@ write to.
With `ftw::FilesToWrite`, use `collect(ftw)` or `iterate(ftw)` to access the
filenames to write to. Use `close(ftw)` or `close(ftw, true)` to close things
in good order, indicating success, and use `close(ftw, false)` or
`close(ftw, err:Exception)` to abort, indicating failure.
`close(ftw, err::Exception)` to abort, indicating failure.

See [`write_files`](@ref) for example code.

Expand Down Expand Up @@ -436,9 +436,9 @@ on the OS and file-system used).
[`ModifyExisting()`](@ref).

If a writing function `f_write` is given, calls
`f_create(temporary_filenames...)`. If `f_create` doesn't throw an exception,
`f_write(temporary_filenames...)`. If `f_write` doesn't throw an exception,
the files `temporary_filenames` are renamed to `filenames`, otherwise
the temporary files are are either deleted (if `delete_tmp_onerror` is `true)
the temporary files are either deleted (if `delete_tmp_onerror` is `true`)
or left in place (e.g. for debugging purposes).

Set `ENV["JULIA_DEBUG"] = "ParallelProcessingTools"` to see a log of all
Expand All @@ -457,7 +457,7 @@ end
files were (re-)written or `nothing` if there was nothing to do (depending
on `mode`).

If no writing funcion `f_write` is given then, `write_files` returns an object
If no writing function `f_write` is given then, `write_files` returns an object
of type [`FilesToWrite`](@ref) that holds the temporary filenames. Closing it
will, like above, either rename temporary files to `filenames` or remove them.
So
Expand Down Expand Up @@ -524,15 +524,15 @@ end
function write_files(
@nospecialize(filenames::AbstractString...);
mode::WriteMode = CreateOrIgnore(),
use_cache::Bool = false, @nospecialize(cache_dirname::AbstractString = default_cache_dir()),
use_cache::Bool = false, @nospecialize(cache_dir::AbstractString = default_cache_dir()),
create_dirs::Bool = true, delete_tmp_onerror::Bool=true,
verbose::Bool = false
)
isempty(filenames) && return nothing

loglevel = verbose ? Info : Debug

cache_dir = String(cache_dirname) # Fix type
cache_dir = String(cache_dir) # Fix type
target_fnames = String[filenames...] # Fix type
staging_fnames = String[]
cache_fnames = String[]
Expand Down Expand Up @@ -643,9 +643,9 @@ function Base.close(ftr::FilesToRead, @nospecialize(reason::Union{Bool,Exception
ftr._isopen[] = false

if reason == true
# @debug "Reading from to $(ftr._source_fnames) was indicated to have succeeded."
# @debug "Reading from $(ftr._source_fnames) was indicated to have succeeded."
elseif reason == false
@debug "Reading from to $(ftr._source_fnames) was indicated to have failed."
@debug "Reading from $(ftr._source_fnames) was indicated to have failed."
else
@debug "Aborted reading from $(ftr._source_fnames) due to exception:" reason
end
Expand Down Expand Up @@ -704,7 +704,7 @@ result = read_files("foo.txt", "bar.txt", use_cache = true) do foo, bar
end
```

If no reading funcion `f_read` is given, then `read_files` returns an object
If no reading function `f_read` is given, then `read_files` returns an object
of type [`FilesToRead`](@ref) that holds the temporary filenames. Closing it
will clean up temporary files, like described above. So

Expand Down
2 changes: 1 addition & 1 deletion src/htcondor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function _generate_condor_worker_script(filename, runmode::OnHTCondor, manager::
additional_julia_flags = `$jl_threads_flag $jl_heap_size_hint_flag $julia_flags`
worker_cmd = worker_local_startcmd(
manager;
julia_flags = `$julia_flags $additional_julia_flags`,
julia_flags = additional_julia_flags,
redirect_output = runmode.redirect_output, env = runmode.env
)
depot_path = join(runmode.julia_depot, ":")
Expand Down
8 changes: 4 additions & 4 deletions src/localhost.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ Example:
runmode = OnLocalhost(n = 4)
task, n = runworkers(runmode)

Threads.@async begin
@async begin
wait(task)
@info "SLURM workers have terminated."
@info "Local workers have terminated."
end

@wait_while nprocs()-1 < n)
@wait_while nprocs()-1 < n
```

Workers can also be started manually, use
Expand Down Expand Up @@ -56,7 +56,7 @@ end
function runworkers(runmode::OnLocalhost, manager::ElasticManager)
start_cmd, m, n = worker_start_command(runmode, manager)

task = Threads.@async begin
task = @async begin
processes = Base.Process[]
for _ in 1:m
push!(processes, open(start_cmd))
Expand Down
4 changes: 2 additions & 2 deletions src/memory.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Values of `-1` mean unlimited.

!!! note
Currently only works on Linux, simply returns `(Int64(-1), Int64(-1))` on
other operationg systems.
other operating systems.
"""
function memory_limit end
export memory_limit
Expand Down Expand Up @@ -75,5 +75,5 @@ export memory_limit!
return rlim[].cur, rlim[].max
end
else
memory_limit!(soft_limit::Integer, hard_limit::Integer) = Int64(-1), Int64(-1)
memory_limit!(soft_limit::Integer, hard_limit::Integer = Int64(-1)) = Int64(-1), Int64(-1)
end
27 changes: 14 additions & 13 deletions src/onthreads.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ end

# Adapted from Julia PR 32477:
function _threading_run(func, threadsel::AbstractVector{<:Integer})
tasks = Vector{Task}(undef, length(eachindex(threadsel)))
for tid in threadsel
i = firstindex(tasks) + (tid - first(threadsel))
tasks = Vector{Task}(undef, length(threadsel))
for (i, tid) in enumerate(threadsel)
tasks[i] = _run_on(Task(func), tid)
end
foreach(wait, tasks)
Expand Down Expand Up @@ -52,9 +51,12 @@ end
"""
allthreads()

Convencience function, returns an equivalent of `1:Base.Threads.nthreads()`.
Returns the thread IDs of all threads in the default threadpool.

Returns an equivalent of `1:Base.Threads.nthreads()` if no interactive
threads are present.
"""
allthreads() = Base.OneTo(Base.Threads.nthreads())
allthreads() = Threads.threadpooltids(:default)
export allthreads


Expand All @@ -65,11 +67,11 @@ Execute code in `expr` in parallel on the threads in `threadsel`.

`threadsel` should be a single thread-ID or a range (or array) of thread-ids.
If `threadsel == Base.Threads.threadid()`, `expr` is run on the current
tread with only minimal overhead.
thread with only minimal overhead.

Example 1:

```juliaexpr
```julia
tlsum = ThreadLocal(0.0)
data = rand(100)
@onthreads allthreads() begin
Expand All @@ -81,13 +83,13 @@ sum(getallvalues(tlsum)) ≈ sum(data)
Example 2:

```julia
# Assuming 4 threads:
# Assuming 4 threads in the default threadpool:
tl = ThreadLocal(42)
threadsel = 2:3
threadsel = allthreads()[2:3]
@onthreads threadsel begin
tl[] = Base.Threads.threadid()
end
getallvalues(tl)[threadsel] == [2, 3]
getallvalues(tl)[2:3] == threadsel
getallvalues(tl)[[1,4]] == [42, 42]
```
"""
Expand All @@ -99,7 +101,6 @@ export @onthreads

function ThreadLocal{T}(f::Base.Callable) where {T}
result = ThreadLocal{T}(undef)
result.value
@onthreads allthreads() result.value[threadid()] = f()
result
end
Expand All @@ -115,12 +116,13 @@ multi-threaded tasks.

Example:

```
```julia
@mt_out_of_order begin
a = foo()
bar()
c = baz()
end
```

will run `a = foo()`, `bar()` and `c = baz()` in parallel and in arbitrary
order, results of assignments will appear in the outside scope.
Expand All @@ -145,7 +147,6 @@ macro mt_out_of_order(ex)
exprs[i] = esc(exprs[i])
end
elseif exprs[i] isa Expr
ftvar = gensym()
exprs[i] = :(push!($tasks, Base.Threads.@spawn($(esc(exprs[i])))))
push!(handle_results, :(wait(popfirst!($tasks))))
else
Expand Down
Loading
Loading