diff --git a/HISTORY.md b/HISTORY.md index 621c0856e..d290d5996 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,9 @@ +# 0.42.4 + +`arraydist` on a vector of univariate distributions now builds its `Distributions.Product` through the inner constructor instead of `Product(dists)`, which is deprecated. The outer constructor calls `Base.depwarn`, and that walks a backtrace on every call, so models with an `arraydist` likelihood paid it once per evaluation. The return type is unchanged. + +This restores the behaviour of the DistributionsAD implementation, which used the inner constructor for the same reason before `arraydist` moved here in 0.40.4. + # 0.42.3 Worked around an upstream Julia code-generation bug that, under concurrent allocation load, could crash the model re-evaluation performed by `ParamsWithStats`. The affected re-evaluation is now routed through an internal function barrier that avoids the miscompilation; behaviour is unchanged. The crash was originally reported in [AbstractMCMC.jl#214](https://github.com/TuringLang/AbstractMCMC.jl/issues/214). diff --git a/Project.toml b/Project.toml index 569a16fc9..f8891bc3a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "DynamicPPL" uuid = "366bfd00-2699-11ea-058f-f148b4cae6d8" -version = "0.42.3" +version = "0.42.4" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" diff --git a/src/distribution_wrappers.jl b/src/distribution_wrappers.jl index f88d22de9..977ef1a06 100644 --- a/src/distribution_wrappers.jl +++ b/src/distribution_wrappers.jl @@ -129,5 +129,10 @@ function arraydist(dists::AbstractArray{<:Distribution}) return product_distribution(dists) end function arraydist(dists::AbstractVector{<:UnivariateDistribution}) - return Product(dists) + # The inner constructor skips `Product`'s deprecation warning, which `Base.depwarn` + # makes expensive because it walks a backtrace on every call. + V = typeof(dists) + T = eltype(dists) + S = Distributions.value_support(T) + return Product{S,T,V}(dists) end diff --git a/test/distribution_wrappers.jl b/test/distribution_wrappers.jl index 91280914d..05ff746eb 100644 --- a/test/distribution_wrappers.jl +++ b/test/distribution_wrappers.jl @@ -5,9 +5,10 @@ using Dates: now __now__ = now() using DynamicPPL: DynamicPPL, @model -using Test: @testset, @test -using Distributions: Normal, logpdf +using Test: @testset, @test, @test_logs +using Distributions: Normal, Product, logpdf, product_distribution using Bijectors: Bijectors +using StableRNGs: StableRNG @testset "distribution_wrappers.jl" begin d = Normal() @@ -23,6 +24,17 @@ using Bijectors: Bijectors @test Bijectors.logpdf_with_trans(nd, 30, true) == 0 end +@testset "arraydist on a vector of univariates" begin + rng = StableRNG(468) + dists = Normal.(randn(rng, 3)) + x = randn(rng, 3) + # `Product(v)` calls `Base.depwarn`, which walks a backtrace on every call, so this has + # to go through the inner constructor instead. + @test_logs DynamicPPL.arraydist(dists) + @test DynamicPPL.arraydist(dists) isa Product + @test logpdf(DynamicPPL.arraydist(dists), x) == logpdf(product_distribution(dists), x) +end + @info "Completed $(@__FILE__) in $(now() - __now__)." end # module