Skip to content

Commit e59eb7e

Browse files
Merge branch 'main' into nvegesna/gemma2-softcap-core
Three conflicts, all two sides adding different things at the same line. tests/pytorch/utils.py: #2964 adds bottom_right_diagonal to ModelConfig and to the AttentionParams call where this branch adds softcap. AttentionParams carries both fields, so both are kept. dot_product_attention.py: the attention_params_kwargs dict. #2964 tightens the alibi_slopes_shape guard to require core_attention_bias_type == "alibi". Kept that and kept the "softcap" key, which get_attention_backend needs to see in order to disqualify the backends that cannot honour a cap. Dropping it here would leave softcap silently ignored during backend selection with no test failure, which is how it was lost in an earlier merge on this branch. Signed-off-by: Nitin Vegesna <nvegesna@nvidia.com>
2 parents a5f9ec0 + f689f8f commit e59eb7e

41 files changed

Lines changed: 7451 additions & 3505 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎docs/envvars.rst‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -190,18 +190,18 @@ backend-selection overview.
190190
:Default: ``1``
191191
:Description: Enable or disable UnfusedDotProductAttention backend (native PyTorch). When set to ``0``, UnfusedDotProductAttention will not be used.
192192

193-
.. envvar:: NVTE_FUSED_ATTN_BACKEND
194-
195-
:Type: ``int`` (1 or 2)
196-
:Default: Auto-selected
197-
:Description: Request a cuDNN FusedAttention backend when that request is supported by the active fused-attention path. ``1`` = F16_arbitrary_seqlen (cuDNN, any seq len), ``2`` = FP8 backend. If not set, the backend is automatically selected based on the input configuration. BF16/FP16 attention uses sub-backend ``1`` when eligible. FP8 attention uses sub-backend ``2`` when FP8 DPA is enabled and supported by the architecture, cuDNN version, and input configuration.
198-
199193
.. envvar:: NVTE_FUSED_ATTN_USE_FAv2_BWD
200194

201195
:Type: ``int`` (0 or 1)
202196
:Default: ``0``
203197
:Description: When using FusedAttention, use FlashAttention-2 implementation for the backward pass instead of the cuDNN implementation. This can be useful due to performance differences between various versions of flash-attn and FusedAttention.
204198

199+
.. envvar:: NVTE_FUSED_ATTN_CACHE_DEBUG
200+
201+
:Type: ``int`` (0, 1 or 2), optionally followed by ``:<ranks>``
202+
:Default: ``0``
203+
:Description: Log FusedAttention graph cache activity to stderr, prefixed with ``[FUSED-ATTN-CACHE]``. ``1`` prints an end-of-run summary of the cache counters and the mean time of each cuDNN build stage. ``2`` additionally traces every event as it happens: each graph built, each graph cuDNN accepts and the cache keeps, each lookup and whether it hit or missed, each first execution that compiles kernels, and each execution. When the launcher exports a rank, only rank 0 logs; append ``:<ranks>`` to override, as in ``1:all`` for level 1 on every rank or ``2:0,3`` for level 2 on ranks 0 and 3.
204+
205205
.. envvar:: NVTE_ALLOW_NONDETERMINISTIC_ALGO
206206

207207
:Type: ``int`` (0 or 1)

