Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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 src/jacobian.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ jacobian(f, x::Real) = throw(DimensionMismatch("jacobian(f, x) expects that x is
#####################

function extract_jacobian!(::Type{T}, result::AbstractArray, ydual::AbstractArray, n) where {T}
out_reshaped = reshape(result, length(ydual), n)
out_reshaped = result isa AbstractMatrix ? result : reshape(result, length(ydual), n)
ydual_reshaped = vec(ydual)
# Use closure to avoid GPU broadcasting with Type
partials_wrap(ydual, nrange) = partials(T, ydual, nrange)
Expand Down
16 changes: 16 additions & 0 deletions test/AllocationsTest.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,20 @@ convert_test_574() = convert(ForwardDiff.Dual{Nothing,ForwardDiff.Dual{Nothing,F
@test iszero(allocs_convert_test_574())
end

@testset "Test jacobian! allocations" begin
# jacobian! should not allocate when called with a pre-allocated result Matrix.
# Previously, reshape() inside extract_jacobian! allocated a wrapper
# object that could not be elided under --check-bounds=yes.
function allocs_jacobian!()
f!(y, x) = (y .= x .^ 2)
x = [1.0, 2.0, 3.0]
y = similar(x)
result = zeros(3, 3)
cfg = ForwardDiff.JacobianConfig(f!, y, x)
ForwardDiff.jacobian!(result, f!, y, x, cfg) # warmup
return @allocated ForwardDiff.jacobian!(result, f!, y, x, cfg)
end
@test iszero(allocs_jacobian!())
end

end
Loading