-
Notifications
You must be signed in to change notification settings - Fork 122
Open
Description
using SymbolicUtils
Threads.nthreads()
SymbolicUtils.ENABLE_HASHCONSING[] = false
function testfunc()
@syms x::Number y::Number f(::Number)::Number
e1 = f(x) + y
e2 = f(cos(x)) + e1^2
e3 = sin(e2)
substitute(e3, Dict(f(x)=>2))
end
# Threads without hash consing: works!
@Threads.threads for i in 1:100
testfunc()
end
SymbolicUtils.ENABLE_HASHCONSING[] = true
# Hash consing without threads: works!
empty!(SymbolicUtils.wvd)
for i in 1:100
testfunc()
end
# Hash consing with threads: exceptions or segfaults! May need to run more than once.
empty!(SymbolicUtils.wvd)
@Threads.threads for i in 1:100
testfunc()
end
I have a guess at what might be going wrong. It looks like the code in arguments()
here initializes the arguments vector without any locking. Hash consing might mean that two threads with apparently independently-defined symbols with the same content now call arguments
on the same newly-initialized symbolic struct at the same time, so the arguments list could get clobbered.
An example exception:
ERROR: TaskFailedException
nested task error: UndefRefError: access to undefined reference
Stacktrace:
[1] getindex
@ ./essentials.jl:13 [inlined]
[2] iterate
@ ./array.jl:945 [inlined]
[3] _foldl_impl
@ ./reduce.jl:60 [inlined]
[4] foldl_impl
@ ./reduce.jl:48 [inlined]
[5] mapfoldl_impl(f::typeof(SymbolicUtils.symtype), op::SymbolicUtils.var"#37#38"{…}, nt::Base._InitialValue, itr::Vector{…})
@ Base ./reduce.jl:44
[6] mapfoldl(f::Function, op::Function, itr::Vector{SymbolicUtils.BasicSymbolic{Number}}; init::Base._InitialValue)
@ Base ./reduce.jl:175
[7] mapfoldl
@ ./reduce.jl:175 [inlined]
[8] _promote_symtype(f::Function, args::Vector{SymbolicUtils.BasicSymbolic{Number}})
@ SymbolicUtils ~/.julia/packages/SymbolicUtils/2cE5G/src/types.jl:1181
[9] maketerm(T::Type{…}, head::Function, args::Vector{…}, metadata::Nothing)
@ SymbolicUtils ~/.julia/packages/SymbolicUtils/2cE5G/src/types.jl:777
[10] substitute(expr::SymbolicUtils.BasicSymbolic{Number}, dict::Dict{SymbolicUtils.BasicSymbolic{…}, Int64}; fold::Bool)
@ SymbolicUtils ~/.julia/packages/SymbolicUtils/2cE5G/src/substitute.jl:34
[11] substitute
@ ~/.julia/packages/SymbolicUtils/2cE5G/src/substitute.jl:16 [inlined]
[12] (::SymbolicUtils.var"#343#345"{Bool, Dict{…}})(x::SymbolicUtils.BasicSymbolic{Number})
@ SymbolicUtils ~/.julia/packages/SymbolicUtils/2cE5G/src/substitute.jl:24
[13] iterate
@ ./generator.jl:47 [inlined]
[14] _collect(c::Vector{…}, itr::Base.Generator{…}, ::Base.EltypeUnknown, isz::Base.HasShape{…})
@ Base ./array.jl:854
[15] collect_similar
@ ./array.jl:763 [inlined]
[16] map
@ ./abstractarray.jl:3286 [inlined]
[17] substitute(expr::SymbolicUtils.BasicSymbolic{Number}, dict::Dict{SymbolicUtils.BasicSymbolic{…}, Int64}; fold::Bool)
@ SymbolicUtils ~/.julia/packages/SymbolicUtils/2cE5G/src/substitute.jl:23
[18] substitute(expr::SymbolicUtils.BasicSymbolic{Number}, dict::Dict{SymbolicUtils.BasicSymbolic{Number}, Int64})
@ SymbolicUtils ~/.julia/packages/SymbolicUtils/2cE5G/src/substitute.jl:16
[19] macro expansion
@ ./REPL[1]:8 [inlined]
[20] (::var"#9#threadsfor_fun#12"{var"#9#threadsfor_fun#11#13"{UnitRange{Int64}}})(tid::Int64; onethread::Bool)
@ Main ./threadingconstructs.jl:215
[21] #9#threadsfor_fun
@ ./threadingconstructs.jl:182 [inlined]
[22] (::Base.Threads.var"#1#2"{var"#9#threadsfor_fun#12"{var"#9#threadsfor_fun#11#13"{UnitRange{Int64}}}, Int64})()
@ Base.Threads ./threadingconstructs.jl:154
...and 1 more exception.
Stacktrace:
[1] threading_run(fun::var"#9#threadsfor_fun#12"{var"#9#threadsfor_fun#11#13"{UnitRange{Int64}}}, static::Bool)
@ Base.Threads ./threadingconstructs.jl:172
[2] macro expansion
@ ./threadingconstructs.jl:220 [inlined]
[3] top-level scope
@ ./REPL[1]:7
Some type information was truncated. Use `show(err)` to see complete types.
Metadata
Metadata
Assignees
Labels
No labels