Use Pytorch Benchmark on the backward pass of an arbitrary function.
(
fn,
*inputs,
grad=None,
repeats=10,
desc="",
verbose=True,
amp=False,
amp_dtype=torch.float16,
**kwinputs,
)
| 28 | |
| 29 | |
| 30 | def benchmark_backward( |
| 31 | fn, |
| 32 | *inputs, |
| 33 | grad=None, |
| 34 | repeats=10, |
| 35 | desc="", |
| 36 | verbose=True, |
| 37 | amp=False, |
| 38 | amp_dtype=torch.float16, |
| 39 | **kwinputs, |
| 40 | ): |
| 41 | """Use Pytorch Benchmark on the backward pass of an arbitrary function.""" |
| 42 | if verbose: |
| 43 | print(desc, "- Backward pass") |
| 44 | with torch.autocast(device_type="cuda", dtype=amp_dtype, enabled=amp): |
| 45 | y = fn(*inputs, **kwinputs) |
| 46 | if type(y) is tuple: |
| 47 | y = y[0] |
| 48 | if grad is None: |
| 49 | grad = torch.randn_like(y) |
| 50 | else: |
| 51 | if grad.shape != y.shape: |
| 52 | raise RuntimeError("Grad shape does not match output shape") |
| 53 | |
| 54 | def f(*inputs, y, grad): |
| 55 | # Set .grad to None to avoid extra operation of gradient accumulation |
| 56 | for x in inputs: |
| 57 | if isinstance(x, torch.Tensor): |
| 58 | x.grad = None |
| 59 | y.backward(grad, retain_graph=True) |
| 60 | |
| 61 | t = benchmark.Timer( |
| 62 | stmt="f(*inputs, y=y, grad=grad)", |
| 63 | globals={"f": f, "inputs": inputs, "y": y, "grad": grad}, |
| 64 | num_threads=torch.get_num_threads(), |
| 65 | ) |
| 66 | m = t.timeit(repeats) |
| 67 | if verbose: |
| 68 | print(m) |
| 69 | return t, m |
| 70 | |
| 71 | |
| 72 | def benchmark_combined( |
no outgoing calls
no test coverage detected