Unverified Commit 8fe35402 authored by Xuehai Pan's avatar Xuehai Pan Committed by GitHub
Browse files

[CI] add `pre-commit` integration (#955)



* chore: misc cleanup

* feat: add pre-commit config

* chore: update lint dependencies

* style: fix lint issues

* feat: add pre-commit hooks

* fix: fix typos

* chore: update .gitattributes

* [Lint]: [pre-commit.ci] auto fixes [...]

* docs: update CONTRIBUTING.md

* chore: update default venv name

* chore: revert and exclude CUDA files

---------
Co-authored-by: default avatarpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
parent f8ae600c
---
BasedOnStyle: LLVM
UseTab: Never
IndentWidth: 2
ColumnLimit: 80
Language: Cpp
Standard: c++17
...@@ -14,7 +14,10 @@ insert_final_newline = true ...@@ -14,7 +14,10 @@ insert_final_newline = true
indent_size = 4 indent_size = 4
[*.{cpp,hpp,cxx,cc,c,h,cu,cuh}] [*.{cpp,hpp,cxx,cc,c,h,cu,cuh}]
indent_size = 4 indent_size = 2
[{*.cmake,CMakeLists.txt}]
indent_size = 2
[*.{yaml,yml}] [*.{yaml,yml}]
indent_size = 2 indent_size = 2
......
* text eol=lf
*.bat eol=crlf
*.svg binary
*.jpg binary
*.jpeg binary
*.png binary
*.gif binary
*.h linguist-language=C++ *.h linguist-language=C++
...@@ -26,7 +26,14 @@ nnfusion.tar.gz ...@@ -26,7 +26,14 @@ nnfusion.tar.gz
# makeenv and test intermediate files # makeenv and test intermediate files
tmp/ tmp/
.env
.envrc
.venv
env/
venv/ venv/
ENV/
env.bak/
venv.bak/
.vscode/ .vscode/
.vs/ .vs/
......
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
ci:
autofix_prs: true
autofix_commit_msg: "[Lint]: [pre-commit.ci] auto fixes [...]"
autoupdate_commit_msg: "[CI] [pre-commit.ci] autoupdate"
autoupdate_schedule: monthly
default_stages: [pre-commit, pre-push, manual]
exclude: '^(build|3rdparty)/.*$' # exclude build and 3rdparty directories
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-symlinks
- id: destroyed-symlinks
# FIXME: enable these hooks
# - id: trailing-whitespace
# - id: end-of-file-fixer
- id: check-added-large-files
- id: check-merge-conflict
fail_fast: true
# FIXME: enable these hooks
# - id: check-executables-have-shebangs
# - id: check-shebang-scripts-are-executable
- id: detect-private-key
- id: check-yaml
- id: check-toml
- id: check-ast
fail_fast: true
- id: debug-statements
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v15.0.7 # sync with requirements-lint.txt
hooks:
- id: clang-format
exclude: |
(?ix)(
^.+\.(cu|cuh)$|
^.+\.json$
)
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.0 # sync with requirements-lint.txt
hooks:
- id: ruff-check
args: [--fix, --exit-non-zero-on-fix]
- repo: https://github.com/google/yapf
rev: v0.43.0 # sync with requirements-lint.txt
hooks:
- id: yapf
args: [--recursive, --in-place]
- repo: https://github.com/codespell-project/codespell
rev: v2.4.1 # sync with requirements-lint.txt
hooks:
- id: codespell
additional_dependencies: [".[toml]"]
exclude: |
(?x)(
^.+\.(cpp|hpp|cxx|cc|c|h|cu|cuh)$|
^.+\.svg$|
^.*\brequirements\b.*\.txt$
)
...@@ -2,14 +2,19 @@ ...@@ -2,14 +2,19 @@
That would be awesome if you want to contribute something to TileLang! That would be awesome if you want to contribute something to TileLang!
- [Contributing](CONTRIBUTING.md#contributing) ### Table of Contents <!-- omit in toc --> <!-- markdownlint-disable heading-increment -->
- [Reporting Bugs](CONTRIBUTING.md#reporting-bugs)
- [Asking Questions](CONTRIBUTING.md#asking-questions)
- [Submitting Pull Requests](CONTRIBUTING.md#submitting-pull-requests)
- [Repository Setup](CONTRIBUTING.md#repository-setup)
- [Running Tests](CONTRIBUTING.md#running-tests)
## Reporting Bugs - [Report Bugs](#report-bugs)
- [Ask Questions](#ask-questions)
- [Submit Pull Requests](#submit-pull-requests)
- [Setup Development Environment](#setup-development-environment)
- [Install Develop Version](#install-develop-version)
- [Lint Check](#lint-check)
- [Test Locally](#test-locally)
- [Build Wheels](#build-wheels)
- [Documentation](#documentation)
## Report Bugs
If you run into any weird behavior while using TileLang, feel free to open a new issue in this repository! Please run a **search before opening** a new issue, to make sure that someone else hasn't already reported or solved the bug you've found. If you run into any weird behavior while using TileLang, feel free to open a new issue in this repository! Please run a **search before opening** a new issue, to make sure that someone else hasn't already reported or solved the bug you've found.
...@@ -18,35 +23,86 @@ Any issue you open must include: ...@@ -18,35 +23,86 @@ Any issue you open must include:
- Code snippet that reproduces the bug with a minimal setup. - Code snippet that reproduces the bug with a minimal setup.
- A clear explanation of what the issue is. - A clear explanation of what the issue is.
## Ask Questions
## Asking Questions
Please ask questions in issues. Please ask questions in issues.
## Submitting Pull Requests ## Submit Pull Requests
All pull requests are super welcomed and greatly appreciated! Issues in need of a solution are marked with a [`♥ help`](https://github.com/ianstormtaylor/TileLang/issues?q=is%3Aissue+is%3Aopen+label%3A%22%E2%99%A5+help%22) label if you're looking for somewhere to start. All pull requests are super welcomed and greatly appreciated! Issues in need of a solution are marked with a [`♥ help`](https://github.com/ianstormtaylor/TileLang/issues?q=is%3Aissue+is%3Aopen+label%3A%22%E2%99%A5+help%22) label if you're looking for somewhere to start.
Please run `./format.sh` before submitting a pull request to make sure that your code is formatted correctly. If you're new to contributing to TileLang, you can follow the following guidelines before submitting a pull request.
> [!NOTE]
> Please include tests and docs with every pull request if applicable!
## Setup Development Environment
Before contributing to TileLang, please follow the instructions below to setup.
1. Fork TileLang ([fork](https://github.com/tile-ai/tilelang/fork)) on GitHub and clone the repository.
```bash
git clone --recurse-submodules git@github.com:<your username>/tilelang.git # use the SSH protocol
cd tilelang
git remote add upstream git@github.com:tile-ai/tilelang.git
```
2. Setup a development environment:
```bash
uv venv --seed .venv # use `python3 -m venv .venv` if you don't have `uv`
source .venv/bin/activate
python3 -m pip install --upgrade pip setuptools wheel "build[uv]"
uv pip install --requirements requirements-dev.txt
```
3. Setup the [`pre-commit`](https://pre-commit.com) hooks:
```bash
pre-commit install --install-hooks
```
Please include tests and docs with every pull request! Then you are ready to rock. Thanks for contributing to TileLang!
## Repository Setup ## Install Develop Version
To run the build, you need to have the TileLang repository cloned to your computer. After that, you need to `cd` into the directory where you cloned it, and install the dependencies with `python`: To install TileLang in an "editable" mode, run:
```bash ```bash
python setup.py install python3 -m pip install --no-build-isolation --verbose --editable .
``` ```
in the main directory. This installation is removable by:
## Running Tests ```bash
python3 -m pip uninstall tilelang
```
## Lint Check
To check the linting, run:
```bash
pre-commit run --all-files
```
## Test Locally
To run the tests, start by building the project as described in the [Repository Setup](CONTRIBUTING.md#repository-setup) section. To run the tests, start by building the project as described in the [Setup Development Environment](#setup-development-environment) section.
Then you can rerun the tests with: Then you can rerun the tests with:
```text ```bash
python -m pytest testing python3 -m pytest testing
``` ```
## Build Wheels
_TBA_
## Documentation
_TBA_
...@@ -256,4 +256,4 @@ For more advanced usage—including partial lowering, explicitly controlling thr ...@@ -256,4 +256,4 @@ For more advanced usage—including partial lowering, explicitly controlling thr
* [BitBLAS](https://github.com/tile-ai/bitblas) * [BitBLAS](https://github.com/tile-ai/bitblas)
* [Triton](https://github.com/openai/triton) * [Triton](https://github.com/openai/triton)
* [Cutlass](https://github.com/NVIDIA/cutlass) * [Cutlass](https://github.com/NVIDIA/cutlass)
* [PyCUDA](https://documen.tician.de/pycuda/) * [PyCUDA](https://documen.tician.de/pycuda/) <!-- codespell:ignore -->
...@@ -258,6 +258,7 @@ def ref_fp8_mqa_logits(q: torch.Tensor, kv: torch.Tensor, weights: torch.Tensor, ...@@ -258,6 +258,7 @@ def ref_fp8_mqa_logits(q: torch.Tensor, kv: torch.Tensor, weights: torch.Tensor,
cost = mask.sum() cost = mask.sum()
return logits, cost return logits, cost
def test_fp8_lighting_indexer(S=4096, SKV=8192, H=32, HKV=1, D=64, kv_stride=1): def test_fp8_lighting_indexer(S=4096, SKV=8192, H=32, HKV=1, D=64, kv_stride=1):
q = torch.randn(S, H, D, device="cuda", dtype=torch.bfloat16).to(torch.bfloat16) q = torch.randn(S, H, D, device="cuda", dtype=torch.bfloat16).to(torch.bfloat16)
kv = torch.randn(SKV, D, device="cuda", dtype=torch.bfloat16).to(torch.bfloat16) kv = torch.randn(SKV, D, device="cuda", dtype=torch.bfloat16).to(torch.bfloat16)
...@@ -302,5 +303,6 @@ def test_fp8_lighting_indexer(S=4096, SKV=8192, H=32, HKV=1, D=64, kv_stride=1): ...@@ -302,5 +303,6 @@ def test_fp8_lighting_indexer(S=4096, SKV=8192, H=32, HKV=1, D=64, kv_stride=1):
print(f"logits_tflops: {logits_tflops}, logits_ms: {logits_ms}") print(f"logits_tflops: {logits_tflops}, logits_ms: {logits_ms}")
print(f"cost_ref: {cost_ref}") print(f"cost_ref: {cost_ref}")
if __name__ == "__main__": if __name__ == "__main__":
test_fp8_lighting_indexer() test_fp8_lighting_indexer()
...@@ -24,6 +24,11 @@ skip = [ ...@@ -24,6 +24,11 @@ skip = [
".venv" ".venv"
] ]
[tool.ruff]
target-version = "py38"
line-length = 100
output-format = "full"
[tool.ruff.lint] [tool.ruff.lint]
select = [ select = [
# pycodestyle # pycodestyle
...@@ -48,10 +53,14 @@ ignore = [ ...@@ -48,10 +53,14 @@ ignore = [
"E741", "E741",
# line too long # line too long
"E501", "E501",
# if-else-block instead of ternary
"SIM108",
# key in dict.keys() # key in dict.keys()
"SIM118", "SIM118",
# memory leaks # memory leaks
"B019", "B019",
# zip without explicit strict
"B905",
# No such file or directory # No such file or directory
"E902", "E902",
] ]
......
# formatting # formatting
yapf==0.40.2 pre-commit
toml==0.10.2 yapf==0.43.0
tomli==2.0.1 ruff==0.14.0
ruff==0.6.5 codespell[toml]==2.4.1
codespell==2.3.0
clang-format==15.0.7 clang-format==15.0.7
clang-tidy==18.1.8 clang-tidy==18.1.8
...@@ -417,7 +417,7 @@ def patch_libs(libpath): ...@@ -417,7 +417,7 @@ def patch_libs(libpath):
subprocess.run([patchelf_path, '--set-rpath', '$ORIGIN', libpath]) subprocess.run([patchelf_path, '--set-rpath', '$ORIGIN', libpath])
class TileLangBuilPydCommand(build_py): class TileLangBuildPyCommand(build_py):
"""Customized setuptools install command - builds TVM after setting up LLVM.""" """Customized setuptools install command - builds TVM after setting up LLVM."""
def run(self): def run(self):
...@@ -643,7 +643,7 @@ class CythonExtension(Extension): ...@@ -643,7 +643,7 @@ class CythonExtension(Extension):
self.sourcedir = os.path.abspath(sourcedir) self.sourcedir = os.path.abspath(sourcedir)
class TilelangExtensionBuild(build_ext): class TileLangExtensionBuild(build_ext):
""" """
Custom build_ext command for CMake-based projects. Custom build_ext command for CMake-based projects.
...@@ -929,8 +929,8 @@ setup( ...@@ -929,8 +929,8 @@ setup(
CythonExtension("TileLangCython", sourcedir="."), CythonExtension("TileLangCython", sourcedir="."),
], ],
cmdclass={ cmdclass={
"build_py": TileLangBuilPydCommand, "build_py": TileLangBuildPyCommand,
"sdist": TileLangSdistCommand, "sdist": TileLangSdistCommand,
"build_ext": TilelangExtensionBuild, "build_ext": TileLangExtensionBuild,
}, },
) )
...@@ -588,7 +588,7 @@ Layout makeGemmVoltaABLayout(int stride, int continuous, bool is_a, ...@@ -588,7 +588,7 @@ Layout makeGemmVoltaABLayout(int stride, int continuous, bool is_a,
// ref: // ref:
// https://github.com/nvidia/cutlass/blob/ad7b2f5e84fcfa124cb02b91d5bd26d238c0459e/include/cutlass/layout/tensor_op_multiplicand_sm75.h#L54 // https://github.com/nvidia/cutlass/blob/ad7b2f5e84fcfa124cb02b91d5bd26d238c0459e/include/cutlass/layout/tensor_op_multiplicand_sm75.h#L54
// Althought the four settings (T or NT) used distinct layouts in CUTLASS, they // Although the four settings (T or NT) used distinct layouts in CUTLASS, they
// appeared to result in the same mem layout // appeared to result in the same mem layout
Layout makeTensorOpMultiplicand(int mat_stride, int mat_continuous, Layout makeTensorOpMultiplicand(int mat_stride, int mat_continuous,
int elementsize, int crosswise) { int elementsize, int crosswise) {
......
...@@ -215,9 +215,9 @@ LayoutMap ParallelOpNode::InferLayout(const LayoutInferArgs &T, ...@@ -215,9 +215,9 @@ LayoutMap ParallelOpNode::InferLayout(const LayoutInferArgs &T,
return {}; return {};
if (level == InferLevel::kStrict) { if (level == InferLevel::kStrict) {
LayoutMap results; LayoutMap results;
// Deduce buffers that shoule be complicated replicated. // Deduce buffers that should be complicated replicated.
// For example: // For example:
// for i in T.Parllel(m): // for i in T.Parallel(m):
// fragment[0] = x[i] // fragment[0] = x[i]
// then fragment[0] must be replicated on all threads. // then fragment[0] must be replicated on all threads.
for (const auto &[buffer, indices] : indice_map_) { for (const auto &[buffer, indices] : indice_map_) {
......
...@@ -2210,7 +2210,7 @@ void CodeGenTileLangCUDA::VisitExpr_(const BufferLoadNode *op, ...@@ -2210,7 +2210,7 @@ void CodeGenTileLangCUDA::VisitExpr_(const BufferLoadNode *op,
DataType element_dtype = op->buffer->dtype; DataType element_dtype = op->buffer->dtype;
int lanes = op->dtype.lanes(); int lanes = op->dtype.lanes();
// delcare type. // declare type.
if (value_dtype.lanes() == element_dtype.lanes()) { if (value_dtype.lanes() == element_dtype.lanes()) {
std::string ref = GetBufferRef(op->dtype, op->buffer.get(), index); std::string ref = GetBufferRef(op->dtype, op->buffer.get(), index);
HandleVolatileLoads(ref, op, os); HandleVolatileLoads(ref, op, os);
......
...@@ -258,7 +258,7 @@ std::string PrintArriveBarrierAsm(const std::string &barrier); ...@@ -258,7 +258,7 @@ std::string PrintArriveBarrierAsm(const std::string &barrier);
* \brief Print ptx barrier arrival with expect tx operation using * \brief Print ptx barrier arrival with expect tx operation using
* mbarrier.arrive.expect_tx \param barrier: The name of the barrier in shared * mbarrier.arrive.expect_tx \param barrier: The name of the barrier in shared
* memory. \param byte_count: Increases the tx count of the mbarrier object to * memory. \param byte_count: Increases the tx count of the mbarrier object to
* track completion of addtional async transactions. * track completion of additional async transactions.
*/ */
std::string PrintArriveBarrierExpectTxAsm(const std::string &barrier, std::string PrintArriveBarrierExpectTxAsm(const std::string &barrier,
const std::string &byte_count); const std::string &byte_count);
......
...@@ -33,8 +33,8 @@ private: ...@@ -33,8 +33,8 @@ private:
}; };
tvm::StructuralHash sh; tvm::StructuralHash sh;
tvm::StructuralEqual se; tvm::StructuralEqual se;
// grouped by expr, since the amount of varidic shape symbols is usualy much // grouped by expr, since the amount of variadic shape symbols is usually
// smaller than buffer // much smaller than buffer
std::vector<Item> items; std::vector<Item> items;
// hash => index in items // hash => index in items
std::unordered_map<size_t, std::vector<size_t>> buckets; std::unordered_map<size_t, std::vector<size_t>> buckets;
......
...@@ -243,9 +243,9 @@ private: ...@@ -243,9 +243,9 @@ private:
std::vector<PrimExpr> conditions_; std::vector<PrimExpr> conditions_;
}; };
class VectorizedConditionExtracter : public StmtExprVisitor { class VectorizedConditionExtractor : public StmtExprVisitor {
public: public:
VectorizedConditionExtracter() = default; VectorizedConditionExtractor() = default;
std::vector<PrimExpr> GetConditions(const Stmt &body) { std::vector<PrimExpr> GetConditions(const Stmt &body) {
this->VisitStmt(body); this->VisitStmt(body);
return conditions_; return conditions_;
...@@ -268,6 +268,9 @@ private: ...@@ -268,6 +268,9 @@ private:
std::vector<PrimExpr> conditions_; std::vector<PrimExpr> conditions_;
}; };
// backward-compatibility: extracter -> extractor
using VectorizedConditionExtracter = VectorizedConditionExtractor;
class NestedLoopChecker : public StmtExprVisitor { class NestedLoopChecker : public StmtExprVisitor {
public: public:
NestedLoopChecker() : loop_num_(0) {} NestedLoopChecker() : loop_num_(0) {}
...@@ -391,8 +394,8 @@ private: ...@@ -391,8 +394,8 @@ private:
vmap.Set(fnode->loop_var, outer_var * vector_size_ + inner_var); vmap.Set(fnode->loop_var, outer_var * vector_size_ + inner_var);
Stmt body = Substitute(fnode->body, vmap); Stmt body = Substitute(fnode->body, vmap);
VectorizedConditionExtracter extracter; VectorizedConditionExtractor extractor;
std::vector<PrimExpr> conditions = extracter.GetConditions(body); std::vector<PrimExpr> conditions = extractor.GetConditions(body);
VectorizedConditionMutator condition_mutator(inner_var, vector_size_); VectorizedConditionMutator condition_mutator(inner_var, vector_size_);
......
...@@ -64,7 +64,7 @@ class LibraryGenerator(object): ...@@ -64,7 +64,7 @@ class LibraryGenerator(object):
verbose = self.verbose verbose = self.verbose
if is_cuda_target(target): if is_cuda_target(target):
from tilelang.env import CUTLASS_INCLUDE_DIR from tilelang.env import CUTLASS_INCLUDE_DIR
src = tempfile.NamedTemporaryFile(mode="w", suffix=".cu", delete=False) src = tempfile.NamedTemporaryFile(mode="w", suffix=".cu", delete=False) # noqa: SIM115
target_arch = get_target_arch(get_target_compute_version(target)) target_arch = get_target_arch(get_target_compute_version(target))
libpath = src.name.replace(".cu", ".so") libpath = src.name.replace(".cu", ".so")
...@@ -111,7 +111,7 @@ class LibraryGenerator(object): ...@@ -111,7 +111,7 @@ class LibraryGenerator(object):
elif is_hip_target(target): elif is_hip_target(target):
from tilelang.env import COMPOSABLE_KERNEL_INCLUDE_DIR from tilelang.env import COMPOSABLE_KERNEL_INCLUDE_DIR
src = tempfile.NamedTemporaryFile(mode="w", suffix=".cpp", delete=False) src = tempfile.NamedTemporaryFile(mode="w", suffix=".cpp", delete=False) # noqa: SIM115
libpath = src.name.replace(".cpp", ".so") libpath = src.name.replace(".cpp", ".so")
rocm_path = find_rocm_path() rocm_path = find_rocm_path()
arch = get_rocm_arch(rocm_path) arch = get_rocm_arch(rocm_path)
...@@ -128,7 +128,7 @@ class LibraryGenerator(object): ...@@ -128,7 +128,7 @@ class LibraryGenerator(object):
] ]
elif is_cpu_target(target): elif is_cpu_target(target):
from tilelang.contrib.cc import get_cplus_compiler from tilelang.contrib.cc import get_cplus_compiler
src = tempfile.NamedTemporaryFile(mode="w", suffix=".cpp", delete=False) src = tempfile.NamedTemporaryFile(mode="w", suffix=".cpp", delete=False) # noqa: SIM115
libpath = src.name.replace(".cpp", ".so") libpath = src.name.replace(".cpp", ".so")
command = [get_cplus_compiler(), "-std=c++17", "-fPIC", "-shared", src.name] command = [get_cplus_compiler(), "-std=c++17", "-fPIC", "-shared", src.name]
...@@ -228,7 +228,7 @@ class PyLibraryGenerator(LibraryGenerator): ...@@ -228,7 +228,7 @@ class PyLibraryGenerator(LibraryGenerator):
verbose = self.verbose verbose = self.verbose
if is_cuda_target(target): if is_cuda_target(target):
from tilelang.env import (CUDA_HOME, CUTLASS_INCLUDE_DIR, TILELANG_TEMPLATE_PATH) from tilelang.env import (CUDA_HOME, CUTLASS_INCLUDE_DIR, TILELANG_TEMPLATE_PATH)
src = tempfile.NamedTemporaryFile(mode="w", suffix=".cu", delete=False) src = tempfile.NamedTemporaryFile(mode="w", suffix=".cu", delete=False) # noqa: SIM115
libpath = src.name.replace(".cu", ".cubin") libpath = src.name.replace(".cu", ".cubin")
project_root = osp.join(osp.dirname(__file__), "..", "..") project_root = osp.join(osp.dirname(__file__), "..", "..")
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment