Conversation
pos_freq_scaling was created with .cuda(), which fails on non-CUDA accelerators such as Ascend NPU (Torch not compiled with CUDA enabled). Create it on CPU and move to seq_len's device at compute time so the DynamicNTK rotary embedding works on any backend that lmdeploy dlinfer supports (Ascend/MACA/Cambricon).
|
There may be a small performance regression here.
pos_freq_scaling = self.pos_freq_scaling.to(seq_len.device)Since the device tensor is only assigned to a local variable, this may introduce a CPU-to-device copy on every forward. This is probably negligible for prefill because the tensor is very small, but for decode it becomes a per-step overhead and may affect TPOT/ITL. Could we cache the migrated tensor, similar to how if self.pos_freq_scaling.device != seq_len.device:
self.pos_freq_scaling = self.pos_freq_scaling.to(seq_len.device)This would still avoid the CUDA hardcode while keeping the device transfer out of the steady-state decode path. |
Address review feedback: instead of migrating self.pos_freq_scaling to the target device on every forward call (creating a temporary local copy), cache it on self via lazy migration so the per-step overhead is eliminated. Aligns with how self.inv_freq is already handled in forward().
|
Thanks for the careful review @wanfengcxz. Good catch on the per-step device copy. Fixed in if self.pos_freq_scaling.device != seq_len.device:
self.pos_freq_scaling = self.pos_freq_scaling.to(seq_len.device) |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
No unresolved issues were identified, and CUDA behavior is preserved.
Review effort: Lite
Findings: None
What changed in this PR
This PR removes a hardcoded CUDA dependency from dlinfer’s dynamic NTK rotary embedding, enabling non-CUDA accelerator support.
Changes:
- Initializes frequency scaling on CPU.
- Moves it to the runtime device during computation.
- Preserves CUDA behavior.
| File | Description |
|---|---|
lmdeploy/pytorch/backends/dlinfer/rotary_embedding.py |
Makes NTK frequency scaling device-agnostic. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Summary
The
DlinferLlamaDynamicNTKScalingRotaryEmbeddingindlinfer/rotary_embedding.pycreated itspos_freq_scalingtensor with a hardcoded.cuda()call:This crashes on any non-CUDA accelerator that lmdeploy's dlinfer backend supports (Ascend NPU, MACA, Cambricon) with
Torch not compiled with CUDA enabled, because those devices are not CUDA.Change
pos_freq_scalingon CPU (device-agnostic).seq_len.deviceat compute time inside_ntk_inv_freq, mirroring howinv_freqis already handled (moved tox.deviceinforward).This makes the DynamicNTK rotary embedding work on Ascend/MACA/Cambricon while keeping behavior identical on CUDA.
Verification
On an Ascend NPU (torch 2.14.0a0 + CANN):
.cuda()raisesAssertionError: Torch not compiled with CUDA enabledon NPU.npudevice, and the NTK computation runs correctly on NPU.No functional change on CUDA (tensor is moved to the same device as before).