Skip to content

Commit

Permalink
[misc] ti.Tape -> ti.ad.Tape (#5501)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucifer1004 authored Jul 25, 2022
1 parent c3508e9 commit 56689ad
Show file tree
Hide file tree
Showing 22 changed files with 67 additions and 67 deletions.
2 changes: 1 addition & 1 deletion cpp_examples/autograd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void autograd() {
energy += c[i]
init()
with ti.Tape(energy):
with ti.ad.Tape(energy):
cal()
support()
Expand Down
4 changes: 2 additions & 2 deletions docs/lang/articles/advanced/odop.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ print(arr.val[0, 0]) # 3
arr.inc2(4)
print(arr.val[0, 0]) # 7

with ti.Tape(loss=arr.total):
with ti.ad.Tape(loss=arr.total):
arr.reduce()

for i in range(arr.n):
Expand All @@ -236,7 +236,7 @@ for i in range(arr.n):
def double():
double_total[None] = 2 * arr.total[None]

with ti.Tape(loss=double_total):
with ti.ad.Tape(loss=double_total):
arr.reduce()
double()

Expand Down
34 changes: 17 additions & 17 deletions docs/lang/articles/differentiable/differentiable_programming.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,16 @@ really error-prone and hard to maintain.

If you run into this situation, Taichi's handy automatic differentiation (autodiff)
system comes to your rescue! Taichi supports gradient evaluation through
either `ti.Tape()` or the more flexible `kernel.grad()` syntax.
either `ti.ad.Tape()` or the more flexible `kernel.grad()` syntax.

## Using `ti.Tape()`
## Using `ti.ad.Tape()`

Let's still take the `compute_y` kernel above for an explanation.
Using `ti.Tape()` is the easiest way to obtain a kernel that computes `dy/dx`:
Using `ti.ad.Tape()` is the easiest way to obtain a kernel that computes `dy/dx`:

1. Enable `needs_grad=True` option when declaring fields involved in
the derivative chain.
2. Use context manager `with ti.Tape(y):` to capture the kernel invocations which you want to automatically differentiate.
2. Use context manager `with ti.ad.Tape(y):` to capture the kernel invocations which you want to automatically differentiate.
3. Now `dy/dx` value at current `x` is available at `x.grad[None]`.

The following code snippet explains the steps above:
Expand All @@ -69,7 +69,7 @@ y = ti.field(dtype=ti.f32, shape=(), needs_grad=True)
def compute_y():
y[None] = ti.sin(x[None])

with ti.Tape(y):
with ti.ad.Tape(y):
compute_y()

print('dy/dx =', x.grad[None], ' at x =', x[None])
Expand Down Expand Up @@ -119,7 +119,7 @@ def advance():


def substep():
with ti.Tape(loss=U):
with ti.ad.Tape(loss=U):
# Kernel invocations in this scope will later contribute to partial derivatives of
# U with respect to input variables such as x.
compute_U(
Expand All @@ -144,15 +144,15 @@ while gui.running:

:::note

The argument `U` to `ti.Tape(U)` must be a 0D field.
The argument `U` to `ti.ad.Tape(U)` must be a 0D field.

To use autodiff with multiple output variables, see the
`kernel.grad()` usage below.
:::

:::note

`ti.Tape(U)` automatically sets _`U[None]`_ to `0` on
`ti.ad.Tape(U)` automatically sets _`U[None]`_ to `0` on
start up.
:::

Expand All @@ -166,13 +166,13 @@ for examples on using autodiff-based force evaluation MPM and FEM.

## Using `kernel.grad()`

As mentioned above, `ti.Tape()` can only track a 0D field as the output variable.
As mentioned above, `ti.ad.Tape()` can only track a 0D field as the output variable.
If there are multiple output variables that you want to back-propagate
gradients to inputs, call `kernel.grad()` instead of `ti.Tape()`.
Different from using `ti.Tape()`, you need to set the `grad` of the output variables themselves to `1` manually
gradients to inputs, call `kernel.grad()` instead of `ti.ad.Tape()`.
Different from using `ti.ad.Tape()`, you need to set the `grad` of the output variables themselves to `1` manually
before calling `kernel.grad()`. The reason is that the `grad` of the output variables themselves
will always be multiplied to the `grad` with respect to the inputs at the end of the back-propagation.
By calling `ti.Tape()`, you have the program do this under the hood.
By calling `ti.ad.Tape()`, you have the program do this under the hood.

```python {13-14}
import taichi as ti
Expand Down Expand Up @@ -257,10 +257,10 @@ for i in range(N):
b[None] = 10
loss.grad[None] = 1

with ti.Tape(loss):
with ti.ad.Tape(loss):
func_broke_rule_1()
# Call func_equivalent to see the correct result
# with ti.Tape(loss):
# with ti.ad.Tape(loss):
# func_equivalent()

assert x.grad[1] == 10.0
Expand Down Expand Up @@ -357,7 +357,7 @@ def manipulation_in_kernel():


x[None] = 0.0
with ti.Tape(loss=loss):
with ti.ad.Tape(loss=loss):
# The line below in python scope only contribute to the forward pass
# but not the backward pass i.e., not auto-differentiated.
loss[None] += ti.sin(x[None]) + 1.0
Expand Down Expand Up @@ -412,13 +412,13 @@ def forward(mul):
def backward(mul):
func.grad(mul)
with ti.Tape(loss=total):
with ti.ad.Tape(loss=total):
forward(4)
assert x.grad[0] == 4
```

Customized gradient function works with both `ti.Tape()` and `kernel.grad()`. More examples can be found at `test_customized_grad.py`.
Customized gradient function works with both `ti.ad.Tape()` and `kernel.grad()`. More examples can be found at `test_customized_grad.py`.

### Checkpointing

Expand Down
2 changes: 1 addition & 1 deletion misc/demo_record_kernel_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ def do_some_works():

with ti.aot.RecordKernelGroup('my_substep'):
x.fill(0)
with ti.Tape(loss):
with ti.ad.Tape(loss):
compute_loss()
do_some_works()
6 changes: 3 additions & 3 deletions python/taichi/ad/_ad.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def __init__(self, loss=None, clear_gradients=True):
>>> for I in ti.grouped(x):
>>> y[None] += x[I] ** a
>>>
>>> with ti.Tape(loss = y):
>>> with ti.ad.Tape(loss = y):
>>> sum(2)
"""
self.calls = []
Expand Down Expand Up @@ -111,7 +111,7 @@ def visit(node):

def grad_replaced(func):
"""A decorator for python function to customize gradient with Taichi's autodiff
system, e.g. `ti.Tape()` and `kernel.grad()`.
system, e.g. `ti.ad.Tape()` and `kernel.grad()`.
This decorator forces Taichi's autodiff system to use a user-defined gradient
function for the decorated function. Its customized gradient must be decorated
Expand Down Expand Up @@ -186,7 +186,7 @@ def decorated(*args, **kwargs):

def no_grad(func):
"""A decorator for python function to skip gradient calculation within Taichi's
autodiff system, e.g. `ti.Tape()` and `kernel.grad()`.
autodiff system, e.g. `ti.ad.Tape()` and `kernel.grad()`.
This decorator forces Taichi's autodiff system to use an empty gradient function
for the decorated function.
Expand Down
2 changes: 1 addition & 1 deletion python/taichi/aot/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def start_recording(filename):
>>> for i in x:
>>> x[i] -= x.grad[i]
>>>
>>> with ti.Tape(loss):
>>> with ti.ad.Tape(loss):
>>> compute_loss()
>>> do_some_works()
"""
Expand Down
2 changes: 1 addition & 1 deletion python/taichi/examples/autodiff/minimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def main():

# Optimize with 100 gradient descent iterations
for k in range(100):
with ti.Tape(loss=L):
with ti.ad.Tape(loss=L):
reduce()
print('Loss =', L[None])
gradient_descent()
Expand Down
2 changes: 1 addition & 1 deletion python/taichi/examples/autodiff/regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def regress_raw():

for i in range(1000):
if use_tape:
with ti.Tape(loss=loss):
with ti.ad.Tape(loss=loss):
regress()
else:
ti.clear_all_gradients()
Expand Down
2 changes: 1 addition & 1 deletion python/taichi/examples/ggui_examples/fem128_ggui.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def main():
attractor_strength[None] = window.is_pressed(
ti.ui.LMB) - window.is_pressed(ti.ui.RMB)
for i in range(50):
with ti.Tape(loss=U):
with ti.ad.Tape(loss=U):
update_U()
advance()
render()
Expand Down
2 changes: 1 addition & 1 deletion python/taichi/examples/simulation/ad_gravity.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def advance():


def substep():
with ti.Tape(loss=U):
with ti.ad.Tape(loss=U):
# Kernel invocations in this scope will later contribute to partial derivatives of
# U with respect to input variables such as x.
compute_U(
Expand Down
2 changes: 1 addition & 1 deletion python/taichi/examples/simulation/fem128.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def main():
attractor_strength[None] = gui.is_pressed(gui.LMB) - gui.is_pressed(
gui.RMB)
for i in range(50):
with ti.Tape(loss=U):
with ti.ad.Tape(loss=U):
update_U()
advance()
paint_phi(gui)
Expand Down
2 changes: 1 addition & 1 deletion python/taichi/examples/simulation/fem99.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def main():
elif e.key == 'r':
init_pos()
for i in range(30):
with ti.Tape(loss=U):
with ti.ad.Tape(loss=U):
update_U()
advance()
gui.circles(pos.to_numpy(), radius=2, color=0xffaa33)
Expand Down
2 changes: 1 addition & 1 deletion python/taichi/examples/simulation/mpm_lagrangian_forces.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def main():
grid_v.fill(0)
# Note that we are now differentiating the total energy w.r.t. the particle position.
# Recall that F = - \partial (total_energy) / \partial x
with ti.Tape(total_energy):
with ti.ad.Tape(total_energy):
# Do the forward computation of total energy and backward propagation for x.grad, which is later used in p2g
compute_total_energy()
# It's OK not to use the computed total_energy at all, since we only need x.grad
Expand Down
2 changes: 1 addition & 1 deletion tests/python/examples/autodiff/test_minimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def test_minimization():
y[i] = random.random()

for k in range(100):
with ti.Tape(loss=L):
with ti.ad.Tape(loss=L):
reduce()
gradient_descent()

Expand Down
6 changes: 3 additions & 3 deletions tests/python/test_ad_basics.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ def test_ad_precision_2():
def func():
loss[None] = x[None]

with ti.Tape(loss):
with ti.ad.Tape(loss):
func()

assert x.grad[None] == 1
Expand All @@ -443,7 +443,7 @@ def work():

x[None] = 10
with pytest.raises(RuntimeError) as e:
with ti.Tape(loss):
with ti.ad.Tape(loss):
work()
assert 'RandStmt not supported' in e.value.args[0]

Expand Down Expand Up @@ -472,7 +472,7 @@ def calc_loss(input_field: ti.template(), loss: ti.template()):
field1 = ti.field(dtype=ti.f32, shape=(n, ), needs_grad=True)
loss = ti.field(dtype=ti.f32, shape=(), needs_grad=True)

with ti.Tape(loss):
with ti.ad.Tape(loss):
ti_frac(field0, field1)
calc_loss(field1, loss)

Expand Down
26 changes: 13 additions & 13 deletions tests/python/test_ad_for.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ def mixed_inner_loops_tape():
loss[None] += ti.sin(x[None]) + 1.0

x[None] = 0.0
with ti.Tape(loss=loss):
with ti.ad.Tape(loss=loss):
mixed_inner_loops_tape()

assert loss[None] == 10.0
Expand All @@ -479,7 +479,7 @@ def test_inner_loops_local_variable():
loss[None] += s + t

x[None] = 0.0
with ti.Tape(loss=loss):
with ti.ad.Tape(loss=loss):
test_inner_loops_local_variable()

assert loss[None] == 18.0
Expand Down Expand Up @@ -530,7 +530,7 @@ def test_inner_loops_local_variable():
loss[None] += s + t

x[None] = 0.0
with ti.Tape(loss=loss):
with ti.ad.Tape(loss=loss):
test_inner_loops_local_variable()

assert loss[None] == 18.0
Expand Down Expand Up @@ -585,7 +585,7 @@ def test_more_inner_loops_local_variable():
loss[None] += s

x[None] = 0.0
with ti.Tape(loss=loss):
with ti.ad.Tape(loss=loss):
test_more_inner_loops_local_variable()

assert loss[None] == 12.0
Expand Down Expand Up @@ -614,7 +614,7 @@ def test_more_inner_loops_local_variable():
loss[None] += s

x[None] = 0.0
with ti.Tape(loss=loss):
with ti.ad.Tape(loss=loss):
test_more_inner_loops_local_variable()

assert loss[None] == 12.0
Expand Down Expand Up @@ -768,7 +768,7 @@ def test_large_loop():
for k in range(1000):
loss[None] += ti.sin(x[None]) + 1.0

with ti.Tape(loss=loss):
with ti.ad.Tape(loss=loss):
test_large_loop()

assert loss[None] == 1e7
Expand All @@ -790,7 +790,7 @@ def test_large_loop():
for k in range(1000):
loss[None] += ti.sin(x[None]) + 1.0

with ti.Tape(loss=loss):
with ti.ad.Tape(loss=loss):
test_large_loop()

assert loss[None] == 1e7
Expand All @@ -811,7 +811,7 @@ def compute_y():
y[None] += x[None]

x[None] = 1.0
with ti.Tape(y):
with ti.ad.Tape(y):
compute_y()

assert y[None] == 12.0
Expand All @@ -837,7 +837,7 @@ def compute_y():
y[None] += x[None]

x[None] = 1.0
with ti.Tape(y):
with ti.ad.Tape(y):
compute_y()

assert y[None] == 24.0
Expand Down Expand Up @@ -865,7 +865,7 @@ def compute_y():
y[None] += x[None]

x[None] = 1.0
with ti.Tape(y):
with ti.ad.Tape(y):
compute_y()

assert y[None] == 42.0
Expand All @@ -890,7 +890,7 @@ def compute_y():
y[None] += x[None]

x[None] = 1.0
with ti.Tape(y):
with ti.ad.Tape(y):
compute_y()

assert y[None] == 30.0
Expand All @@ -916,7 +916,7 @@ def compute_y():
y[None] += x[None]

x[None] = 1.0
with ti.Tape(y):
with ti.ad.Tape(y):
compute_y()

assert y[None] == 42.0
Expand Down Expand Up @@ -975,7 +975,7 @@ def compute_y():
y[None] += x[None]

x[None] = 1.0
with ti.Tape(y):
with ti.ad.Tape(y):
compute_y()

assert y[None] == 78.0
Expand Down
Loading

0 comments on commit 56689ad

Please sign in to comment.