ref(upstream): FULL TREE — Deep-Spark xllm (1470) + ds_vllm csrc/models (703)
Replaces cherry-picked upstream_ref with complete source trees. xllm/ — Iluvatar official C++ inference engine (15MB, 1470 files) Complete: kernels → layers → models → runtime → scheduler → api Excluded: .git, binary images, third_party submodule checkouts ds_vllm/ — Iluvatar official vllm fork (8MB, 703 files) Included: csrc/ (ALL CUDA kernels), fused_moe/, qwen3_5 model, _custom_ops Excluded: tests, benchmarks, docs, examples (not needed for reference) Critical call chains now fully traceable: MoE: moe_topk_softmax_kernels.cuh → ixformer.h → fused_moe.cpp → layer GDN: qwen3_gated_delta_net_base.cpp → qwen3_5_gated_delta_net.cpp Attention: ixformer.h → xllm_paged_attention → attention.cpp
This commit is contained in:
48
upstream_ref/xllm/.agents/skills/add-unit-test/SKILL.md
Normal file
48
upstream_ref/xllm/.agents/skills/add-unit-test/SKILL.md
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
name: add-unit-test
|
||||
description: Add or update xLLM unit tests in the repository. Use when Codex needs to create a new C++/CUDA/NPU/MLU unit test, place a test under tests/, wire it into CMake with cc_test, update an existing test target, choose platform gates, or validate test naming and dependencies against current xLLM test conventions.
|
||||
---
|
||||
|
||||
# Add Unit Test
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Inspect the production code and the nearest existing tests before writing a new test.
|
||||
- Match the production path under `xllm/` to `tests/` where possible.
|
||||
- Prefer extending an existing nearby `*_test.cpp` and `cc_test` target when the behavior belongs to the same domain.
|
||||
- Create a new test source only when it improves isolation, keeps platform setup separate, or follows an existing directory pattern.
|
||||
|
||||
2. Read the project style guide before editing production files under `xllm/`, and apply the same C++ style discipline to new test code:
|
||||
`.agents/skills/code-review/references/custom-code-style.md`.
|
||||
|
||||
3. Follow the current test layout and CMake conventions.
|
||||
- Read [xllm-test-patterns.md](references/xllm-test-patterns.md) when adding a new test file, new `cc_test`, platform-specific test, or test directory.
|
||||
- Use `*_test.cpp` for C++ test files and `*_test.cu` for CUDA source tests.
|
||||
- Do not create nested `test/` or `tests/` directories for new unit tests unless the surrounding tree already requires that structure.
|
||||
|
||||
4. Wire tests through CMake with `include(cc_test)` and `cc_test(...)`.
|
||||
- Keep source names relative to the current test directory unless an existing target already uses an absolute source path for a production `.cpp`.
|
||||
- Use target names ending in `_test`.
|
||||
- Put platform-directory gates in the parent `CMakeLists.txt` when the whole child directory is platform-specific.
|
||||
- Use target-level `if(USE_NPU)`, `if(USE_MLU)`, `if(USE_CUDA)`, or generator expressions only when a mixed directory contains both generic and platform-specific tests.
|
||||
|
||||
5. Write tests for observable behavior, not implementation trivia.
|
||||
- Cover success, edge, and error paths touched by the change.
|
||||
- Prefer deterministic inputs, fixed seeds, and small tensors/data structures.
|
||||
- Keep helpers file-local in an anonymous namespace unless shared by multiple test files.
|
||||
- Use `TEST`/`TEST_F` names that describe behavior clearly.
|
||||
|
||||
6. Validate narrowly before finishing.
|
||||
- Always run `git diff --check` for the changed test paths.
|
||||
- Search for stale filenames after moving or renaming tests.
|
||||
- Run the narrowest build/test command available locally; if not feasible, state the exact reason and what was checked instead.
|
||||
|
||||
## Common Commands
|
||||
|
||||
```bash
|
||||
rg --files tests/<area>
|
||||
rg "old_test_name|old_file_name" tests xllm CMakeLists.txt
|
||||
git diff --check -- tests/<area>
|
||||
```
|
||||
|
||||
For full remote validation on the development machine, use the repository AGENTS instructions for SSH, container, build, and test commands.
|
||||
@@ -0,0 +1,124 @@
|
||||
# xLLM Unit Test Patterns
|
||||
|
||||
Use this reference when creating or changing unit tests under `tests/`.
|
||||
|
||||
## Layout
|
||||
|
||||
- Mirror production structure where practical:
|
||||
- `xllm/core/framework/tokenizer` -> `tests/core/framework/tokenizer`
|
||||
- `xllm/core/layers/mlu` -> `tests/core/layers/mlu`
|
||||
- `xllm/function_call/...` -> `tests/function_call/...`
|
||||
- Keep tests directly in the relevant leaf directory.
|
||||
- Avoid new nested `test/` or `tests/` directories. Recent cleanup moved those tests into their parent directories.
|
||||
- Shared helpers may live beside tests, such as `tests/core/layers/mlu/tests_utils.cpp`.
|
||||
|
||||
## Naming
|
||||
|
||||
- Test source files use singular suffixes:
|
||||
- C++: `thing_test.cpp`
|
||||
- CUDA source: `thing_test.cu`
|
||||
- Test CMake target names also end in `_test`.
|
||||
- If a target aggregates several source files, keep the target name at the domain level, for example `layer_test`, `moe_layer_test`, or `sampler_test`.
|
||||
- Keep helper files out of the `*_test.cpp` suffix unless they define tests.
|
||||
|
||||
## CMake Basics
|
||||
|
||||
Use `cc_test` for C++/CUDA unit test binaries:
|
||||
|
||||
```cmake
|
||||
include(cc_test)
|
||||
|
||||
cc_test(
|
||||
NAME
|
||||
feature_test
|
||||
SRCS
|
||||
feature_test.cpp
|
||||
DEPS
|
||||
:feature
|
||||
GTest::gtest_main
|
||||
glog::glog
|
||||
)
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- Add `include(cc_test)` in each CMake file that declares `cc_test`.
|
||||
- Use dependencies that match nearby tests first.
|
||||
- Prefer `GTest::gtest_main`; add `GTest::gtest` only when nearby tests need it or the target explicitly uses it.
|
||||
- Add `target_link_libraries(...)` and `add_dependencies(...)` after `cc_test` when needed for `brpc`, `OpenSSL`, `protobuf`, platform runtime libraries, or link-group handling.
|
||||
- Use `:target_name` for local production CMake targets where existing tests do so.
|
||||
|
||||
## Platform Gates
|
||||
|
||||
Gate entire platform-only directories in the parent `CMakeLists.txt`.
|
||||
|
||||
Current examples:
|
||||
|
||||
```cmake
|
||||
if(USE_CUDA)
|
||||
add_subdirectory(cuda)
|
||||
endif()
|
||||
|
||||
if(USE_NPU)
|
||||
add_subdirectory(npu)
|
||||
endif()
|
||||
```
|
||||
|
||||
```cmake
|
||||
if(USE_CUDA)
|
||||
add_subdirectory(cuda)
|
||||
endif()
|
||||
|
||||
if(USE_MLU)
|
||||
add_subdirectory(mlu)
|
||||
endif()
|
||||
```
|
||||
|
||||
Do not repeat the same platform `if(...)` inside every child CMake file when the parent already gates the directory.
|
||||
|
||||
Use target-level platform gates only for mixed directories where generic and platform-specific tests coexist, such as `tests/core/runtime` or framework directories with both generic and NPU-only targets.
|
||||
|
||||
Use generator expressions for platform-specific optional link libraries when the target exists across platforms:
|
||||
|
||||
```cmake
|
||||
target_link_libraries(example_test
|
||||
PUBLIC
|
||||
Python::Python
|
||||
$<$<BOOL:${USE_NPU}>:ascendcl>
|
||||
$<$<BOOL:${USE_NPU}>:hccl>
|
||||
$<$<BOOL:${USE_NPU}>:c_sec>)
|
||||
```
|
||||
|
||||
## Source Style
|
||||
|
||||
- Add the xLLM copyright header to new files, using the current year.
|
||||
- Include `<gtest/gtest.h>` in every test source.
|
||||
- Use project-root-relative includes; avoid `../` includes.
|
||||
- Put file-local helpers in an anonymous namespace.
|
||||
- Prefer fixed-width integers (`int32_t`, `int64_t`) unless an API requires plain `int`.
|
||||
- Use `static_cast`, `nullptr`, braces on all control statements, and concise comments only where they clarify test setup.
|
||||
- Keep deterministic random or tensor tests seeded with stable labels or fixed seeds.
|
||||
|
||||
## Test Design
|
||||
|
||||
- Test behavior through public or stable internal interfaces used by nearby tests.
|
||||
- Cover the regression or edge case that motivated the test.
|
||||
- For parser and pure logic tests, keep inputs small and assert exact outputs/errors.
|
||||
- For tensor/device tests, keep tensor shapes small, check dtype/device expectations, and compare against a simple reference implementation.
|
||||
- For forked-process or device-init-sensitive tests, follow nearby standalone target patterns and leave a short CMake comment explaining why the target is isolated.
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
Before finishing:
|
||||
|
||||
```bash
|
||||
rg --files tests/<area>
|
||||
rg "old_file_name|old_target_name" tests xllm CMakeLists.txt
|
||||
git diff --check -- tests/<area>
|
||||
```
|
||||
|
||||
Run the narrowest feasible validation:
|
||||
|
||||
- Local CMake/build target if available.
|
||||
- `python setup.py test` in the project container when full validation is requested or risk is high.
|
||||
- For development-machine validation, follow the repo AGENTS instructions for `ssh gpu-h800-195`, `/export/home/zhangxu709/xllm`, container `zx-xllm-cuda`, and the build/test commands.
|
||||
115
upstream_ref/xllm/.agents/skills/code-review/SKILL.md
Normal file
115
upstream_ref/xllm/.agents/skills/code-review/SKILL.md
Normal file
@@ -0,0 +1,115 @@
|
||||
---
|
||||
name: code-review
|
||||
description: Review code changes for quality, security, performance, and correctness following project-specific standards. Use when reviewing pull requests, examining git diffs, or when the user asks for a code review. This skill should be used proactively — when the user asks for a review without specifying commits, automatically detect the current branch and diff against the main branch.
|
||||
---
|
||||
|
||||
# Code Review
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1: Determine the diff
|
||||
|
||||
If the user provides explicit SHAs or a PR link, use those. Otherwise, **auto-detect**:
|
||||
|
||||
```bash
|
||||
# Fetch latest remote state
|
||||
git fetch origin main --quiet
|
||||
|
||||
# Detect current branch
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
|
||||
# Find the merge base with origin/main
|
||||
MERGE_BASE=$(git merge-base origin/main HEAD)
|
||||
|
||||
# Show what changed
|
||||
git diff --stat $MERGE_BASE..HEAD
|
||||
git diff $MERGE_BASE..HEAD
|
||||
```
|
||||
|
||||
If `CURRENT_BRANCH` is `main`, warn the user and ask which commits to review.
|
||||
|
||||
### Step 2: Read project standards
|
||||
|
||||
Read [custom-code-style.md](references/custom-code-style.md) for project-specific coding style.
|
||||
|
||||
### Step 3: Review against the checklist
|
||||
|
||||
**Correctness:**
|
||||
- Logic handles edge cases and boundary conditions
|
||||
- Error handling is comprehensive (no silent failures)
|
||||
- Type safety maintained (no unsafe casts, proper use of `std::optional`)
|
||||
- Resource lifecycle correct (RAII, no leaks, proper cleanup order)
|
||||
|
||||
**Architecture:**
|
||||
- Clean separation of concerns, no layer violations
|
||||
- Dependencies flow in the correct direction
|
||||
- Changes align with existing patterns in the codebase
|
||||
- No unnecessary coupling introduced
|
||||
|
||||
**Performance & Concurrency:**
|
||||
- No performance regressions on hot paths
|
||||
- Thread safety: proper locking, no data races
|
||||
- CUDA/NPU kernels: memory coalescing, occupancy, sync correctness
|
||||
- No unnecessary copies of large objects (tensors, vectors)
|
||||
|
||||
**Testing:**
|
||||
- Tests verify actual logic, not just mock wiring
|
||||
- Edge cases and error paths covered
|
||||
- Integration tests for cross-component changes
|
||||
|
||||
**Production Readiness:**
|
||||
- Backward compatibility maintained (or breaking changes documented)
|
||||
- Migration strategy for schema/config changes
|
||||
- No hardcoded values that should be configurable
|
||||
|
||||
### Step 4: Output findings
|
||||
|
||||
Use the format below.
|
||||
|
||||
## Output Format
|
||||
|
||||
### Strengths
|
||||
[Specific things done well, with file:line references]
|
||||
|
||||
### Issues
|
||||
|
||||
#### Critical (Must Fix)
|
||||
[Bugs, security holes, data loss risks, broken functionality]
|
||||
|
||||
#### Important (Should Fix)
|
||||
[Architecture problems, missing error handling, test gaps, performance issues]
|
||||
|
||||
#### Minor (Nice to Have)
|
||||
[Style, optimization opportunities, documentation improvements]
|
||||
|
||||
**Each issue must include:**
|
||||
- **File:line** reference
|
||||
- **What** is wrong
|
||||
- **Why** it matters
|
||||
- **How** to fix (if not obvious)
|
||||
|
||||
### Recommendations
|
||||
[Broader improvements for code quality, architecture, or process]
|
||||
|
||||
### Assessment
|
||||
|
||||
**Ready to merge?** [Yes / No / With fixes]
|
||||
|
||||
**Reasoning:** [1-2 sentence technical assessment]
|
||||
|
||||
## Rules
|
||||
|
||||
**DO:**
|
||||
- Apply project-specific style from [custom-code-style.md](references/custom-code-style.md)
|
||||
- Follow DDD (Domain Driven Design) principles, and keep the codebase clean and maintainable
|
||||
- Categorize by actual severity (not everything is Critical)
|
||||
- Be specific with file:line references
|
||||
- Explain WHY issues matter
|
||||
- Acknowledge strengths
|
||||
- Give a clear verdict
|
||||
|
||||
**DON'T:**
|
||||
- Approve without thorough review
|
||||
- Mark nitpicks as Critical
|
||||
- Give feedback on code not in the diff
|
||||
- Be vague (e.g., "improve error handling" without specifics)
|
||||
@@ -0,0 +1,316 @@
|
||||
# Custom Code Style
|
||||
|
||||
Project-specific coding style for xllm. The reviewer **MUST** enforce these style.
|
||||
|
||||
---
|
||||
|
||||
## 1. Naming Conventions
|
||||
|
||||
### C++
|
||||
|
||||
| Element | Style | Example |
|
||||
|------------------|------------------------------------|--------------------------------------|
|
||||
| Namespace | `snake_case` | `xllm`, `xllm::detail` |
|
||||
| Class / Struct | `PascalCase` | `LlmModelImplBase`, `KVCache` |
|
||||
| Function | `snake_case` | `get_input_embeddings`, `forward` |
|
||||
| Member variable | `snake_case_` (trailing underscore)| `model_type_`, `embed_tokens_` |
|
||||
| Local variable | `snake_case` | `inputs_embeds`, `kv_caches` |
|
||||
| Constant | `k` + `PascalCase` | `kContentLength`, `kMaxBatchSize` |
|
||||
| Enum type | `PascalCase` | `EngineType`, `DeviceType` |
|
||||
| Enum value | `ALL_CAPS` | `LLM`, `VLM`, `INVALID` |
|
||||
| Template param | `PascalCase` | `DecoderLayerType` |
|
||||
| Macro | `ALL_CAPS` | `XLLM_CHECK`, `LOG_EVERY_N` |
|
||||
| File name | `snake_case` | `llm_model_base.h`, `types.h` |
|
||||
| Header guard | `#pragma once` | - |
|
||||
|
||||
### Python
|
||||
|
||||
| Element | Style | Example |
|
||||
|------------------|------------------------|--------------------------------------|
|
||||
| Module / file | `snake_case` | `model_loader.py` |
|
||||
| Class | `PascalCase` | `TokenizerConfig` |
|
||||
| Function | `snake_case` | `load_model` |
|
||||
| Variable | `snake_case` | `batch_size` |
|
||||
| Constant | `ALL_CAPS` | `MAX_SEQ_LEN` |
|
||||
| Private member | `_leading_underscore` | `_internal_state` |
|
||||
|
||||
---
|
||||
|
||||
## 2. File & Header Rules
|
||||
|
||||
- **Copyright header required** on all new files. Use the correct year matching the file creation date.
|
||||
|
||||
```cpp
|
||||
/* Copyright 2025 The xLLM Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
...
|
||||
==============================================================================*/
|
||||
```
|
||||
|
||||
- **No relative paths in `#include`**. Always use project-root-relative paths.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
#include "core/common/types.h"
|
||||
|
||||
// Bad
|
||||
#include "../common/types.h"
|
||||
#include "./types.h"
|
||||
```
|
||||
|
||||
- **Remove redundant and duplicate includes**. Each header should be included exactly once, and unused includes must be cleaned up.
|
||||
|
||||
---
|
||||
|
||||
## 3. Type System & Declarations
|
||||
|
||||
- **Use fixed-width integers** (`int32_t`, `int64_t`) instead of plain `int`, unless the API you are calling explicitly requires `int`.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
int32_t batch_size = 16;
|
||||
int64_t total_tokens = 0;
|
||||
|
||||
// Bad
|
||||
int batch_size = 16;
|
||||
```
|
||||
|
||||
- **Use `static_cast`** for all type conversions. Never use C-style casts.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
auto len = static_cast<int32_t>(vec.size());
|
||||
|
||||
// Bad
|
||||
auto len = (int32_t)vec.size();
|
||||
```
|
||||
|
||||
- **Do not use `auto` for simple/primitive types**. `auto` is acceptable for complex types (iterators, lambdas, template-deduced types) but not for `int32_t`, `float`, `bool`, `std::string`, etc.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
int32_t count = 0;
|
||||
auto it = map.find(key); // complex iterator type, auto is fine
|
||||
|
||||
// Bad
|
||||
auto count = 0;
|
||||
auto name = std::string("model");
|
||||
```
|
||||
|
||||
- **Use `using` instead of `typedef`** for type aliases. Prefer aliases for complex types to improve readability.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
using TensorVec = std::vector<torch::Tensor>;
|
||||
using CallbackFn = std::function<void(int32_t)>;
|
||||
|
||||
// Bad
|
||||
typedef std::vector<torch::Tensor> TensorVec;
|
||||
```
|
||||
|
||||
- **Use `enum class`** instead of plain `enum` to provide type safety and prevent implicit conversions.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
enum class DeviceType : int8_t { CPU = 0, CUDA = 1, NPU = 2 };
|
||||
|
||||
// Bad
|
||||
enum DeviceType { CPU = 0, CUDA = 1, NPU = 2 };
|
||||
```
|
||||
|
||||
- **Use `nullptr`** instead of `NULL` or `0` for null pointers.
|
||||
|
||||
- **Choose the right container**: use `std::unordered_map` / `std::unordered_set` when key ordering is irrelevant (O(1) average lookup). Use `std::map` / `std::set` only when sorted iteration or key ordering is required.
|
||||
|
||||
---
|
||||
|
||||
## 4. Class Design
|
||||
|
||||
- **Mark classes `final`** if they are not designed to be inherited from.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
class TokenizerConfig final { ... };
|
||||
|
||||
// Bad – class has no virtual functions and is not intended as a base
|
||||
class TokenizerConfig { ... };
|
||||
```
|
||||
|
||||
- **Use `explicit`** on any constructor that can be invoked with a single argument. This includes multi-parameter constructors where all parameters except the first have default values.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
explicit ModelArgs(const std::string& path, int32_t num_layers = 12);
|
||||
|
||||
// Bad – allows implicit conversion from std::string
|
||||
ModelArgs(const std::string& path, int32_t num_layers = 12);
|
||||
```
|
||||
|
||||
- **Use `override`** when overriding virtual functions in derived classes. Never repeat the `virtual` keyword on overrides.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
ModelOutput forward(torch::Tensor tokens, ...) override;
|
||||
|
||||
// Bad
|
||||
virtual ModelOutput forward(torch::Tensor tokens, ...);
|
||||
```
|
||||
|
||||
- **Structs must not have member functions**. If you need methods, use a `class`. Structs are for plain data aggregation only.
|
||||
|
||||
---
|
||||
|
||||
## 5. Memory & Resource Management
|
||||
|
||||
- **Avoid raw pointers**. Prefer smart pointers (`std::unique_ptr`, `std::shared_ptr`) for ownership semantics.
|
||||
- Use `std::unique_ptr` by default (sole ownership).
|
||||
- Use `std::shared_ptr` only when shared ownership is genuinely needed.
|
||||
- Raw pointers are acceptable only for non-owning references where the lifetime is clearly managed elsewhere.
|
||||
|
||||
---
|
||||
|
||||
## 6. Scoping & Visibility
|
||||
|
||||
### C++
|
||||
|
||||
- **File-local functions and variables** (used only within a single `.cpp` file) must be placed in an **anonymous namespace**.
|
||||
|
||||
```cpp
|
||||
namespace {
|
||||
int32_t compute_padding(int32_t seq_len, int32_t alignment) {
|
||||
return (alignment - seq_len % alignment) % alignment;
|
||||
}
|
||||
} // namespace
|
||||
```
|
||||
|
||||
### Python
|
||||
|
||||
- **File-local helper functions** (not part of the public API) must be prefixed with `_`.
|
||||
- **Non-public member functions** of a class must be prefixed with `_`.
|
||||
|
||||
```python
|
||||
def _validate_config(config: dict) -> bool:
|
||||
...
|
||||
|
||||
class ModelLoader:
|
||||
def load(self, path: str) -> Model:
|
||||
self._check_path(path)
|
||||
...
|
||||
|
||||
def _check_path(self, path: str) -> None:
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Torch & Framework API Usage
|
||||
|
||||
- **Use `torch::` namespace** instead of `at::` or `c10::` wherever possible. Prefer the highest-level PyTorch C++ API.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
torch::Tensor output = torch::zeros({batch_size, hidden_dim});
|
||||
|
||||
// Bad
|
||||
at::Tensor output = at::zeros({batch_size, hidden_dim});
|
||||
c10::optional<torch::Tensor> mask = c10::nullopt; // use std::optional
|
||||
```
|
||||
|
||||
- **Use `CHECK`** (glog) instead of `TORCH_CHECK` for assertions.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
CHECK(tensor.is_contiguous()) << "Input tensor must be contiguous";
|
||||
|
||||
// Bad
|
||||
TORCH_CHECK(tensor.is_contiguous(), "Input tensor must be contiguous");
|
||||
```
|
||||
|
||||
- **Use `LOG(FATAL)`** for unrecoverable errors instead of throwing `std::runtime_error`.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
LOG(FATAL) << "Unsupported model type: " << model_type;
|
||||
|
||||
// Bad
|
||||
throw std::runtime_error("Unsupported model type: " + model_type);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Code Style & Control Flow
|
||||
|
||||
- **Always use braces `{}`** with `if`, `while`, `for`, even for single-line bodies.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
if (x > 0) {
|
||||
return x;
|
||||
}
|
||||
|
||||
// Bad
|
||||
if (x > 0) return x;
|
||||
```
|
||||
|
||||
- **Avoid `if` inside `for` loops** when possible. Prefer filtering the data beforehand or restructuring the logic (e.g., early `continue`, separate loops, `std::copy_if`).
|
||||
|
||||
- **Define variables close to first use**. Do not declare all variables at the top of a function.
|
||||
|
||||
- **Annotate constant arguments** with a comment indicating the parameter name when calling functions or constructors.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
auto layer = DecoderLayer(/*hidden_size=*/4096, /*num_heads=*/32);
|
||||
|
||||
// Bad
|
||||
auto layer = DecoderLayer(4096, 32);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. STL Best Practices
|
||||
|
||||
- **Always `reserve()` before filling a `std::vector`** when the size is known or can be estimated.
|
||||
|
||||
```cpp
|
||||
// Good
|
||||
std::vector<torch::Tensor> outputs;
|
||||
outputs.reserve(num_layers);
|
||||
for (int32_t i = 0; i < num_layers; ++i) {
|
||||
outputs.emplace_back(compute_layer(i));
|
||||
}
|
||||
|
||||
// Bad – causes multiple reallocations
|
||||
std::vector<torch::Tensor> outputs;
|
||||
for (int32_t i = 0; i < num_layers; ++i) {
|
||||
outputs.push_back(compute_layer(i));
|
||||
}
|
||||
```
|
||||
|
||||
- **Prefer `emplace_back`** over `push_back` to construct elements in-place and avoid unnecessary copies.
|
||||
|
||||
---
|
||||
|
||||
## 10. Global Flags
|
||||
|
||||
- **Do not overuse `FLAGS_` global variables**. Prefer passing configuration through constructor parameters or config structs. Only use global flags for top-level, process-wide settings.
|
||||
- **Register new flags in `help_formatter.h`**. When adding a new global flag, always add a corresponding entry in `help_formatter.h` so it appears in `--help` output.
|
||||
|
||||
---
|
||||
|
||||
## 11. Python-Specific Rules
|
||||
|
||||
- **Type annotations are required** on all function signatures (parameters and return types). Use `typing` module types where needed.
|
||||
|
||||
```python
|
||||
# Good
|
||||
def load_model(path: str, device: str = "cuda") -> nn.Module:
|
||||
...
|
||||
|
||||
# Bad
|
||||
def load_model(path, device="cuda"):
|
||||
...
|
||||
```
|
||||
|
||||
- **Private helpers**: prefix with `_` (see Section 6).
|
||||
49
upstream_ref/xllm/.agents/skills/git-workflow/SKILL.md
Normal file
49
upstream_ref/xllm/.agents/skills/git-workflow/SKILL.md
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
name: git-workflow
|
||||
description: Use when the task involves Git operations for the public xLLM repository, including choosing branch or tag names, preparing commits and pull requests, backporting fixes, checking repo-specific review expectations, or drafting commit messages from actual diffs.
|
||||
---
|
||||
|
||||
# Git Workflow
|
||||
|
||||
Use xLLM repo reality, not generic Git habits.
|
||||
|
||||
## Reference Map
|
||||
|
||||
Load only the file that matches the user's immediate Git task.
|
||||
|
||||
| File | What it is for | When to load it |
|
||||
| --- | --- | --- |
|
||||
| `references/source-of-truth.md` | Repo-specific source priority and canonical files to consult | Load first when repo docs, local state, and user wording may disagree |
|
||||
| `references/branch-naming.md` | Branch naming patterns and default branch conventions | Load when the user asks how to name a branch or which branch to branch from |
|
||||
| `references/development-flow.md` | Day-to-day fork, sync, branch, validate, and push flow | Load when the user asks for normal development steps from local change to push |
|
||||
| `references/pr-review.md` | PR targeting, PR scope, and review expectations | Load when the task is about opening a PR, choosing the target branch, or deciding who should review |
|
||||
| `references/release-layout.md` | Release branch and tag shapes used by xLLM | Load when the task mentions release branches, release tags, or patch version naming |
|
||||
| `references/backport-flow.md` | Preferred backport and hotfix flow for released lines | Load when the task mentions cherry-picks, hotfixes, or fixing an already released branch |
|
||||
| `references/commit-format.md` | Commit title/body conventions and xLLM-style examples | Load when the user asks for a commit message, commit style guidance, or message cleanup |
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Decide which subtask the user actually needs.
|
||||
2. Read `references/source-of-truth.md` when you need repo-specific confirmation.
|
||||
3. Then load only the most relevant task file from the table above.
|
||||
4. For commit message drafting, run `bash scripts/collect_git_context.sh [--staged|--all|--unstaged]` before writing the final message.
|
||||
5. Draft commit messages from the actual diff, not from filenames alone.
|
||||
6. If one diff mixes unrelated concerns, recommend splitting the commit instead of forcing one vague summary.
|
||||
7. Default PR targets to `main` unless the task is clearly a release or backport flow.
|
||||
8. For released lines, prefer landing on `main` first and then backporting unless the user explicitly wants a direct hotfix flow.
|
||||
|
||||
## Output
|
||||
|
||||
Return the smallest useful answer for the user's Git task:
|
||||
|
||||
- workflow questions: concrete branch, tag, PR, or backport steps
|
||||
- commit message requests: `<type>: <subject>` plus an optional short bullet body
|
||||
- repo-convention questions: current xLLM-specific guidance, not generic Git advice
|
||||
|
||||
## Quick Checks
|
||||
|
||||
- branch names match xLLM style such as `feat/<topic>`, `bugfix/<topic>`, or `release/vX.Y.Z`
|
||||
- PR target is `main` unless this is a release or backport task
|
||||
- commit title matches the dominant change in the diff
|
||||
- release tags use semantic versions such as `v0.9.0` or `v0.9.1`
|
||||
- owner-review expectations come from `.github/CODEOWNERS` when relevant
|
||||
@@ -0,0 +1,30 @@
|
||||
# Backport Flow
|
||||
|
||||
When a released line needs a bugfix, prefer this flow:
|
||||
|
||||
1. land the fix on `main` first unless the user explicitly needs a direct hotfix flow
|
||||
2. cherry-pick or backport the fix to the matching `release/vX.Y.Z` branch
|
||||
3. update release content as needed on that release branch
|
||||
4. create the next patch tag for that release line
|
||||
|
||||
Example shape:
|
||||
|
||||
```bash
|
||||
# land on main first
|
||||
git checkout main
|
||||
git pull --rebase upstream main
|
||||
git checkout -b bugfix/<topic>
|
||||
git commit -m "bugfix: fix <summary>."
|
||||
|
||||
# then backport
|
||||
git checkout release/v0.9.0
|
||||
git pull --rebase upstream release/v0.9.0
|
||||
git cherry-pick <bugfix_commit>
|
||||
git tag v0.9.1
|
||||
```
|
||||
|
||||
## Quick Checklist
|
||||
|
||||
- backport from a commit already landed on `main` when possible
|
||||
- cherry-pick onto the matching `release/vX.Y.Z` branch
|
||||
- use the next semantic patch tag for the release line
|
||||
@@ -0,0 +1,54 @@
|
||||
# Branch Naming
|
||||
|
||||
Use one of these branch shapes:
|
||||
|
||||
```text
|
||||
<type>/<topic>
|
||||
<namespace>/<type>/<topic>
|
||||
preview/<topic>
|
||||
release/vX.Y.Z
|
||||
```
|
||||
|
||||
Recommended lowercase branch types:
|
||||
|
||||
- `feat`: new user-visible capability or feature work
|
||||
- `bugfix`: incorrect behavior, regressions, or hot fixes
|
||||
- `refactor`: structural changes without intended behavior changes
|
||||
- `docs`: documentation-only work when a dedicated branch is useful
|
||||
- `test`: test-only work when separated from product changes
|
||||
- `perf`: runtime or memory improvements
|
||||
- `chore`: repo maintenance that does not fit the other categories
|
||||
- `build`: dependency, CI, packaging, or release tooling changes
|
||||
|
||||
Topic guidelines:
|
||||
|
||||
- use lowercase letters, numbers, and hyphens by default
|
||||
- keep the topic short, specific, and review-friendly
|
||||
- prefer nouns or short noun phrases like `scheduler`, `lm-head-new`, `npu-template`
|
||||
- avoid spaces, uppercase letters, and vague names like `misc`, `temp`, `test-branch`
|
||||
- avoid repeating the type in the topic, such as `feat/feature-x`
|
||||
- use slash-separated namespace prefixes only when the work clearly belongs to a scoped stream
|
||||
|
||||
Scoped branch guidelines:
|
||||
|
||||
- use `<namespace>/<type>/<topic>` for team-, model-, or project-scoped work such as `dsv4/feat/rope-dsv4`
|
||||
- keep the namespace stable and meaningful, not personal or temporary
|
||||
- use `preview/<topic>` only for preview-track work that intentionally aligns with preview branches upstream
|
||||
- reserve `release/vX.Y.Z` for release preparation or release-only changes
|
||||
- avoid direct development on `main` and `release/*` unless the user explicitly asks for it
|
||||
|
||||
Examples:
|
||||
|
||||
- `feat/skills`
|
||||
- `feat/lm_head_new`
|
||||
- `bugfix/scheduler`
|
||||
- `refactor/npu_template`
|
||||
- `preview/glm-5`
|
||||
- `release/v0.9.0`
|
||||
|
||||
Notes for xLLM:
|
||||
|
||||
- `main` is the default development branch
|
||||
- `feat/*`, `bugfix/*`, and `refactor/*` appear in current branch usage and are safe defaults
|
||||
- `preview/*` and `release/*` are long-lived integration branches, not ordinary personal topic branches
|
||||
- both hyphen and underscore appear in existing history, but prefer hyphens for new branch topics unless matching an established naming family
|
||||
@@ -0,0 +1,56 @@
|
||||
# Commit Format
|
||||
|
||||
Use this exact first-line format:
|
||||
|
||||
```text
|
||||
<type>: <subject>
|
||||
```
|
||||
|
||||
Allowed lowercase types:
|
||||
|
||||
- `feat`: add user-visible behavior or a new capability
|
||||
- `bugfix`: correct incorrect behavior or a regression
|
||||
- `docs`: change documentation only
|
||||
- `test`: add or update tests only
|
||||
- `refactor`: improve structure without changing intended behavior
|
||||
- `chore`: repository maintenance that does not fit the other types
|
||||
- `style`: formatting or style-only changes without logic changes
|
||||
- `revert`: revert an earlier commit
|
||||
- `perf`: improve runtime or memory behavior
|
||||
- `model`: change model definitions, checkpoints, prompts, or inference behavior
|
||||
- `build`: change build, release, or dependency wiring
|
||||
- `release`: change release versioning, release notes, or release-only metadata
|
||||
|
||||
Subject guidelines:
|
||||
|
||||
- use lowercase letters by default
|
||||
- include at least 4 words
|
||||
- end with a period
|
||||
- start with a verb like `add`, `fix`, `remove`, `refactor`, `document`
|
||||
- keep it specific enough that a reviewer understands the main change
|
||||
- avoid filler like `update`, `misc`, `stuff`, `changes`
|
||||
- describe the effect or intent, not a mechanical file list
|
||||
|
||||
Body guidelines:
|
||||
|
||||
- add a body only when the title alone is not enough
|
||||
- use short bullets for secondary details or important context
|
||||
- mention follow-up work, migration steps, or compatibility impact when relevant
|
||||
- if confidence is low because the diff is partial or noisy, say that explicitly
|
||||
|
||||
Observed xLLM-style examples:
|
||||
|
||||
- `feat: add rope_in_place tilelang kernel for npu device. (#964)`
|
||||
- `bugfix: align rec initialization flags with options. (#1142)`
|
||||
- `docs: update the document to align them with the latest code. (#1113)`
|
||||
- `refactor: extract multi-modal input processors to processors dir. (#1022)`
|
||||
- `perf: reserve vector capacity before batch push_back. (#1089)`
|
||||
- `release: update xllm release version to v0.9.0. (#1124)`
|
||||
- `feat: support qwen3.5/qwen3.5-moe mtp draft model for speculative decoding[3/N]. (#1119)`
|
||||
|
||||
Notes for xLLM:
|
||||
|
||||
- `bugfix:` appears more often than `fix:` in current history and should be the default bug-repair prefix
|
||||
- `fix:` exists in a few historical commits but is less consistent than `bugfix:`
|
||||
- PR-number suffixes like `(#1142)` are common in merged history but are optional unless the user explicitly wants them
|
||||
- staged series markers like `[1/N]` or `[3/N]` appear when a change is intentionally split across multiple commits
|
||||
@@ -0,0 +1,33 @@
|
||||
# Development Flow
|
||||
|
||||
Follow this sequence unless the user asks for a different workflow:
|
||||
|
||||
1. fork the upstream repository
|
||||
2. sync local `main` with `upstream/main`
|
||||
3. create a focused topic branch from `main`
|
||||
4. implement the change
|
||||
5. run formatting and the narrowest relevant validation
|
||||
6. commit in clear English
|
||||
7. push to the fork
|
||||
8. open a PR to upstream `main`
|
||||
|
||||
Example commands:
|
||||
|
||||
```bash
|
||||
git fetch upstream
|
||||
git checkout main
|
||||
git pull --rebase upstream main
|
||||
git checkout -b feat/<topic>
|
||||
|
||||
# after development
|
||||
git add <files>
|
||||
git commit -m "feat: add <change summary>."
|
||||
git push origin feat/<topic>
|
||||
```
|
||||
|
||||
## Quick Checklist
|
||||
|
||||
- branch from `main` unless this is a release or backport task
|
||||
- keep the branch focused on one change
|
||||
- run the narrowest relevant validation before commit
|
||||
- push to your fork before opening the PR
|
||||
@@ -0,0 +1,28 @@
|
||||
# PR And Review
|
||||
|
||||
## Pull Request Guidance
|
||||
|
||||
The public repo guidance is lightweight:
|
||||
|
||||
- `README.md` and `CONTRIBUTING.md` ask contributors to fork, create a branch, and send a pull request
|
||||
- keep PRs focused and easy to review, even though the public docs do not publish a hard line-count limit
|
||||
- write commit messages and PR descriptions in clear English
|
||||
- avoid unnecessary merge noise in branch history; prefer a clean linear history when practical
|
||||
|
||||
## Target Branch
|
||||
|
||||
- use `main` unless this is explicitly a release or backport task
|
||||
|
||||
## Review Expectations
|
||||
|
||||
Use `.github/CODEOWNERS` as the visible review signal:
|
||||
|
||||
- changes under `/xllm/` have listed code owners
|
||||
- expect owner review or owner attention for those paths
|
||||
- if the user asks who should review a change under `/xllm/`, check `CODEOWNERS`
|
||||
|
||||
## Quick Checklist
|
||||
|
||||
- PR target is `main` unless this is a backport or release task
|
||||
- PR is focused and clearly described
|
||||
- review expectations are checked through `CODEOWNERS`
|
||||
@@ -0,0 +1,15 @@
|
||||
# Release Layout
|
||||
|
||||
Observed public release layout:
|
||||
|
||||
- release branches use `release/vX.Y.Z`
|
||||
- observed release branches include `release/v0.6.0`, `release/v0.7.0`, `release/v0.8.0`, and `release/v0.9.0`
|
||||
- release notes are tracked in `RELEASE.md`
|
||||
- public tags use semantic version tags such as `v0.9.0`
|
||||
- patch tags use normal patch versions such as `v0.7.1` and `v0.7.2`, not `-rcN`
|
||||
|
||||
## Naming Guardrails
|
||||
|
||||
- do not switch to `release_0.1.0` branches unless the user explicitly wants an older internal workflow
|
||||
- do not assume `v0.1.0-rc0` style tags unless the user explicitly asks for them
|
||||
- prefer the next semantic patch tag for bugfix releases
|
||||
@@ -0,0 +1,29 @@
|
||||
# Source Of Truth
|
||||
|
||||
Use these repo files first when the user asks for xLLM-specific Git guidance:
|
||||
|
||||
- `README.md`
|
||||
- `CONTRIBUTING.md`
|
||||
- `RELEASE.md`
|
||||
- `.github/workflows/check_format.yml`
|
||||
- `.pre-commit-config.yaml`
|
||||
- `.github/CODEOWNERS`
|
||||
|
||||
Guidance priority:
|
||||
|
||||
1. direct user request
|
||||
2. current repo files and branch reality
|
||||
3. visible remote repo conventions
|
||||
4. older internal notes or remembered habits
|
||||
|
||||
When repo docs, local repo state, and user wording disagree:
|
||||
|
||||
- say the conflict explicitly
|
||||
- prefer the most concrete source available
|
||||
- avoid inventing rules that are not visible in the public repo
|
||||
|
||||
Common examples of rules you should not assume without evidence:
|
||||
|
||||
- rebase-only or squash-only merge requirements
|
||||
- mandatory reviewer counts beyond what `CODEOWNERS` implies
|
||||
- old naming patterns such as `features/*`, `release_0.1.0`, or `v0.1.0-rc0`
|
||||
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
mode="auto"
|
||||
|
||||
if [[ $# -gt 1 ]]; then
|
||||
echo "usage: $0 [--staged|--all|--unstaged]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $# -eq 1 ]]; then
|
||||
case "$1" in
|
||||
--staged)
|
||||
mode="staged"
|
||||
;;
|
||||
--all)
|
||||
mode="all"
|
||||
;;
|
||||
--unstaged)
|
||||
mode="unstaged"
|
||||
;;
|
||||
*)
|
||||
echo "unknown option: $1" >&2
|
||||
echo "usage: $0 [--staged|--all|--unstaged]" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if ! git rev-parse --show-toplevel >/dev/null 2>&1; then
|
||||
echo "not inside a git repository" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
repo_root="$(git rev-parse --show-toplevel)"
|
||||
cd "$repo_root"
|
||||
|
||||
staged_count="$(git diff --cached --name-only | wc -l | tr -d ' ')"
|
||||
untracked_files="$(git ls-files --others --exclude-standard)"
|
||||
|
||||
if [[ "$mode" == "auto" ]]; then
|
||||
if [[ "$staged_count" != "0" ]]; then
|
||||
mode="staged"
|
||||
else
|
||||
mode="all"
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$mode" in
|
||||
staged)
|
||||
status_cmd=(git diff --cached --name-status)
|
||||
stat_cmd=(git diff --cached --stat)
|
||||
patch_cmd=(git diff --cached --unified=1 --no-color)
|
||||
headline="staged changes"
|
||||
;;
|
||||
unstaged)
|
||||
status_cmd=(git diff --name-status)
|
||||
stat_cmd=(git diff --stat)
|
||||
patch_cmd=(git diff --unified=1 --no-color)
|
||||
headline="unstaged changes"
|
||||
;;
|
||||
all)
|
||||
headline="all local changes"
|
||||
;;
|
||||
*)
|
||||
echo "invalid mode: $mode" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "repo: $repo_root"
|
||||
echo "branch: $(git branch --show-current)"
|
||||
echo "scope: $headline"
|
||||
echo
|
||||
echo "status:"
|
||||
git status --short
|
||||
echo
|
||||
|
||||
if [[ -n "$untracked_files" ]]; then
|
||||
echo "untracked files:"
|
||||
printf '%s\n' "$untracked_files"
|
||||
echo
|
||||
fi
|
||||
|
||||
if [[ "$mode" == "all" ]]; then
|
||||
echo "changed files:"
|
||||
git diff HEAD --name-status
|
||||
echo
|
||||
echo "diff stat:"
|
||||
git diff HEAD --stat
|
||||
echo
|
||||
echo "patch excerpt:"
|
||||
git diff HEAD --unified=1 --no-color | sed -n '1,400p'
|
||||
else
|
||||
echo "changed files:"
|
||||
"${status_cmd[@]}"
|
||||
echo
|
||||
echo "diff stat:"
|
||||
"${stat_cmd[@]}"
|
||||
echo
|
||||
echo "patch excerpt:"
|
||||
"${patch_cmd[@]}" | sed -n '1,400p'
|
||||
fi
|
||||
1
upstream_ref/xllm/.agents/skills/tilelang-api-best-practices
Symbolic link
1
upstream_ref/xllm/.agents/skills/tilelang-api-best-practices
Symbolic link
@@ -0,0 +1 @@
|
||||
../../third_party/tilelang-ascend/.agents/skills/tilelang-custom-skill/tilelang-api-best-practices
|
||||
140
upstream_ref/xllm/.agents/skills/tilelang-ascend-kernel/SKILL.md
Normal file
140
upstream_ref/xllm/.agents/skills/tilelang-ascend-kernel/SKILL.md
Normal file
@@ -0,0 +1,140 @@
|
||||
---
|
||||
name: tilelang-ascend-kernel
|
||||
description: Use when the user wants to add, modify, debug, or review an xLLM TileLang Ascend kernel or specialization, including Python kernel definitions, generated Ascend-C source, runtime wrapper dispatch, TileLang CMake wiring, and NPU tests.
|
||||
---
|
||||
|
||||
# TileLang Ascend Kernel
|
||||
|
||||
## When to use
|
||||
|
||||
Use this skill when the task involves any of the following in the xLLM repo:
|
||||
|
||||
- `xllm/compiler/tilelang/targets/ascend/kernels/*.py`
|
||||
- `xllm/core/kernels/npu/tilelang/*_wrapper.cpp`
|
||||
- `xllm/core/kernels/npu/tilelang/CMakeLists.txt`
|
||||
- generated TileLang artifacts such as `manifest.json`, `registry.inc`, or specialization `.cpp`
|
||||
|
||||
Run build and test commands inside the NPU container.
|
||||
|
||||
Run TileLang commands from the xLLM repo root, not from an installed-package environment.
|
||||
|
||||
## Entry points and TL_ROOT
|
||||
|
||||
- Prefer `python xllm/compiler/tilelang_launcher.py ...` for end-to-end TileLang compile flows.
|
||||
- From the xLLM repo root, use `export TL_ROOT=$PWD/third_party/tilelang-ascend` for xLLM TileLang tooling and verify `test -f "$TL_ROOT/tilelang/__init__.py"`.
|
||||
- Before any raw script does `import tilelang`, run `export TL_ROOT=$PWD/third_party/tilelang-ascend && source third_party/tilelang-ascend/set_env.sh`, then execute the script.
|
||||
- Do not run kernel files directly with `python rope.py`; use module execution because these files rely on relative imports.
|
||||
- For direct kernel-script debugging, run them as modules and pass required CLI args:
|
||||
|
||||
```bash
|
||||
cd xllm
|
||||
python -m compiler.tilelang.targets.ascend.kernels.rope \
|
||||
--output ../.tmp/rope.cpp
|
||||
# Expected: [INFO] RoPE output matches torch reference
|
||||
```
|
||||
|
||||
- The same module-style rule applies to other kernel files under `xllm/compiler/tilelang/targets/ascend/kernels/`.
|
||||
|
||||
## Primary Reference And Mode Preference
|
||||
|
||||
Primary reference:
|
||||
|
||||
- `third_party/tilelang-ascend/docs/TileLang-Ascend Programming Guide.md`
|
||||
|
||||
Use `third_party/tilelang-ascend/.agents/skills/tilelang-custom-skill/tilelang-api-best-practices/references/api-tile-ops.md` when the task depends on `T.tile.xxx` semantics such as `compare`, `select`, `cast`, or other vector intrinsics.
|
||||
|
||||
Default to Expert mode for xLLM Ascend kernels:
|
||||
|
||||
- prefer `T.tile.xxx`, explicit UB/shared allocation, and explicit `T.copy`
|
||||
- prefer explicit `T.serial` control for row/block traversal
|
||||
- do not introduce Developer mode `T.Parallel` unless the kernel is a clearly tile-local element-wise expression and the change does not reduce control over UB usage, temporary buffers, or exact runtime semantics
|
||||
- when translating Triton kernels, preserve the Triton runtime semantics first, then choose the smallest Expert-mode lowering that matches them
|
||||
|
||||
## Common Triton To TileLang-Ascend Semantics
|
||||
|
||||
Use this table as the quick semantic mapping when translating Triton kernels:
|
||||
|
||||
| Triton pattern | TileLang-Ascend pattern | Notes |
|
||||
| --- | --- | --- |
|
||||
| `x + y`, `x - y`, `x * y`, `x / y` | `T.tile.add/sub/mul/div` | Prefer tile ops in Expert-style vector code instead of hand-written scalar loops. |
|
||||
| `tl.exp(x)`, `tl.log(x)`, `tl.abs(x)` | `T.tile.exp`, `T.tile.ln`, `T.tile.abs` | TileLang uses `ln`, not `log`. |
|
||||
| `x.to(tl.float32)` or `tl.cast(...)` | `T.tile.cast(dst, src, "CAST_NONE", count)` | Pick a non-default cast mode only when rounding semantics are required. |
|
||||
| `x <= y`, `x < y`, `x >= y`, `x == y` | `T.tile.compare(mask, x, y, "LE"/"LT"/"GE"/"EQ")` | `T.tile.compare` produces a bit mask, not a float tensor. |
|
||||
| `tl.where(cond, a, b)` | `T.tile.select(dst, selMask, a, b, selMode)` | API-level match. If `cond` is a comparison expression such as `x <= y`, materialize `selMask` with `T.tile.compare(...)` first; use the matching `VSEL_*` mode for tensor-tensor or tensor-scalar selection. |
|
||||
| `tl.full(shape, value, dtype)` | allocate buffer + `T.tile.fill(dst, value)` | Separate allocation from initialization. |
|
||||
| `tl.arange(0, N)` | `T.tile.createvecindex(dst, 0)` or explicit loop indices | Prefer `createvecindex` only when the kernel truly needs a vector index tensor. |
|
||||
|
||||
Rules for semantic-preserving lowering:
|
||||
|
||||
- Preserve Triton control-flow, masking, and parameter semantics. Do not substitute a numerically similar formula unless the runtime-visible behavior is unchanged for the supported input domain.
|
||||
- Keep the kernel ABI aligned with the lowering. Every runtime parameter must either participate in the TileLang implementation or be removed from the interface.
|
||||
- Add targeted tests for branch, mask, and boundary behavior. Do not rely only on random inputs if some paths are hit only under specific values.
|
||||
- Choose the correct `VSEL_*` mode based on the source operands. `VSEL_CMPMASK_SPR` is the natural match for a mask produced by `T.tile.compare`; `VSEL_TENSOR_SCALAR_MODE` and `VSEL_TENSOR_TENSOR_MODE` are for explicit tensor/scalar or tensor/tensor selection modes.
|
||||
|
||||
## New kernel
|
||||
|
||||
Follow this order:
|
||||
|
||||
1. Implement `build_<kernel>_kernel(...)`
|
||||
2. Implement `generate_source(...)`
|
||||
3. Declare `DISPATCH_SCHEMA` and `SPECIALIZATIONS`
|
||||
4. Run TileLang compilation once and inspect `registry.inc`
|
||||
5. Add or update `<kernel>_wrapper.cpp`
|
||||
6. Register the kernel in `xllm/core/kernels/npu/tilelang/CMakeLists.txt` with:
|
||||
- `tilelang_register_runtime_kernel(NAME <kernel> WRAPPER_SRCS <srcs...>)`
|
||||
|
||||
For wrapper work:
|
||||
|
||||
- do kernel precision alignment on the Python side first (`build_<kernel>_kernel(...)` / `generate_source(...)`), not in the C++ wrapper
|
||||
- handwrite tensor checks, layout transforms, and `build_runtime_specialization(...)`
|
||||
- use generated `make_<kernel>_specialization(...)` and `find_<kernel>_kernel_entry(...)`
|
||||
- do not handwrite kernel-specific specialization structs or kernel fn typedefs
|
||||
- **never use `permute`, `contiguous`, `transpose`, `reshape` (when non-trivial), `clone`, or any operation that triggers a device memory copy in the wrapper**. The wrapper must only pass pointers to existing tensors. If the kernel needs a different layout, handle it inside the kernel itself or require the caller to provide the correct layout.
|
||||
|
||||
## New specialization
|
||||
|
||||
Use this path when the kernel logic and wrapper ABI stay the same.
|
||||
|
||||
1. Update the existing kernel's `SPECIALIZATIONS`
|
||||
2. Confirm every runtime dispatch field still matches `DISPATCH_SCHEMA`
|
||||
3. Re-run TileLang compilation
|
||||
4. Check that `registry.inc` contains the new entry
|
||||
5. Check that the wrapper's `build_runtime_specialization(...)` still constructs matching values
|
||||
|
||||
## Debug generated Ascend-C
|
||||
|
||||
When the task is to inspect codegen or compare two kernel implementations, use an isolated output root:
|
||||
|
||||
```bash
|
||||
python xllm/compiler/tilelang_launcher.py compile-kernels \
|
||||
--target ascend \
|
||||
--device a3 \
|
||||
--output-root .tmp/tilelang_debug \
|
||||
--kernels <kernel> \
|
||||
--force
|
||||
```
|
||||
|
||||
Then inspect:
|
||||
|
||||
- `.tmp/tilelang_debug/targets/ascend/<kernel>/<variant_key>/<kernel>_<variant_key>_kernel.cpp`
|
||||
- `.tmp/tilelang_debug/targets/ascend/<kernel>/registry.inc`
|
||||
- `.tmp/tilelang_debug/targets/ascend/<kernel>/manifest.json`
|
||||
|
||||
Use this path before changing wrapper code when you need to understand generated symbols, field order, or ABI.
|
||||
|
||||
## Validate
|
||||
|
||||
Prefer the narrowest command first:
|
||||
|
||||
- `python -m py_compile xllm/compiler/tilelang/targets/ascend/kernels/<kernel>.py`
|
||||
- `cd xllm && python -m compiler.tilelang.targets.ascend.kernels.<kernel> --output ../.tmp/<kernel>.cpp`
|
||||
- `python xllm/compiler/tilelang_launcher.py prepare-ascend`
|
||||
- `python setup.py test --test-name <wrapper_test_target> --device npu`
|
||||
|
||||
## References
|
||||
|
||||
Read `docs/en/dev_guide/tilelang_ascend_kernel_dev.md` for mechanism details.
|
||||
Use `rope` as the concrete template:
|
||||
- `xllm/compiler/tilelang/targets/ascend/kernels/rope.py`
|
||||
- `xllm/core/kernels/npu/tilelang/rope_wrapper.cpp`
|
||||
- `xllm/core/kernels/npu/tilelang/CMakeLists.txt`
|
||||
1
upstream_ref/xllm/.agents/skills/tilelang-debug-helper
Symbolic link
1
upstream_ref/xllm/.agents/skills/tilelang-debug-helper
Symbolic link
@@ -0,0 +1 @@
|
||||
../../third_party/tilelang-ascend/.agents/skills/tilelang-custom-skill/tilelang-debug-helper
|
||||
1
upstream_ref/xllm/.agents/skills/tilelang-expert-to-developer
Symbolic link
1
upstream_ref/xllm/.agents/skills/tilelang-expert-to-developer
Symbolic link
@@ -0,0 +1 @@
|
||||
../../third_party/tilelang-ascend/.agents/skills/tilelang-custom-skill/tilelang-expert-to-developer
|
||||
Reference in New Issue
Block a user