Skip to content

[AutoDiff] devirtualize diff witnesses #28480

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

Merged
merged 6 commits into from
Nov 26, 2019
Merged

Conversation

marcrasi
Copy link

@marcrasi marcrasi commented Nov 26, 2019

Adds an optimization pass that devirtualizes differentiability witnesses into functions that reference them, replacing differentiability_witness_functions with function_refs.

Resolves TF-919 and TF-994.

Performance impact

This completely eliminates the performance impact of #28451 under -O, except for cross-module non-serialized differentiability witnesses, by causing it to generate the same code that would be generated by tensorflow HEAD.

I confirmed this by measuring the microbenchmark posted at #28451 (comment) . I haven't experimentally confirmed that the google internal model is also fixed, but I will experimentally verify that before I merge #2845.

@marcrasi marcrasi requested review from rxwei and dan-zheng November 26, 2019 01:34
@marcrasi
Copy link
Author

@swift-ci please test tensorflow

Copy link
Contributor

@dan-zheng dan-zheng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

I like your point that "devirtualization" isn't an apt name because there's no virtual dispatch.
Running the pass only with -O sounds good.


bool DifferentiabilityWitnessInliner::
inlineDifferentiabilityWitnessesInFunction(SILFunction &F) {
bool Changed = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: how about consistently using camelcase spelling for variables in differentiable programming code? I don't feel too strongly as long as casing is locally consistent.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

auto *W = I->getWitness();
if (W->isDeclaration() && !F.getModule().loadDifferentiabilityWitness(W))
continue;
assert(W->isDefinition());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to set Changed to true here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

SILMod, *linkage, original, parameterIndices, resultIndices,
derivativeGenSig, jvp, vjp, isSerialized);
diffWitnessOrOffset.set(diffWitness, /*isFullyDeserialized*/ true);
if (diffWitness->isDeclaration() && !isDeclaration)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please explain when this condition is true and convertToDefinition is called?
It doesn't seem wholly obvious, perhaps an explanatory comment would be good.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@dan-zheng
Copy link
Contributor

Could you please comment on how this patch impacts -O runtime performance?
Does it eliminate performance differences with current tensorflow HEAD?

@rxwei
Copy link
Contributor

rxwei commented Nov 26, 2019

I named this "inliner" instead of "devirtualizer" because there is no runtime dynamism involved, which makes this seem more like inlining than devirtualization.

There is runtime dynamism. The way it works is like protocol witness methods: there's no virtual dispatch, but there is dispatch -- the derivative is fetched at runtime. SIL devirtualizer applies to witness methods even though there's no virtual dispatch, so I think "devirtualizer" totally applies to differentiability witness functions.

Copy link
Contributor

@rxwei rxwei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the similarity to the SIL devirtualizer, maybe it's easier to just add some logic in swift::tryDevirtualizeApply that handles DifferentiabilityWitnessFunction instructions.

@marcrasi marcrasi changed the title [AutoDiff] inline diff witnesses [AutoDiff] devirtualize diff witnesses Nov 26, 2019
@marcrasi
Copy link
Author

The way it works is like protocol witness methods: there's no virtual dispatch, but there is dispatch -- the derivative is fetched at runtime. SIL devirtualizer applies to witness methods even though there's no virtual dispatch, so I think "devirtualizer" totally applies to differentiability witness functions.

This sounds good, I will rename it to devirtualizer

Given the similarity to the SIL devirtualizer, maybe it's easier to just add some logic in swift::tryDevirtualizeApply that handles DifferentiabilityWitnessFunction instructions.

Currently this would be pretty involved because the SIL devirtualizer starts at apply methods and looks for the callee. A lot of the callees in differentiation cases are hidden behind differentiable_function and differentiable_function_extracts.

The pass as written handles the devirtualization at the reference sites, avoiding this difficulty.

Could you please comment on how this patch impacts -O runtime performance?
Does it eliminate performance differences with current tensorflow HEAD?

In combination with #28451, -O performance is the same as tensorflow HEAD in the cases that I tested. Will add comment to PR description about this.

@rxwei
Copy link
Contributor

rxwei commented Nov 26, 2019

Currently this would be pretty involved because the SIL devirtualizer starts at apply methods and looks for the callee. A lot of the callees in differentiation cases are hidden behind differentiable_function and differentiable_function_extracts.

Makes sense. We need to do a proper differentiable_function-differentiable_function_extract folding pass at some point, after which we can revisit making tryDevirtualizeApply handle differentiability witness functions.

@marcrasi
Copy link
Author

@swift-ci please test tensorflow

2 similar comments
@marcrasi
Copy link
Author

@swift-ci please test tensorflow

@marcrasi
Copy link
Author

@swift-ci please test tensorflow

@marcrasi
Copy link
Author

@swift-ci please test tensorflow macos

@marcrasi
Copy link
Author

@swift-ci please test tensorflow

3 similar comments
@marcrasi
Copy link
Author

@swift-ci please test tensorflow

@marcrasi
Copy link
Author

@swift-ci please test tensorflow

@marcrasi
Copy link
Author

@swift-ci please test tensorflow

@rxwei
Copy link
Contributor

rxwei commented Nov 26, 2019

@swift-ci please test tensorflow

2 similar comments
@rxwei
Copy link
Contributor

rxwei commented Nov 26, 2019

@swift-ci please test tensorflow

@rxwei
Copy link
Contributor

rxwei commented Nov 26, 2019

@swift-ci please test tensorflow

@marcrasi
Copy link
Author

@swift-ci please test tensorflow macos

1 similar comment
@marcrasi
Copy link
Author

@swift-ci please test tensorflow macos

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants