diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a9e8a6d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,44 @@ +# https://editorconfig.org/ + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{py,pyi}] +indent_size = 4 + +[*.{cpp,hpp,cxx,cc,c,h,cu,cuh}] +indent_size = 2 + +[{*.cmake,CMakeLists.txt}] +indent_size = 2 + +[*.{yaml,yml}] +indent_size = 2 + +[.clang-{format,tidy}] +indent_size = 2 + +[Makefile] +indent_style = tab + +[*.sh] +indent_size = 4 + +[*.bat] +indent_size = 4 +end_of_line = crlf + +[*.md] +indent_size = 2 +x-soft-wrap-text = true + +[*.rst] +indent_size = 4 +x-soft-wrap-text = true diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..bbb14db --- /dev/null +++ b/.gitattributes @@ -0,0 +1,10 @@ +* text eol=lf +*.bat eol=crlf + +*.svg binary +*.jpg binary +*.jpeg binary +*.png binary +*.gif binary + +*.h linguist-language=C++ diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..0f0d8f8 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + time: "12:00" + timezone: "Asia/Shanghai" + commit-message: + prefix: "[CI]" + diff --git a/.github/workflows/pr-perfbench-bot.yml b/.github/workflows/pr-perfbench-bot.yml index c1a357a..a3177d0 100644 --- a/.github/workflows/pr-perfbench-bot.yml +++ b/.github/workflows/pr-perfbench-bot.yml @@ -7,6 +7,8 @@ on: permissions: contents: read + issues: write + pull-requests: write concurrency: group: "${{ github.workflow }}-${{ github.ref }}" diff --git a/.github/workflows/pr-reminder-bot.yml b/.github/workflows/pr-reminder-bot.yml index 5689c84..799a149 100644 --- a/.github/workflows/pr-reminder-bot.yml +++ b/.github/workflows/pr-reminder-bot.yml @@ -5,6 +5,10 @@ on: types: - opened +permissions: + issues: write + pull-requests: write + jobs: remind: runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index 04b265a..9db0810 100755 --- a/.gitignore +++ b/.gitignore @@ -50,4 +50,4 @@ kernel_diff_analysis.md tilelang_optimization_analysis.md boundary_check_comparison.md GITHUB_ISSUE.md -Tilelang-failed_test_cases \ No newline at end of file +Tilelang-failed_test_cases/ \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..f52f91b --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,59 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +ci: + autofix_prs: false + 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 + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-added-large-files + - id: check-merge-conflict + fail_fast: true + - 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 + - id: file-contents-sorter + args: [--ignore-case] + files: ^docs/spelling_wordlist\.txt$ + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v21.1.7 # sync with requirements-lint.txt + hooks: + - id: clang-format + types_or: [c++, c] + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.14.9 # sync with requirements-lint.txt + hooks: + - id: ruff-check + args: [--fix, --exit-non-zero-on-fix] + - id: ruff-format + args: [--exit-non-zero-on-format] + - 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$ + ) + - repo: https://github.com/jackdewinter/pymarkdown + rev: v0.9.33 + hooks: + - id: pymarkdown + args: ["--config", ".pymarkdown", "fix"] diff --git a/.pymarkdown b/.pymarkdown new file mode 100644 index 0000000..5394265 --- /dev/null +++ b/.pymarkdown @@ -0,0 +1,37 @@ +{ + "plugins": { + "md003": { + "style": "atx" + }, + "md004": { + "style": "dash" + }, + "md013": { + "enabled": false + }, + "md026": { + "enabled": false + }, + "md029": { + "enabled": false + }, + "md031": { + "enabled": false + }, + "md032": { + "enabled": false + }, + "md033": { + "enabled": false + }, + "md034": { + "enabled": false + }, + "md040": { + "enabled": false + }, + "md041": { + "enabled": false + } + } +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..5eba904 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,132 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socioeconomic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +- Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, and sexual attention or advances of + any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, + without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[leiwang1999@outlook.com](mailto:leiwang1999@outlook.com) +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..49a659f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,110 @@ +# Contributing + +That would be awesome if you want to contribute something to Diffulex! + +## Table of Contents + +- [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 Diffulex, 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. + +Any issue you open must include: + +- Code snippet that reproduces the bug with a minimal setup. +- A clear explanation of what the issue is. + +## Ask Questions + +Please ask questions in issues. + +## 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/zhijie-group/Diffulex/issues?q=is%3Aissue+is%3Aopen+label%3A%22%E2%99%A5+help%22) label if you're looking for somewhere to start. + +If you're new to contributing to Diffulex, 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 Diffulex, please follow the instructions below to setup. + +1. Fork Diffulex ([fork](https://github.com/zhijie-group/Diffulex/fork)) on GitHub and clone the repository. + + ```bash + git clone --recurse-submodules git@github.com:/Diffulex.git # use the SSH protocol + cd Diffulex + + git remote add upstream git@github.com:zhijie-group/Diffulex.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 + ``` + +Then you are ready to rock. Thanks for contributing to Diffulex! + +## Install Develop Version + +To install Diffulex in an "editable" mode, run: + +```bash +python3 -m pip install --no-build-isolation --verbose --editable . +``` + +in the main directory. This installation is removable by: + +```bash +python3 -m pip uninstall diffulex +``` + +We also recommend installing Diffulex in a more manual way for better control over the build process, by compiling the C++ extensions first and set the `PYTHONPATH`. See the documentation for detailed instructions. + +## 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 [Setup Development Environment](#setup-development-environment) section. + +Then you can rerun the tests with: + +```bash +python3 -m pytest testing +``` + +## Build Wheels + +_TBA_ + +## Documentation + +_TBA_ diff --git a/diffulex/attention/__init__.py b/diffulex/attention/__init__.py index dbd6e52..7e536f8 100644 --- a/diffulex/attention/__init__.py +++ b/diffulex/attention/__init__.py @@ -20,7 +20,7 @@ def __getattr__(name): try: from .attn_impl import Attention return Attention - except e: + except Exception as e: raise ImportError(f"Failed to import diffulex.attention.attn_impl.Attention: {e}") if name == "fetch_attn_metadata": return metadata.fetch_attn_metadata diff --git a/diffulex/strategy/fast_dllm_v2/engine/sequence.py b/diffulex/strategy/fast_dllm_v2/engine/sequence.py index 16453e5..d105a55 100644 --- a/diffulex/strategy/fast_dllm_v2/engine/sequence.py +++ b/diffulex/strategy/fast_dllm_v2/engine/sequence.py @@ -16,11 +16,13 @@ class FDV2BlockStatus(Enum): class FDV2SubBlockStatus(Enum): ACTIVE = auto() + TO_DUAL_CACHE = auto() + IN_DUAL_CACHE = auto() @dataclass class FDV2SubBlock: - pass - + sub_block_id: int = 0 + status: FDV2SubBlockStatus = FDV2SubBlockStatus.ACTIVE @dataclass class FDV2Block: diff --git a/examples/test_dream_diffulex_gsm8k.py b/examples/test_dream_diffulex_gsm8k.py index 6605627..3ba3d0f 100755 --- a/examples/test_dream_diffulex_gsm8k.py +++ b/examples/test_dream_diffulex_gsm8k.py @@ -10,30 +10,6 @@ from transformers import AutoTokenizer from diffulex import Diffulex, SamplingParams - - -def summarize_profiling(csv_path: str) -> dict: - totals = {} - total_nums = {} - avgs = {} - with open(csv_path, 'r', newline='') as f: - reader = csv.dictReader(f) - for row in reader: - for k, v in row.items(): - try: - val = float(v) - except ValueError: - continue - if val != 0.0: - total_nums[k] = total_nums.get(k, 0) + 1 - totals[k] = totals.get(k, 0.0) + val - print(pd.DataFrame([totals]).T) - for k, v in totals.items(): - if k in total_nums and total_nums[k] > 0: - avgs[k] = v / total_nums[k] - else: - avgs[k] = 0.0 - print(pd.DataFrame([avgs]).T) FEW_SHOTS=""" diff --git a/examples/test_sdar_diffulex_gsm8k.py b/examples/test_sdar_diffulex_gsm8k.py index b0fc8d5..b4f360c 100755 --- a/examples/test_sdar_diffulex_gsm8k.py +++ b/examples/test_sdar_diffulex_gsm8k.py @@ -12,34 +12,11 @@ from diffulex import Diffulex, SamplingParams -def summarize_profiling(csv_path: str) -> dict: - totals = {} - total_nums = {} - avgs = {} - with open(csv_path, 'r', newline='') as f: - reader = csv.DictReader(f) - for row in reader: - for k, v in row.items(): - try: - val = float(v) - except ValueError: - continue - if val != 0.0: - total_nums[k] = total_nums.get(k, 0) + 1 - totals[k] = totals.get(k, 0.0) + val - print(pd.DataFrame([totals]).T) - for k, v in totals.items(): - if k in total_nums and total_nums[k] > 0: - avgs[k] = v / total_nums[k] - else: - avgs[k] = 0.0 - print(pd.DataFrame([avgs]).T) - FEW_SHOTS = "<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\nQuestion: Jen and Tyler are gymnasts practicing flips. Jen is practicing the triple-flip while Tyler is practicing the double-flip. Jen did sixteen triple-flips during practice. Tyler flipped in the air half the number of times Jen did. How many double-flips did Tyler do?\nAnswer:<|im_end|>\n<|im_start|>assistant\nJen did 16 triple-flips, so she did 16 * 3 = <<16*3=48>>48 flips.\nTyler did half the number of flips, so he did 48 / 2 = <<48/2=24>>24 flips.\nA double flip has two flips, so Tyler did 24 / 2 = <<24/2=12>>12 double-flips.\n#### 12<|im_end|>\n<|im_start|>user\nQuestion: Four people in a law firm are planning a party. Mary will buy a platter of pasta for $20 and a loaf of bread for $2. Elle and Andrea will split the cost for buying 4 cans of soda which cost $1.50 each, and chicken wings for $10. Joe will buy a cake that costs $5. How much more will Mary spend than the rest of the firm put together?\nAnswer:<|im_end|>\n<|im_start|>assistant\nMary will spend $20 + $2 = $<<20+2=22>>22.\nElle and Andrea will spend $1.5 x 4 = $<<1.5*4=6>>6 for the soda.\nElle and Andrea will spend $6 + $10 = $<<6+10=16>>16 for the soda and chicken wings.\nElle, Andrea, and Joe together will spend $16 + $5 = $<<16+5=21>>21.\nSo, Mary will spend $22 - $21 = $<<22-21=1>>1 more than all of them combined.\n#### 1<|im_end|>\n<|im_start|>user\nQuestion: A charcoal grill burns fifteen coals to ash every twenty minutes of grilling. The grill ran for long enough to burn three bags of coals. Each bag of coal contains 60 coals. How long did the grill run?\nAnswer:<|im_end|>\n<|im_start|>assistant\nThe grill burned 3 * 60 = <<3*60=180>>180 coals.\nIt takes 20 minutes to burn 15 coals, so the grill ran for 180 / 15 * 20 = <<180/15*20=240>>240 minutes.\n#### 240<|im_end|>\n<|im_start|>user\nQuestion: A bear is preparing to hibernate for the winter and needs to gain 1000 pounds. At the end of summer, the bear feasts on berries and small woodland animals. During autumn, it devours acorns and salmon. It gained a fifth of the weight it needed from berries during summer, and during autumn, it gained twice that amount from acorns. Salmon made up half of the remaining weight it had needed to gain. How many pounds did it gain eating small animals?\nAnswer:<|im_end|>\n<|im_start|>assistant\nThe bear gained 1 / 5 * 1000 = <<1/5*1000=200>>200 pounds from berries.\nIt gained 2 * 200 = <<2*200=400>>400 pounds from acorns.\nIt still needed 1000 - 200 - 400 = <<1000-200-400=400>>400 pounds.\nThus, it gained 400 / 2 = <<400/2=200>>200 pounds from salmon.\nTherefore, the bear gained 400 - 200 = <<400-200=200>>200 pounds from small animals.\n#### 200<|im_end|>\n<|im_start|>user\nQuestion: Janet’s ducks lay 16 eggs per day. She eats three for breakfast every morning and bakes muffins for her friends every day with four. She sells the remainder at the farmers' market daily for $2 per fresh duck egg. How much in dollars does she make every day at the farmers' market?\nAnswer:<|im_end|>\n<|im_start|>assistant\n" # FEW_SHOTS = "<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n" if __name__ == "__main__": - PROFILE = False + PROFILE = True # model = "/root/data/ckpts/JetLM/SDAR-1.7B-Chat-b32" model = "/data1/ckpts/JetLM/SDAR-1.7B-Chat-b32" dataset = load_dataset("gsm8k", "main", split="test")["question"][:1] diff --git a/format.sh b/format.sh new file mode 100755 index 0000000..3cc4390 --- /dev/null +++ b/format.sh @@ -0,0 +1,183 @@ +#!/usr/bin/env bash +# Usage: +# # Do work and commit your work. +# +# # Format files that differ from origin/main. +# bash format.sh +# +# # Format all files. +# bash format.sh --all +# +# +# Ruff (format) + Clang formatter (if installed). This script formats all changed files from the last mergebase. +# You are encouraged to run this locally before pushing changes for review. + +# Cause the script to exit if a single command fails +set -eo pipefail + +if [[ -z "${BASH_VERSION}" ]]; then + echo "Please run this script using bash." >&2 + exit 1 +fi + +# this stops git rev-parse from failing if we run this from the .git directory +builtin cd "$(dirname "${BASH_SOURCE:-$0}")" +ROOT="$(git rev-parse --show-toplevel)" +builtin cd "$ROOT" || exit 1 + +ALL_FILES='' +ONLY_CHANGED='' +FILES=() +if (($# == 0)); then + # Default: allow dirty workspace; run on changed files (committed + worktree) + ONLY_CHANGED='true' +else + while (($# > 0)); do + case "$1" in + --files) + shift + while (($# > 0)); do + FILES+=("$1") + shift + done + ;; + --all) + ALL_FILES='true' + shift + ;; + *) + echo "Unknown argument: '$1'" >&2 + exit 1 + ;; + esac + done +fi + +MERGE_BASE="" +get_merge_base() { + UPSTREAM_REPO="https://github.com/tile-ai/tilelang" + if git ls-remote --exit-code "${UPSTREAM_REPO}" main &>/dev/null; then + # First try to use the upstream repository directly + MERGE_BASE="$(git fetch "${UPSTREAM_REPO}" main &>/dev/null && git merge-base FETCH_HEAD HEAD)" + elif git show-ref --verify --quiet refs/remotes/origin/main; then + # Fall back to origin/main if available + BASE_BRANCH="origin/main" + MERGE_BASE="$(git merge-base "${BASE_BRANCH}" HEAD)" + else + # Last resort, use local main + BASE_BRANCH="main" + MERGE_BASE="$(git merge-base "${BASE_BRANCH}" HEAD)" + fi + echo "${MERGE_BASE}" +} + +if [[ -n "${ALL_FILES}" ]]; then + echo "Checking all files..." >&2 +elif [[ -n "${ONLY_CHANGED}" ]]; then + MERGE_BASE="$(get_merge_base)" + echo "Checking changed files vs merge base (${MERGE_BASE}) and working tree..." >&2 +elif [[ "${#FILES[@]}" -gt 0 ]]; then + echo "Checking specified files: ${FILES[*]}..." >&2 +fi + +# Some systems set pip's default to --user, which breaks isolated virtualenvs. +export PIP_USER=0 + +# If pre-commit is not installed, install it. +if ! python3 -m pre_commit --version &>/dev/null; then + python3 -m pip install pre-commit --user +fi + +echo 'tile-lang pre-commit: Check Start' + +if [[ -n "${ALL_FILES}" ]]; then + python3 -m pre_commit run --all-files +elif [[ -n "${ONLY_CHANGED}" ]]; then + # Collect changed files (committed since merge-base + current worktree) + CHANGED_FILES="$(git diff --name-only --diff-filter=ACM "${MERGE_BASE}" 2>/dev/null || true)" + if [[ -n "${CHANGED_FILES}" ]]; then + echo "Running pre-commit on changed files:" + echo "${CHANGED_FILES}" + # Convert newline-separated files to space-separated and run pre-commit once + CHANGED_FILES_SPACE="$(echo "${CHANGED_FILES}" | tr '\n' ' ')" + python3 -m pre_commit run --files ${CHANGED_FILES_SPACE} + else + echo "No files changed relative to merge base and worktree. Skipping pre-commit." + fi +elif [[ "${#FILES[@]}" -gt 0 ]]; then + python3 -m pre_commit run --files "${FILES[@]}" +fi + +echo 'tile-lang pre-commit: Done' + +echo 'tile-lang clang-tidy: Check Start' +# If clang-tidy is available, run it; otherwise, skip +if [[ -x "$(command -v run-clang-tidy)" ]]; then + # Check if clang-tidy is available + if [[ ! -x "$(command -v clang-tidy)" ]]; then + python3 -m pip install --upgrade --requirements "${ROOT}/requirements-lint.txt" --user + fi + # Get clang-tidy version + CLANG_TIDY_VERSION="$(clang-tidy --version | head -n1 | awk '{print $4}')" + echo "Using clang-tidy version: ${CLANG_TIDY_VERSION}" + + # Check if build directory exists + if [[ ! -d "${ROOT}/build" ]]; then + echo "Build directory not found. Skipping clang-tidy checks." + else + # Run clang-tidy on specified files + clang_tidy_files() { + run-clang-tidy -j 64 "$@" -p build + } + + # Run clang-tidy on all C/C++ source files + clang_tidy_all() { + run-clang-tidy -j 64 src/*.cc -p build + } + + # Run clang-tidy on changed C/C++ files relative to main + clang_tidy_changed() { + # Get changed C/C++ files + CHANGED_FILES="$(git diff --name-only --diff-filter=ACM "${MERGE_BASE}" -- '*.c' '*.cc' '*.cpp' '*.h' '*.hpp' 2>/dev/null || true)" + + if [[ -n "${CHANGED_FILES}" ]]; then + echo "Running clang-tidy on changed files:" + echo "${CHANGED_FILES}" + # Convert newline-separated files to space-separated and run clang-tidy once + CHANGED_FILES_SPACE="$(echo "${CHANGED_FILES}" | tr '\n' ' ')" + run-clang-tidy -j 64 ${CHANGED_FILES_SPACE} -p build -fix + else + echo "No C/C++ files changed. Skipping clang-tidy." + fi + } + + if [[ -n "${ALL_FILES}" ]]; then + # If --all is given, run clang-tidy on all source files + clang_tidy_all + elif [[ -n "${ONLY_CHANGED}" ]]; then + # Otherwise, run clang-tidy only on changed C/C++ files + clang_tidy_changed + elif [[ "${#FILES[@]}" -gt 0 ]]; then + # If --files is given, run clang-tidy only on the provided files + clang_tidy_files "${FILES[@]}" + fi + fi + +else + echo "run-clang-tidy not found. Skipping clang-tidy checks." + echo "To install clang-tidy tools, you may need to install clang-tidy and run-clang-tidy." +fi +echo 'tile-lang clang-tidy: Done' + +# Check if there are any uncommitted changes after all formatting steps. +# If there are, ask the user to review and stage them. +if ! git diff --quiet &>/dev/null; then + echo 'Reformatted files. Please review and stage the changes.' + echo 'Changes not staged for commit:' + echo + git --no-pager diff --name-only + + exit 1 +fi + +echo 'tile-lang: All checks passed' diff --git a/pyproject.toml b/pyproject.toml index ebc9aa3..49fa67b 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,8 @@ dependencies = [ "matplotlib>=3.10.5", "fastapi>=0.115.0", "uvicorn>=0.30.0", + "pandas>=2.3.3", + "tilelang==0.1.7.post1" ] [project.urls] @@ -39,6 +41,10 @@ Homepage = "https://github.com/zhijie-group/D2fEngine" Repository = "https://zhijie-group.github.io/D2fEngine" "Organization" = "https://github.com/zhijie-group" +[[tool.uv.index]] +url = "https://mirrors.aliyun.com/pypi/simple" +default = true + [tool.setuptools.packages.find] include = [ "diffulex", @@ -46,7 +52,3 @@ include = [ "diffulex_legacy", "test" ] - -[[tool.uv.index]] -url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" -default = true \ No newline at end of file