`deepcopy` of a container of tracked numbers gives zero gradients, with no error
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 46/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- julia
- Lĩnh vực
- machine-learning
Hướng nghiên cứu
Start by reading src/tracked.jl and inspect how deepcopy and deepcopy_internal handle TrackedReal, TrackedArray, and containers. Reproduce the supplied examples, including the copied-tape case, before choosing an approach. Done means container copies preserve gradients while deep-copying a tape still produces an independent tape.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Thank you for your incredible work. Below is a Claude-generated reduction of an error I ran into when using deepcopy - I hope its useful. Let me know if I can do anything, and my apologies if this is a known error.
-- claude --
deepcopy of anything that holds tracked numbers, such as a Vector, Tuple, NamedTuple or TrackedArray, cuts them off from the reverse pass. The gradient comes back as zeros, with no error or warning. A bare TrackedReal is fine.
using ReverseDiff
x = [3.0, 4.0]
println("No deepcopy: ", ReverseDiff.gradient(x -> sum([x[1], x[2]]), x))
println("Bare numbers: ", ReverseDiff.gradient(x -> deepcopy(x[1]) + deepcopy(x[2]), x))
println("Vector: ", ReverseDiff.gradient(x -> sum(deepcopy([x[1], x[2]])), x))
println("Tuple: ", ReverseDiff.gradient(x -> sum(deepcopy((x[1], x[2]))), x))
println("NamedTuple: ", ReverseDiff.gradient(x -> sum(deepcopy((; a = x[1], b = x[2]))), x))
println("TrackedArray: ", ReverseDiff.gradient(x -> sum(deepcopy(x)), x))
println("Next to original: ", ReverseDiff.gradient(x -> x[1] + deepcopy((x[1],))[1], x))
Output:
No deepcopy: [1.0, 1.0]
Bare numbers: [1.0, 1.0]
Vector: [0.0, 0.0]
Tuple: [0.0, 0.0]
NamedTuple: [0.0, 0.0]
TrackedArray: [0.0, 0.0]
Next to original: [1.0, 0.0]
The right answer is [1.0, 1.0] for all but the last, where it is [2.0, 0.0]. A compiled tape gives the same zeros for the Vector.
Where it seems to come from
src/tracked.jl has Base.deepcopy(t::T) where {T <: TrackedReal} = t, so a bare number stays on the tape. Inside a container, Julia calls Base.deepcopy_internal instead of deepcopy, and ReverseDiff has no method for it. The numbers then seem to get their own copy of the tape, which the reverse pass never reaches.
A possible fix, and its catch
With these two methods, all of the cases above are right. With only the first one, all but TrackedArray are right.
Base.deepcopy_internal(t::ReverseDiff.TrackedReal, ::IdDict) = t
Base.deepcopy_internal(t::ReverseDiff.TrackedArray, ::IdDict) = t
But with both of them, deepcopy of a tape no longer gives an independent tape. Running the copy changes the original:
tape = ReverseDiff.GradientTape(x -> sum(abs2, x), [3.0, 4.0])
copied = deepcopy(tape)
ReverseDiff.gradient!(zeros(2), copied, [1.0, 1.0])
ReverseDiff.value(tape.output) # 25.0 without the methods, 2.0 with them
So the fix probably needs more care than this.
Versions
- ReverseDiff v1.18.7, the newest version in the General registry on 2026-11-04
- Julia 1.13.3
- macOS, arm64 (Apple M5)
The example ran in a clean environment with only ReverseDiff installed. It hasn't been tried on other platforms.
- Ngôn ngữ chính
- Julia
- Star
- 397
- Fork
- 62
- Merge trung bình
- 8 giờ 9 phút
- Pull request đã merge (30 ngày)
- 4
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của JuliaDiff/ReverseDiff.jl
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 86/100
JuliaDiff/ReverseDiff.jl#318 ·
-
`@grad`/`@grad_from_chainrules` silently reuse a tangent if a pullback returns too few tangentsĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 83/100
JuliaDiff/ReverseDiff.jl#315 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
JuliaDiff/ReverseDiff.jl#314 ·
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 56/100
JuliaDiff/ReverseDiff.jl#321 ·
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 72/100
JuliaDiff/ReverseDiff.jl#320 ·
Tất cả issue của JuliaDiff/ReverseDiff.jl
Issue tương tự
-
Prescribed ice velocities never get their halos filled, so ice is created at a periodic seamĐang mở🕷️ bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
CliMA/ClimaSeaIce.jl#203 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
documentation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 64/100
JuliaPhysics/BeamletOptics.jl#221 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
release preparation spack
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 67/100
Maintainer thường phản hồi trong vòng 1 ngày
-
30-minutes algorithm any-language codewars dart easy elixir hackerrank hacktoberfest haskell help wanted interview-prep julia leetcode lua open-source r scala students zig
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Huerte/algo-solutions-python#163 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
QuantumSavory/QuantumClifford.jl#853 ·
Maintainer thường phản hồi trong vòng 1 ngày