-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[AutoDiff] Fixes memory leaks in autodiff linear map context allocation builtins #67944
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
@asl @BradLarson Could I get a review on this? |
@swift-ci Please test. |
@@ -2273,12 +2273,12 @@ FUNCTION(TaskGroupDestroy, | |||
ATTRS(NoUnwind), | |||
EFFECT(Concurrency)) | |||
|
|||
// AutoDiffLinearMapContext *swift_autoDiffCreateLinearMapContext(size_t); | |||
// AutoDiffLinearMapContext *swift_autoDiffCreateLinearMapContext(const Metadata *); |
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.
So, there will be no link errors for things compiled with old compiler and linked with new runtime and vice versa?
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.
Ah, it slipped my mind and I meant to ask this. I wasn't able to figure out how to make this a link time error.
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 easiest way: rename functions :) Hard way: invent some backward compatibility scheme. @rxwei any suggestions? I think we do not care about ABI stability for now, isn't it?
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.
Haven't made a decision on this in the latest revision. Waiting on @rxwei's input. If breaking ABI is going to be a concern we could deprecate existing builtins instead of completely removing them.
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.
Just to be safe, we should add a new runtime function without modifying the signature of the old one.
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.
Should we deprecate the old ones as well? They do lead to memory leaks.
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.
What do you mean by deprecate? We just don't call it
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 mean, this is not an API. There is not a real way to deprecate it.
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.
@jkshtj I believe what @rxwei means is as follows:
- Add new functions, say
swift_autoDiffCreateLinearMapContext2
etc. with the desired functionality - Keep old functions as-is
As a result: old code would still be able to run with the new runtime. The behavior will be the same, well, it will leak. The new code will call that new runtime functions and will be leak-less.
test/AutoDiff/stdlib/callee_differential_not_leaked_in_func_with_loops.swift
Outdated
Show resolved
Hide resolved
test/AutoDiff/stdlib/callee_differential_not_leaked_in_func_with_loops.swift
Show resolved
Hide resolved
@asl as per offline discussion w/ @BradLarson, since we're already aware of the memory scaling issues with allocating loop context objects directly on the heap I have created a new revision to reintegrate |
@jkshtj Well, this was quite different case, as the chain of boxes were explicitly created ;) Anyway, as we already discussed, as soon as you had the initial implementation on top of the boxes, it was possible to change the underlying implementation to something more lightweight, as we certainly did not want to reference count the pullback tuples. |
@swift-ci please test |
This commit builds on top of a previous commit that fixed memory leak issues in the autodiff loop context allocation builtins. The previous commit allocated loop contexts in a box, which is known to have memory scaling issues. This commit modifies AutoDiffLinearMapContext to perform memory allocation using the BumpPtrAllocator, like it used to, while introducing new bookkeeping logic that enables AutoDiffLinearMapContext to prevent memory leaks, unlike before.
@swift-ci Please test |
@swift-ci please test windows |
include/swift/AST/Builtins.def
Outdated
@@ -994,6 +994,12 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(AutoDiffProjectTopLevelSubcontext, "autoDiffP | |||
// autoDiffAllocateSubcontext: (Builtin.NativeObject, Builtin.Word) -> Builtin.RawPointer | |||
BUILTIN_MISC_OPERATION_WITH_SILGEN(AutoDiffAllocateSubcontext, "autoDiffAllocateSubcontext", "", Special) | |||
|
|||
// autoDiffCreateLinearMapContext2: (T.Type) -> Builtin.NativeObject |
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.
Some bike-shedding: maybe rename these to autoDiffCreateLinearMapContextWithType
etc.?
lib/IRGen/GenCall.cpp
Outdated
@@ -5500,8 +5501,9 @@ Address irgen::emitAutoDiffProjectTopLevelSubcontext( | |||
return Address(call, IGF.IGM.Int8Ty, IGF.IGM.getPointerAlignment()); | |||
} | |||
|
|||
Address irgen::emitAutoDiffAllocateSubcontext( | |||
IRGenFunction &IGF, Address context, llvm::Value *size) { | |||
Address irgen::emitAutoDiffAllocateSubcontext(IRGenFunction &IGF, |
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.
Do we need to keep these functions after all? We are not going to call these builtins from the compiler.
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.
Removed
lib/AST/Builtins.cpp
Outdated
@@ -1625,6 +1625,20 @@ static ValueDecl *getAutoDiffAllocateSubcontext(ASTContext &ctx, | |||
ctx.TheRawPointerType); | |||
} | |||
|
|||
static ValueDecl *getAutoDiffCreateLinearMapContext2(ASTContext &ctx, |
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.
As the functions above with old builtins are never called from the compiler, I'd steal their names for the helpers that call new builtins
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 think it'll be better to keep the helpers symmetric with the names of the builtins. Otherwise autoDiffProjectTopLevelSubcontext
will be the odd one out in different places.
…ld ones This commit builds on top of a previous commit that fixed memory leak issues in the autodiff loop context allocation builtins. The previous commit changed the existing builtins. However, inorder to maintain ABI compatibility and not break other consumers of autodiff, this commit creates newly named builtins that don't leak memory and preserves the older builtins. As a result, now, code compiled with an older frontend and using a newer stdlib will continue to work. But code compiled with a newer frontend and using older stdlib will have undefined behavior.
@swift-ci Please test |
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.
Thanks!
Resolve conflicts introduced in #67944 as follows: ``` diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def index 3c973b5884b..44cde707d17 100644 --- a/include/swift/Runtime/RuntimeFunctions.def +++ b/include/swift/Runtime/RuntimeFunctions.def @@ -2537,16 +2537,10 @@ FUNCTION(AutoDiffCreateLinearMapContextWithType, swift_autoDiffCreateLinearMapContextWithType, SwiftCC, DifferentiationAvailability, RETURNS(RefCountedPtrTy), -<<<<<<< HEAD - ARGS(SizeTy), + ARGS(TypeMetadataPtrTy), ATTRS(NoUnwind), EFFECT(AutoDiff), MEMEFFECTS(ArgMemOnly)) -======= - ARGS(TypeMetadataPtrTy), - ATTRS(NoUnwind, ArgMemOnly), - EFFECT(AutoDiff)) ->>>>>>> public-github/main // void *swift_autoDiffProjectTopLevelSubcontext(AutoDiffLinearMapContext *); FUNCTION(AutoDiffProjectTopLevelSubcontext, @@ -2563,16 +2557,10 @@ FUNCTION(AutoDiffAllocateSubcontextWithType, swift_autoDiffAllocateSubcontextWithType, SwiftCC, DifferentiationAvailability, RETURNS(Int8PtrTy), -<<<<<<< HEAD - ARGS(RefCountedPtrTy, SizeTy), + ARGS(RefCountedPtrTy, TypeMetadataPtrTy), ATTRS(NoUnwind), EFFECT(AutoDiff), MEMEFFECTS(ArgMemOnly)) -======= - ARGS(RefCountedPtrTy, TypeMetadataPtrTy), - ATTRS(NoUnwind, ArgMemOnly), - EFFECT(AutoDiff)) ->>>>>>> public-github/main ```
When the differentiating a function containing loops, we allocate a linear map context object on the heap. This context object may store non-trivial objects, such as closures,that need to be freed explicitly, at program exit. This PR fixes the autodiff linear map context allocation builtins to destroy and deallocate any such objects.
Fixes #67323