-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[AutoDiff] Support differentiation of loops. #25558
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
8ebed4a
to
eab1067
Compare
- Change predecessor enum generation to support loops. - Generate indirect predecessor enums for BBs in loops. - Handle boxed payloads of indirect enums. - Traverse basic blocks in post-order post-dominance order. - This is necessary for computational correctness. - Add loop tests (`for-in`, `while`, nested).
eab1067
to
16dc9a2
Compare
if (!boxType) | ||
return builder.createEnum(loc, pbStructVal, enumEltDecl, enumLoweredTy); | ||
// Otherwise, box the pullback struct value and create an enum. | ||
auto *allocBox = builder.createAllocBox(loc, boxType); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This alloc_box
is not being deallocated and may cause leaks - to be verified.
Loop AD leak checking tests are added in test/AutoDiff/leakchecking.swift
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved - see this comment. Deallocation is handled automatically during release_value
for pullback structs.
/// Mapping from original basic blocks to local adjoint values to be cleaned | ||
/// up. This is populated when adjoint emission is run on one basic block and | ||
/// cleaned before processing another basic block. | ||
DenseMap<SILBasicBlock *, SmallVector<AdjointValue, 8>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: changed blockLocalAdjointValues
to a DenseMap
for more principled/predictable behavior.
Previously, using SmallVector
caused bugs when the original entry BB isn't the last visited BB during adjoint generation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't find any emission of dealloc_box
and this is apparently leaking a lot more memory (all pullback structs in loops are kept alive). This needs to be fixed before merging.
Actually, this should be handled automatically when you release_value
the pullback struct.
expectEqual((8, 12), valueWithGradient(at: 2, in: for_loop)) | ||
expectEqual((27, 27), valueWithGradient(at: 3, in: for_loop)) | ||
|
||
func while_loop(_ x: Float) -> Float { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please also test a repeat
-while
loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The patch is pretty clean. LGTM!
Add tests for repeat-while loops and break/continue statements. Expose TF-584: incorrect derivative computation for repeat-while loops.
a92cdb7
to
32f6629
Compare
@swift-ci Please test tensorflow |
Two tests fail only with optimizations, which I hadn't tested locally:
Perhaps there are some missing deallocations in generated code. Will investigate later. EDIT: Filed TF-585 with details about the AllocBoxToStack crash. |
@swift-ci Please test tensorflow |
dfd9e3d
to
ea63e6f
Compare
Generate `fix_lifetime` instruction on `alloc_box` to avoid crash.
ea63e6f
to
46caa45
Compare
@swift-ci Please test tensorflow |
for-in
,while
,repeat-while
,break
/continue
, nested).Examples:
Verified loop differentiation correctness against PyTorch and Tangent.
Exposed TF-584: derivative computation bug for repeat-while loops.
Exposed TF-585: AllocBoxToStack crash with
-O
for nested loop AD.