‎docs/examples/attention/attention.ipynb‎

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,7 @@
249249
"NVTE_DEBUG = 0/1 # disables/enables debugging\n",
250250
"NVTE_DEBUG_LEVEL = 0/1/2 # enables logging.WARNING/INFO/DEBUG-level messages\n",
251251
"```\n",
252-
"<div class=\"alert alert-info\">\n",
253-
"<b>Note:</b>\n",
254-
" \n",
255-
"These flags are supported in PyTorch only as of Transformer Engine 2.0. JAX support is expected to be added in the future.\n",
256-
"</div>"
252+
"These flags are available in both PyTorch and Jax in TE v2.20 onwards."
257253
]
258254
},
259255
{
@@ -330,6 +326,51 @@
330326
"!NVTE_DEBUG=1 NVTE_DEBUG_LEVEL=2 python example_attention.py"
331327
]
332328
},
329+
{
330+
"cell_type": "markdown",
331+
"id": "fc0c9e3d",
332+
"metadata": {},
333+
"source": [
334+
"For the FusedAttention backend, cuDNN graphs are cached and reused, and the following flag helps understand the activities taking place in the cache. `NVTE_FUSED_ATTN_CACHE_DEBUG` is supported in both PyTorch and JAX.\n",
335+
"```\n",
336+
"NVTE_FUSED_ATTN_CACHE_DEBUG = 0 # disables cache diagnostics\n",
337+
"NVTE_FUSED_ATTN_CACHE_DEBUG = 1/2:ranks # enables cache diagnostics (events)/(tracing):select ranks for information collection\n",
338+
"```\n",
339+
"At level 1, these cache events are collected and reported in the end-of-run summary: `create_graph` (number of graphs created), `cache_graph` (number of graphs cached), `hit` (number of cache hits), `miss` (number of cache misses), `build_plans` (number of graphs whose plans are built), and `execute` (number of plan executions). These event counters are tallied up per backend (f16 and fp8), per pass (forward and backward), and per thread. They help paint a picture of the graph reuse rate and caching effectiveness. Another part of the end-of-run summary are the build times of various stages of the cuDNN graph. Out of the 5 cuDNN calls, `validate`, `build_operation_graph`, `create_execution_plans`, `check_support`, and `build_plans`, `build_plans` is the most expensive one, because it is where the kernels get compiled. It happens once per eligible graph and is expected to execute many times in a real-life run.\n",
340+
"\n",
341+
"For more verbose diagnostics, level 2 enables tracing for all the events taking place in the cache. For example, for every `miss` event, a \"MISS\" line is printed in the logs, as well as the cache key that triggered it. This helps identify if the cache is processing the right config as we intended.\n",
342+
"\n",
343+
"By default, only rank 0 is enabled for both level 1 and level 2. Users can use the \"level:ranks\" format to specify a select set of ranks to collect diagnostics on. For example, \"2:0,3\" means to enable level 2 diagnostics on ranks 0 and 3. An example of the level 2 diagnostics, which also includes the level 1 summary, is as follows, for a `tests/pytorch/attention/test_attention.py::test_dot_product_attention` test.\n",
344+
"```\n",
345+
"[FUSED-ATTN-CACHE] rank=0 | tid=0 dev=0 | f16 fwd MISS | train=1 det=0 cg=0 maxlogit=0 mask=0 bias=0 wl=-1 wr=-1 brd=0 softmax=0 scale_mode=0 dropout=0 attn_scale=1 qkv_dt=5 o_dt=5 do_dt=6 dqkv_dt=6 qkv_lay=0 o_fmt=0 do_fmt=8 dqkv_lay=26 qkv_sif=8 do_sif=8 b=8 h=16 hg=16 dqk=64 dv=64 sq=128 skv=128 tq=0 tkv=0 bb=0 btq=0 btkv=0 npk=0 npv=0 psk=0 psv=0 mppk=0 mppv=0 bias_b=0 bias_h=0 bias_sq=0 bias_skv=0\n",
346+
"[FUSED-ATTN-CACHE] rank=0 | tid=0 dev=0 | f16 fwd CREATE_GRAPH | hit= 0, miss= 1, create_graph= 1, cache_graph= 0, build_plans= 0, execute= 0\n",
347+
"[FUSED-ATTN-CACHE] rank=0 | tid=0 dev=0 | f16 fwd CACHE_GRAPH | hit= 0, miss= 1, create_graph= 1, cache_graph= 1, build_plans= 0, execute= 0\n",
348+
"...\n",
349+
"[FUSED-ATTN-CACHE] rank=0 | tid=0 dev=0 | f16 fwd HIT | train=1 det=0 cg=0 maxlogit=0 mask=0 bias=0 wl=-1 wr=-1 brd=0 softmax=0 scale_mode=0 dropout=0 attn_scale=1 qkv_dt=5 o_dt=5 do_dt=6 dqkv_dt=6 qkv_lay=0 o_fmt=0 do_fmt=8 dqkv_lay=26 qkv_sif=8 do_sif=8 b=8 h=16 hg=16 dqk=64 dv=64 sq=128 skv=128 tq=0 tkv=0 bb=0 btq=0 btkv=0 npk=0 npv=0 psk=0 psv=0 mppk=0 mppv=0 bias_b=0 bias_h=0 bias_sq=0 bias_skv=0\n",
350+
"[FUSED-ATTN-CACHE] rank=0 | tid=0 dev=0 | f16 fwd BUILD_PLANS | hit= 3, miss= 1, create_graph= 1, cache_graph= 1, build_plans= 1, execute= 0\n",
351+
"...\n",
352+
"[FUSED-ATTN-CACHE] rank=0 | tid=0 dev=0 | f16 fwd EXECUTE | hit= 5, miss= 1, create_graph= 1, cache_graph= 1, build_plans= 1, execute= 1\n",
353+
"...\n",
354+
"[FUSED-ATTN-CACHE] rank=0 | ===== summary begin =====\n",
355+
"[FUSED-ATTN-CACHE] rank=0 | tid=0 dev=0 | f16 fwd | hit= 5, miss= 1, create_graph= 1, cache_graph= 1, build_plans= 1, execute= 1\n",
356+
"[FUSED-ATTN-CACHE] rank=0 | tid=0 dev=0 | f16 bwd | hit= 1, miss= 1, create_graph= 1, cache_graph= 1, build_plans= 0, execute= 0\n",
357+
"[FUSED-ATTN-CACHE] rank=0 | tid=1 dev=0 | f16 bwd | hit= 4, miss= 0, create_graph= 0, cache_graph= 0, build_plans= 1, execute= 1\n",
358+
"[FUSED-ATTN-CACHE] rank=0 | tid=all dev=all | f16 fwd | hit= 5, miss= 1, create_graph= 1, cache_graph= 1, build_plans= 1, execute= 1\n",
359+
"[FUSED-ATTN-CACHE] rank=0 | tid=all dev=all | f16 bwd | hit= 5, miss= 1, create_graph= 1, cache_graph= 1, build_plans= 1, execute= 1\n",
360+
"[FUSED-ATTN-CACHE] rank=0 | f16 fwd validate | calls=1 | time= 0.168 ms/call\n",
361+
"[FUSED-ATTN-CACHE] rank=0 | f16 fwd build_operation_graph | calls=1 | time= 11.405 ms/call\n",
362+
"[FUSED-ATTN-CACHE] rank=0 | f16 fwd create_execution_plans | calls=1 | time= 2.054 ms/call\n",
363+
"[FUSED-ATTN-CACHE] rank=0 | f16 fwd check_support | calls=1 | time= 0.044 ms/call\n",
364+
"[FUSED-ATTN-CACHE] rank=0 | f16 fwd build_plans | calls=1 | time= 327.083 ms/call\n",
365+
"[FUSED-ATTN-CACHE] rank=0 | f16 bwd validate | calls=1 | time= 0.009 ms/call\n",
366+
"[FUSED-ATTN-CACHE] rank=0 | f16 bwd build_operation_graph | calls=1 | time= 1.026 ms/call\n",
367+
"[FUSED-ATTN-CACHE] rank=0 | f16 bwd create_execution_plans | calls=1 | time= 2.874 ms/call\n",
368+
"[FUSED-ATTN-CACHE] rank=0 | f16 bwd check_support | calls=1 | time= 0.016 ms/call\n",
369+
"[FUSED-ATTN-CACHE] rank=0 | f16 bwd build_plans | calls=1 | time= 514.599 ms/call\n",
370+
"[FUSED-ATTN-CACHE] rank=0 | ===== summary end =====\n",
371+
"```"
372+
]
373+
},
333374
{
334375
"cell_type": "markdown",
335376
"id": "611d8fdb",
@@ -346,18 +387,7 @@
346387
"NVTE_FUSED_ATTN = 0 # disables cuDNN attention; default = 1\n",
347388
"```\n",
348389
"\n",
349-
"**cuDNN attention sub-backends:**\n",
350-
"This environment variable allows users to express their preference of cuDNN attention sub-backends. However, the elected sub-backend will only be used *if* it is eligible, i.e. if it has support for the provided inputs and runtime environment.\n",
351-
"```\n",
352-
"NVTE_FUSED_ATTN_BACKEND = 1/2 # user preference of cuDNN sub-backend\n",
353-
"```\n",
354-
"\n",
355-
"```\n",
356-
"<div class=\"alert alert-info\">\n",
357-
"<b>Note</b>\n",
358-
" \n",
359-
"Environment variables <code>NVTE_FLASH_ATTN</code>, <code>NVTE_UNFUSED_ATTN</code>, <code>NVTE_FUSED_ATTN_BACKEND</code>, and <code>NVTE_FUSED_ATTN_USE_FAv2_BWD</code> are supported in PyTorch. <code>NVTE_FUSED_ATTN</code> and <code>NVTE_ALLOW_NONDETERMINISTIC_ALGO</code> are supported in both PyTorch and JAX.\n",
360-
"</div>\n",
390+
"Environment variables <code>NVTE_FLASH_ATTN</code>, <code>NVTE_UNFUSED_ATTN</code>, and <code>NVTE_FUSED_ATTN_USE_FAv2_BWD</code> are supported in PyTorch. <code>NVTE_FUSED_ATTN</code> and <code>NVTE_ALLOW_NONDETERMINISTIC_ALGO</code> are supported in both PyTorch and JAX.\n",
361391
"\n",
362392
"### 2.3 Example Tests\n",
363393
"\n",

‎docs/examples/jax/attention_context_parallel.py‎

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -245,21 +245,23 @@ def context_parallel_supported() -> Tuple[bool, str]:
245245
return False, f"needs {cp_size} GPUs"
246246

247247
has_kernel = is_fused_attn_kernel_available(
248-
True,
249-
dtype,
250-
dtype,
251-
QKVLayout.THD_THD_THD,
252-
AttnBiasType.NO_BIAS,
253-
AttnMaskType.PADDING_CAUSAL_MASK,
254-
AttnSoftmaxType.VANILLA_SOFTMAX,
255-
0.0,
256-
num_query_heads,
257-
num_kv_heads,
258-
seq,
259-
seq,
260-
head_dim,
261-
head_dim,
262-
window_size,
248+
is_training=True,
249+
batch_size=batch,
250+
q_dtype=dtype,
251+
kv_dtype=dtype,
252+
qkv_layout=QKVLayout.THD_THD_THD,
253+
attn_bias_type=AttnBiasType.NO_BIAS,
254+
attn_mask_type=AttnMaskType.PADDING_CAUSAL_MASK,
255+
softmax_type=AttnSoftmaxType.VANILLA_SOFTMAX,
256+
dropout_probability=0.0,
257+
q_num_heads=num_query_heads,
258+
kv_num_heads=num_kv_heads,
259+
q_max_seqlen=seq,
260+
kv_max_seqlen=seq,
261+
head_dim_qk=head_dim,
262+
head_dim_v=head_dim,
263+
window_size=window_size,
264+
max_segments_per_seq=max_segments_per_seq,
263265
)
264266
if not has_kernel:
265267
return False, "no fused attention kernel for the THD SWA shape"

‎docs/examples/jax/test_attention.py‎

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -87,21 +87,23 @@ def _context_parallel_supported():
8787
return False, f"needs {cp_size} GPUs"
8888

8989
has_kernel = is_fused_attn_kernel_available(
90-
True,
91-
jnp.bfloat16,
92-
jnp.bfloat16,
93-
QKVLayout.THD_THD_THD,
94-
AttnBiasType.NO_BIAS,
95-
AttnMaskType.PADDING_CAUSAL_MASK,
96-
AttnSoftmaxType.VANILLA_SOFTMAX,
97-
0.0,
98-
128,
99-
8,
100-
65536,
101-
65536,
102-
128,
103-
128,
104-
(8192, 0),
90+
is_training=True,
91+
batch_size=2,
92+
q_dtype=jnp.bfloat16,
93+
kv_dtype=jnp.bfloat16,
94+
qkv_layout=QKVLayout.THD_THD_THD,
95+
attn_bias_type=AttnBiasType.NO_BIAS,
96+
attn_mask_type=AttnMaskType.PADDING_CAUSAL_MASK,
97+
softmax_type=AttnSoftmaxType.VANILLA_SOFTMAX,
98+
dropout_probability=0.0,
99+
q_num_heads=128,
100+
kv_num_heads=8,
101+
q_max_seqlen=65536,
102+
kv_max_seqlen=65536,
103+
head_dim_qk=128,
104+
head_dim_v=128,
105+
window_size=(8192, 0),
106+
max_segments_per_seq=4,
105107
)
106108
if not has_kernel:
107109
return False, "no fused attention kernel for the THD SWA shape"

‎tests/jax/test_distributed_fused_attn.py‎

Lines changed: 11 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -82,25 +82,6 @@ def impl_test_self_attn(
8282
is_training = True
8383
batch, seqlen, num_head, hidden = data_shape
8484

85-
if not is_fused_attn_kernel_available(
86-
is_training,
87-
dtype,
88-
dtype,
89-
QKVLayout.BS3HD,
90-
attn_bias_type,
91-
attn_mask_type,
92-
softmax_type,
93-
dropout_prob,
94-
num_head,
95-
num_head,
96-
seqlen,
97-
seqlen,
98-
hidden,
99-
hidden,
100-
None, # no window
101-
):
102-
pytest.skip("No FusedAttn backend found")
103-
10485
col_ref = self.generate_collectives_count_ref(
10586
mesh_shape,
10687
mesh_axes,
@@ -234,25 +215,6 @@ def test_cross_attn(
234215

235216
batch, seqlen, num_head, hidden = data_shape
236217

237-
if not is_fused_attn_kernel_available(
238-
is_training,
239-
dtype,
240-
dtype,
241-
QKVLayout.BSHD_BS2HD,
242-
attn_bias_type,
243-
attn_mask_type,
244-
softmax_type,
245-
dropout_prob,
246-
num_head,
247-
num_head,
248-
seqlen,
249-
seqlen,
250-
hidden,
251-
hidden,
252-
None, # no window
253-
):
254-
pytest.skip("No FusedAttn backend found")
255-
256218
col_ref = self.generate_collectives_count_ref()
257219
runner = FusedAttnRunner(
258220
batch,
@@ -488,9 +450,17 @@ def impl_test_context_parallel_attn(
488450
cp_load_balanced=load_balanced,
489451
)
490452

453+
# Mirror _FusedAttnCPWithAllGatherHelper.get_adjusted_max_segments_per_seq()
454+
runner_segments = runner._get_max_segments_per_sequence()
455+
if stripe_size and cp_strategy in (CPStrategy.DEFAULT, CPStrategy.ALL_GATHER):
456+
max_segments_per_seq = runner_segments + seqlen // (stripe_size * cp_size)
457+
else:
458+
max_segments_per_seq = runner_segments
459+
491460
def check_has_backend_for_mask(mask_type):
492461
return is_fused_attn_kernel_available(
493462
is_training,
463+
batch,
494464
dtype,
495465
dtype,
496466
qkv_layout,
@@ -504,8 +474,9 @@ def check_has_backend_for_mask(mask_type):
504474
seqlen,
505475
hidden,
506476
hidden,
507-
None,
508-
) # no SWA for CP
477+
None, # no SWA for CP
478+
max_segments_per_seq=max_segments_per_seq,
479+
)
509480

510481
# For causal masking we depend on having bottom right support also.
511482
# The API does not check this and instead we rely on lower level checks to raise

0 commit comments

Comments
 (0)