Skip to content

[AutoDiff] Support ref_element_addr differentiation. #29749

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 5 commits into from
Feb 11, 2020

Conversation

dan-zheng
Copy link
Contributor

@dan-zheng dan-zheng commented Feb 10, 2020

Support differentiation of ref_element_addr: class stored property references.

Activity analysis:

  • Propagate activity for ref_element_addr like struct_element_addr.
  • Do not propagate activity for ref_element_addr to @noDerivative members.

Pullback generation rules:

  Original: y = ref_element_addr x, <n>
   Adjoint: adj[x] += struct (0, ..., #field': adj[y], ..., 0)
                                      ^~~~~~~
                    field in tangent space corresponding to #field
  • Add ref_element_addr case to PullbackEmitter::getAdjointProjection.
    • The adjoint projection of a ref_element_addr is a local allocation
      initialized with the corresponding field value from the class's base
      adjoint value.

Exposes TF-1149: cannot differentiate active value with loadable type but
address-only TangentVector type. Diagnose for now.

Resolves SR-12152.

Todos:

  • SR-12152: support class initializer differentiation.
  • TF-1149: robust fix for original/tangent value category mismatch.
  • TF-970: replace invalid TangentVector struct assertions with diagnostics.

Example:

class C: Differentiable {
  @differentiable
  var float: Float

  init(_ float: Float) {
    self.float = float
  }

  @differentiable
  func method(_ x: Float) -> Float {
    x * float
  }
}
print(valueWithGradient(at: C(10), 3, in: { c, x in c.method(x) }))

Before:

$ swift tf-645.swift
tf-645.swift:2:4: error: function is not differentiable
  @differentiable
  ~^~~~~~~~~~~~~~
tf-645.swift:3:7: note: when differentiating this function definition
  var float: Float
      ^
tf-645.swift:3:7: note: differentiating class properties is not yet supported
  var float: Float
      ^

After:

$ swift tf-645.swift
value: 30.0, gradient: (C.TangentVector(float: 3.0), 10.0))

Support differentiation of `ref_element_addr`: class stored property references.

Teach activity analysis about `ref_element_addr`, handling it like `struct_element_addr`.
Do not propagate activity for `ref_element_addr` to `@noDerivative` members.

Pullback generation rules:
```
Original: y = ref_element_addr x, <n>
 Adjoint: adj[x] += struct (0, ..., #field': adj[y], ..., 0)
                                    ^~~~~~~
                  field in tangent space corresponding to #field
```

Exposes TF-1149: cannot differentiate active value with loadable type but
address-only `TangentVector` type. Diagnose for now.

Resolves SR-12152.
@dan-zheng dan-zheng added the tensorflow This is for "tensorflow" branch PRs. label Feb 10, 2020
@dan-zheng
Copy link
Contributor Author

@swift-ci Please test tensorflow

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.

Very nice!

@dan-zheng
Copy link
Contributor Author

@swift-ci Please test tensorflow

@dan-zheng
Copy link
Contributor Author

5012f1b fixes incorrect ref_element_addr zero derivatives:

Add `ref_element_addr` case to `PullbackEmitter::getAdjointProjection`.

The adjoint projection of a `ref_element_addr` is a local allocation initialized
with the corresponding field value from the class's base adjoint value.

@dan-zheng
Copy link
Contributor Author

@swift-ci Please test tensorflow

Add `ref_element_addr` case to `PullbackEmitter::getAdjointProjection`.

The adjoint projection of a `ref_element_addr` is a local allocation initialized
with the corresponding field value from the class's base adjoint value.

Fixes incorrect `ref_element_addr` zero derivatives.
Add class initializer differentiation tests.
@dan-zheng dan-zheng force-pushed the autodiff-ref-element-addr branch from 5012f1b to 358c1ce Compare February 11, 2020 02:49
@dan-zheng
Copy link
Contributor Author

@swift-ci Please test tensorflow

/// Adjoint: adj[x] += struct (0, ..., #field': adj[y], ..., 0)
/// ^~~~~~~
/// field in tangent space corresponding to #field
void visitRefElementAddrInst(RefElementAddrInst *reai);
Copy link
Contributor

Choose a reason for hiding this comment

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

We should get rid of this header soon...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can do it soon :)

@dan-zheng dan-zheng merged commit 5b7a1c3 into swiftlang:tensorflow Feb 11, 2020
@dan-zheng dan-zheng deleted the autodiff-ref-element-addr branch February 11, 2020 07:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tensorflow This is for "tensorflow" branch PRs.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants