|
1 | 1 | # SPDX-License-Identifier: LGPL-3.0-or-later |
2 | 2 | """ |
3 | | -CuTe-DSL accelerated SO(2) rotation operators for SeZM / DPA4. |
| 3 | +CuTe-DSL fused SO(2) value-path operator for SeZM / DPA4. |
4 | 4 |
|
5 | | -This package provides a self-contained, ``torch.compile``-friendly implementation |
6 | | -of the two fused gather + batched-GEMM operators used by the SeZM SO(2) edge |
7 | | -convolution: |
| 5 | +This package hosts a single bucketed CuTe operator that folds the entire per-edge |
| 6 | +value path of :class:`~deepmd.pt.model.descriptor.sezm_nn.so2.SO2Convolution` |
| 7 | +(``rotate_to_local`` -> radial degree mix -> the three-layer gated SO(2) mixing |
| 8 | +stack -> focus competition) into a fused forward kernel and a matching |
| 9 | +recompute backward kernel, keeping the per-edge intermediates on chip. It is an |
| 10 | +opt-in inference path enabled by ``DP_CUTE_INFER``; the final local features are |
| 11 | +handed to the committed flash-attention aggregation for rotate-back and scatter. |
| 12 | +Kernel entry points are internal implementation details of the SeZM descriptor; |
| 13 | +the package-level API only exposes availability and the value-path factory. |
8 | 14 |
|
9 | | -* ``rotate_to_local`` : ``out[e] = wigner[e][coeff_index] @ x[src[e]]`` |
10 | | -* ``rotate_back`` : ``out[e] = wigner[e][:, coeff_index] @ x_local[e]`` |
| 15 | +Current limitations |
| 16 | +------------------- |
| 17 | +Performance |
| 18 | + On H20 / fp32 the operator is about 2.8x slower than the compiled Triton + |
| 19 | + flash-attention path (roughly 489 / 724 ms versus 174 / 262 ms per force step |
| 20 | + at 2000 / 4000 atoms). Peak memory is at parity with, or marginally below, |
| 21 | + the compiled path (about 0.5 / 0.8 GB lower) and roughly 1.68x below the |
| 22 | + eager path. The bottleneck is the recompute backward, which dominates the |
| 23 | + kernel time: its occupancy is capped by the block-diagonal weight held |
| 24 | + resident in shared memory, and both the forward and backward GEMMs run at the |
| 25 | + hand-written plateau of about 21% of fp32 peak (versus about 52% for cuBLAS). |
11 | 26 |
|
12 | | -The kernels are written with the NVIDIA CuTe DSL (``cutlass.cute``) and fuse the |
13 | | -Wigner-row/column gather and the source-node gather directly into the matmul, so |
14 | | -the large ``D_to_m`` / ``x_src`` intermediates are never materialized. They are |
15 | | -exposed through the modern ``torch.library.custom_op`` API (functional, with |
16 | | -``register_fake`` + ``register_autograd``) so that they compose correctly with |
17 | | -``torch.compile`` and autograd. |
| 27 | +Deployment |
| 28 | + This is a Python-inference-only path. The ``cutlass.cute`` kernels are |
| 29 | + nvcc / NVRTC JIT-compiled at runtime and do not bake into the AOTInductor |
| 30 | + ``.pt2`` artifact, so the operator is unavailable to the LAMMPS / GPUMD C++ |
| 31 | + inference path. ``DP_CUTE_INFER`` is an independent path from |
| 32 | + ``DP_TRITON_INFER``; it engages regardless of the Triton flag and reuses the |
| 33 | + committed flash-attention aggregation kernel when it is active. |
18 | 34 |
|
19 | | -The top-level entry points are re-exported here for convenience. |
| 35 | +Correctness |
| 36 | + The force is bit-exact against the eager reference (energy relative error |
| 37 | + about 1e-9, force relative error about 5e-7 in fp32). |
20 | 38 | """ |
21 | 39 |
|
22 | 40 | from __future__ import ( |
23 | 41 | annotations, |
24 | 42 | ) |
25 | 43 |
|
26 | | -from .so2_rotation import ( |
| 44 | +from .forward import ( |
27 | 45 | SEZM_CUTE_AVAILABLE, |
28 | | - rotate_back_cute, |
29 | | - rotate_to_local_cute, |
| 46 | +) |
| 47 | +from .operator import ( |
| 48 | + make_cute_value_path, |
30 | 49 | ) |
31 | 50 |
|
32 | 51 | __all__ = [ |
33 | 52 | "SEZM_CUTE_AVAILABLE", |
34 | | - "rotate_back_cute", |
35 | | - "rotate_to_local_cute", |
| 53 | + "make_cute_value_path", |
36 | 54 | ] |
0 commit comments