[Ascend] Tensor.exponential_() produces 1024 NaNs for large tensors (n ≥ 65536) — breaks all LLM random sampling
Repo: https://github.com/flagos-ai/FlagGems
Summary
FlagGems' exponential_ op (flag_gems/ops/exponential_.py, Triton kernel) on
the Ascend backend writes exactly 1024 NaN values into large output tensors.
For tensors with a trailing dimension n ≥ 65536 the last (or one) 1024-element
block comes out as NaN instead of an exponential-distributed value; smaller
tensors are fine.
This silently breaks all random sampling in vLLM on Ascend. vLLM's
random_sample does q = torch.empty_like(probs); q.exponential_(); probs.div_(q).argmax(-1).
With a vocab of 151936, q gets NaNs, probs / NaN = NaN, and argmax over an
all-NaN row returns index 0 — so every sampled token is id 0 and completions
degenerate to "!!!!". Greedy decoding (pure argmax, no exponential_) is
unaffected.
Environment
| Component |
Version |
| flag_gems |
5.4.0rc2.post3+gad89ec477 |
| flagtree |
0.7.0rc2+ascend3.5 |
| vllm |
0.20.2+flagos |
| torch / torch_npu |
2.10.0 |
| CANN |
9.0.0 |
| Device |
Ascend910_9382 (910C) |
Minimal reproduction
import torch, torch_npu, flag_gems
flag_gems.enable()
d = torch.device("npu")
for n in [2048, 4096, 8192, 16384, 32768, 65536, 131072, 151936]:
q = torch.empty((1, n), dtype=torch.float32, device=d)
q.exponential_()
print(n, "nan=", int(q.isnan().sum()))
Output:
2048 nan=0
4096 nan=0
8192 nan=0
16384 nan=0
32768 nan=0 # OK up to here
65536 nan=1024 # NaNs appear
131072 nan=1024
151936 nan=1024 # real Qwen3 vocab size
The NaN count is a constant 1024 regardless of tensor size once the
threshold (somewhere in 32768 < n ≤ 65536) is crossed — pointing at a
tiling / block-boundary bug in the kernel (one 1024-element block's philox /
safe_fast_log output is not written correctly). uniform_() on the identical
tensor is fine, so this is specific to exponential_, not a general RNG or
memory-layout issue.
How it was found (in a live vLLM server)
Instrumenting random_sample in a running TP=2 server, for a
temperature=1.0 request:
[DIAG] q_dtype=float32 q_contig=True q_isnan=1024 exp_nan=1024 uni_nan=0 \
pmax=0.41 psum=1.0 pnan=0 arg=[0]
i.e. probs is correct (sums to 1, no NaN), but q from exponential_() has
1024 NaNs, so the sampled token collapses to 0. uniform_() on the same tensor
in the same process returns valid values.
Impact
No usable random sampling on Ascend for any model with a large vocab (Qwen3,
etc.). Combined with the separate Triton top-k/top-p compile crash
(FlagTree issue: _topk_topp_kernel / ConvertTritonIRToLinalgIR PassManager),
there is currently no working sampling path on this Ascend stack — only
greedy decoding works.
Ask
Fix the block-boundary handling in the Ascend exponential_ Triton kernel so
large tensors don't emit NaN. Happy to provide the dumped kernel or run further
diagnostics.
[Ascend]
Tensor.exponential_()produces 1024 NaNs for large tensors (n ≥ 65536) — breaks all LLM random samplingRepo: https://github.com/flagos-ai/FlagGems
Summary
FlagGems'
exponential_op (flag_gems/ops/exponential_.py, Triton kernel) onthe Ascend backend writes exactly 1024
NaNvalues into large output tensors.For tensors with a trailing dimension
n ≥ 65536the last (or one) 1024-elementblock comes out as
NaNinstead of an exponential-distributed value; smallertensors are fine.
This silently breaks all random sampling in vLLM on Ascend. vLLM's
random_sampledoesq = torch.empty_like(probs); q.exponential_(); probs.div_(q).argmax(-1).With a vocab of 151936,
qgets NaNs,probs / NaN = NaN, andargmaxover anall-NaN row returns index 0 — so every sampled token is id 0 and completions
degenerate to
"!!!!". Greedy decoding (pureargmax, noexponential_) isunaffected.
Environment
5.4.0rc2.post3+gad89ec4770.7.0rc2+ascend3.50.20.2+flagos2.10.09.0.0Ascend910_9382(910C)Minimal reproduction
Output:
The NaN count is a constant 1024 regardless of tensor size once the
threshold (somewhere in 32768 < n ≤ 65536) is crossed — pointing at a
tiling / block-boundary bug in the kernel (one 1024-element block's philox /
safe_fast_logoutput is not written correctly).uniform_()on the identicaltensor is fine, so this is specific to
exponential_, not a general RNG ormemory-layout issue.
How it was found (in a live vLLM server)
Instrumenting
random_samplein a running TP=2 server, for atemperature=1.0request:i.e.
probsis correct (sums to 1, no NaN), butqfromexponential_()has1024 NaNs, so the sampled token collapses to 0.
uniform_()on the same tensorin the same process returns valid values.
Impact
No usable random sampling on Ascend for any model with a large vocab (Qwen3,
etc.). Combined with the separate Triton top-k/top-p compile crash
(FlagTree issue:
_topk_topp_kernel/ConvertTritonIRToLinalgIR PassManager),there is currently no working sampling path on this Ascend stack — only
greedy decoding works.
Ask
Fix the block-boundary handling in the Ascend
exponential_Triton kernel solarge tensors don't emit NaN. Happy to provide the dumped kernel or run further
diagnostics.