linkedin / linkedin/Liger-Kernel

[RFC] Native Ascend NPU Support for Liger Kernel

Open
#954 2 comments 24 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
6.6k
Forks
603
Avg merge
1d 20h
Merged PRs (30d)
47

Description

## 1. Background & Motivation
Ascend NPU is a default PyTorch device backend, natively compatible with ecosystems like Transformers, FlagGems, and Llama Factory. We’re also enabling Triton support (repo: [triton-ascend](https://gitcode.com/Ascend/triton-ascend)).

Liger Kernel’s wide adoption has led to growing user requests for NPU support. This proposal aims to advance native adaptation, with community input welcome.

## 2. Proposed Implementation Steps
Adaptation proceeds in phases, with no breaking changes to existing devices.

### 2.1 Device Support Integration
Extend device detection logic to include NPU:
```python
def infer_device():
"""Get current device name based on available devices"""
if torch.cuda.is_available(): # Works for Nvidia/AMD
return "cuda"
elif is_npu_available(): # Ascend NPU check
return "npu"
elif torch.xpu.is_available():
return "xpu"
else:
return "cpu"
```

### 2.2 Operator Compatibility Guarantee
- **Native-run Operators**: Some (e.g., `geglu`, `fused_neighborhood_attention`) work on NPU via basic device adaptation.
- **NPU-specific Adjustments**: Partial operators need `BLOCK_SIZE` tweaks to avoid Unified Buffer (UB) overflow.

**Example: geglu Operator Modification**
Original code:
```python
@triton.jit
def _geglu_tanh_forward_kernel(a, b, c, stride, n_cols: tl.constexpr, BLOCK_SIZE: tl.constexpr):
program_id = tl.program_id(0).to(tl.int64)
a += program_id * stride
b += program_id * stride
c += program_id * stride

col_offsets = tl.arange(0, BLOCK_SIZE)
mask = col_offsets < n_cols
a_row = tl.load(a + col_offsets, mask=mask, other=0).to(tl.float32)
b_row = tl.load(b + col_offsets, mask=mask, other=0)

# GELU tanh approximation
sqrt_2_over_pi = 0.7978845608028654
a_cubed = a_row ** 3
tanh_arg = sqrt_2_over_pi * (a_row + 0.044715 * a_cubed)
c_row = 0.5 * a_row * (1 + tanh(tanh_arg)) * b_row
tl.store(c + col_offsets, c_row, mask=mask)
```

NPU-adapted code (add `BLOCK_SIZE_SUB` for UB overflow prevention):
```python
@triton.jit
def _geglu_tanh_forward_kernel(a, b, c, stride, n_cols: tl.constexpr,
BLOCK_SIZE: tl.constexpr, BLOCK_SIZE_SUB: tl.constexpr):
program_id = tl.program_id(0).to(tl.int64)
base_offset = program_id * stride
num_sub_blocks = tl.cdiv(BLOCK_SIZE, BLOCK_SIZE_SUB)

for sub_block_idx in range(num_sub_blocks):
col_offsets = tl.arange(0, BLOCK_SIZE_SUB) + sub_block_idx * BLOCK_SIZE_SUB
mask = col_offsets < n_cols

a_row = tl.load(a + base_offset + col_offsets, mask=mask, other=0).to(tl.float32)
b_row = tl.load(b + base_offset + col_offsets, mask=mask, other=0)

# GELU tanh approximation (same as original)
sqrt_2_over_pi = 0.7978845608028654
a_cubed = a_row ** 3
tanh_arg = sqrt_2_over_pi * (a_row + 0.044715 * a_cubed)
c_row = 0.5 * a_row * (1 + tanh(tanh_arg)) * b_row

tl.store(c + base_offset + col_offsets, c_row, mask=mask)
```
*Note: `BLOCK_SIZE_SUB` = `BLOCK_SIZE` for non-NPU devices.*

### 2.3 Performance Optimization
- Tune operator parameters for NPU performance.
- Future plan: Add NPU-affine APIs to `triton-ascend`.

### 2.4 CI Integration
We’re applying for NPU devices to integrate into Liger Kernel’s native CI for continuous validation.

## 3. Code Organization Proposal
NPU modifications won’t break existing code. To improve readability, we consider organizing device-specific operators into dedicated directories (referencing FlagGems):
Reference: [FlagGems Muti backend](https://github.com/flagos-ai/FlagGems/blob/master/src/flag_gems/runtime/backend/README.md)

Seeking community feedback on this approach.

## 4. Conclusion
We aim to extend Liger Kernel to Ascend NPU while ensuring compatibility/performance. Your input will help refine this initiative.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Begin with the infer_device() entry point and the geglu and fused_neighborhood_attention operators described in the proposal. Review how device-specific BLOCK_SIZE handling and NPU CI would fit the existing project, then define validation for native-run and adjusted operators; the RFC does not name files or tests, so scope and completion criteria need maintainer agreement.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, pytorch
Domain
machine-learning
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.