mirror of
https://github.com/zebrajr/pytorch.git
synced 2025-12-07 00:21:07 +01:00
Summary: This is a benchmarking tooling to work with sparse tensors. To implement this, we extended PR `benchmarking util` [https://github.com/pytorch/pytorch/issues/38338](https://github.com/pytorch/pytorch/pull/38338) for sparse tensors. In order to extend the proposed utility library the **FuzzedTensor** class was extended by creating the new **FuzzedSparseTensor** class. In addition two new operator classes were added, the `UnaryOpSparseFuzzer` and `BinaryOpSparseFuzzer`. The class `FuzzedSparseTensor` adds new input parameters to the constructor: 1. `sparse_dim`: The number of sparse dimensions in a sparse tensor. 2. `nnz`: Number of non-zero elements in the sparse tensor. 3. `density`: The density of the sparse tensor. 4. `coalesced`: As we know the sparse tensor format permits coalesced/uncoalesced sparse tensors. and removes `probability_contiguous`, `max_allocation_bytes`, `roll_parameter`, `tensor_constructor` as they are dense-tensors related parameters. In addition, I've extended the `torch.utils.benchmark.examples` to work with the new classes `FuzzedSparseTensor`, `UnaryOpSparseFuzzer` and `BinaryOpSparseFuzzer`. Hopefully, this tooling and these examples will help to make other benchmarks in other PRs. Looking forward to your thoughts and feedback. cc robieta, mruberry, ngimel Pull Request resolved: https://github.com/pytorch/pytorch/pull/48397 Reviewed By: ejguan Differential Revision: D26008137 Pulled By: mruberry fbshipit-source-id: 2f37811c7c3eaa3494a0f2500e519267f2186dfb
102 lines
3.3 KiB
Python
102 lines
3.3 KiB
Python
"""Example of the Timer and Sparse Fuzzer APIs:
|
|
|
|
$ python -m examples.sparse.fuzzer
|
|
"""
|
|
|
|
import sys
|
|
|
|
import torch.utils.benchmark as benchmark_utils
|
|
|
|
def main():
|
|
add_fuzzer = benchmark_utils.Fuzzer(
|
|
parameters=[
|
|
[
|
|
benchmark_utils.FuzzedParameter(
|
|
name=f"k{i}",
|
|
minval=16,
|
|
maxval=16 * 1024,
|
|
distribution="loguniform",
|
|
) for i in range(3)
|
|
],
|
|
benchmark_utils.FuzzedParameter(
|
|
name="dim_parameter",
|
|
distribution={2: 0.6, 3: 0.4},
|
|
),
|
|
benchmark_utils.FuzzedParameter(
|
|
name="sparse_dim",
|
|
distribution={1: 0.3, 2: 0.4, 3: 0.3},
|
|
),
|
|
benchmark_utils.FuzzedParameter(
|
|
name="density",
|
|
distribution={0.1: 0.4, 0.05: 0.3, 0.01: 0.3},
|
|
),
|
|
benchmark_utils.FuzzedParameter(
|
|
name="coalesced",
|
|
distribution={True: 0.7, False: 0.3},
|
|
)
|
|
],
|
|
tensors=[
|
|
[
|
|
benchmark_utils.FuzzedSparseTensor(
|
|
name=name,
|
|
size=[f"k{i}" for i in range(3)],
|
|
min_elements=64 * 1024,
|
|
max_elements=128 * 1024,
|
|
sparse_dim="sparse_dim",
|
|
density="density",
|
|
dim_parameter="dim_parameter",
|
|
coalesced="coalesced"
|
|
) for name in ("x", "y")
|
|
],
|
|
],
|
|
seed=0,
|
|
)
|
|
|
|
n = 100
|
|
measurements = []
|
|
|
|
for i, (tensors, tensor_properties, _) in enumerate(add_fuzzer.take(n=n)):
|
|
x = tensors["x"]
|
|
y = tensors["y"]
|
|
shape = ", ".join(tuple(f'{i:>4}' for i in x.shape))
|
|
x_tensor_properties = tensor_properties["x"]
|
|
description = "".join([
|
|
f"| {shape:<20} | ",
|
|
f"{x_tensor_properties['sparsity']:>9.2f} | ",
|
|
f"{x_tensor_properties['sparse_dim']:>9d} | ",
|
|
f"{x_tensor_properties['dense_dim']:>9d} | ",
|
|
f"{('True' if x_tensor_properties['is_hybrid'] else 'False'):>9} | ",
|
|
f"{('True' if x.is_coalesced() else 'False'):>9} | "
|
|
])
|
|
timer = benchmark_utils.Timer(
|
|
stmt="torch.sparse.sum(x) + torch.sparse.sum(y)",
|
|
globals=tensors,
|
|
description=description,
|
|
)
|
|
measurements.append(timer.blocked_autorange(min_run_time=0.1))
|
|
measurements[-1].metadata = {"nnz": x._nnz()}
|
|
print(f"\r{i + 1} / {n}", end="")
|
|
sys.stdout.flush()
|
|
print()
|
|
|
|
# More string munging to make pretty output.
|
|
print(f"Average attemts per valid config: {1. / (1. - add_fuzzer.rejection_rate):.1f}")
|
|
|
|
def time_fn(m):
|
|
return m.mean / m.metadata["nnz"]
|
|
|
|
measurements.sort(key=time_fn)
|
|
|
|
template = f"{{:>6}}{' ' * 16} Shape{' ' * 17}\
|
|
sparsity{' ' * 4}sparse_dim{' ' * 4}dense_dim{' ' * 4}hybrid{' ' * 4}coalesced\n{'-' * 108}"
|
|
print(template.format("Best:"))
|
|
for m in measurements[:10]:
|
|
print(f"{time_fn(m) * 1e9:>5.2f} ns / element {m.description}")
|
|
|
|
print("\n" + template.format("Worst:"))
|
|
for m in measurements[-10:]:
|
|
print(f"{time_fn(m) * 1e9:>5.2f} ns / element {m.description}")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|