Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/conventions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Conventions
on: [push, pull_request]

permissions:
contents: read

jobs:
conventions:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Run convention checker
env:
BEFORE_SHA: ${{ github.event.before }}
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
EVENT_NAME: ${{ github.event_name }}
HEAD_SHA: ${{ github.sha }}
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
set -euo pipefail

if [ "$EVENT_NAME" = "pull_request" ]; then
python3 scripts/check_conventions.py \
--base "$PR_BASE_SHA" \
--head "$PR_HEAD_SHA" \
--check-git \
--pr-title "$PR_TITLE" \
--summary-by-code
exit 0
fi

if [ "$BEFORE_SHA" = "0000000000000000000000000000000000000000" ]; then
BASE_REF="origin/$DEFAULT_BRANCH"
else
BASE_REF="$BEFORE_SHA"
fi

python3 scripts/check_conventions.py \
--base "$BASE_REF" \
--head "$HEAD_SHA" \
--summary-by-code
22 changes: 17 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ Platform maintainers can add auto-detection in `CMakeLists.txt` under the `if(AU
pytest
```

## Convention Checks

Project-specific conventions that are not covered by `clang-format` or `ruff`
are checked by:

```bash
python3 scripts/check_conventions.py --base origin/master --head HEAD --check-git
```

Use `python3 scripts/check_conventions.py --list-checks` to see the full check
catalog.

## Adding an Operator

1. **Base class** in `src/base/`: the class must inherit from `Operator<Op>` (e.g. `class Gemm : public Operator<Gemm>`). See `src/base/gemm.h`.
Expand All @@ -104,7 +116,7 @@ pytest

Since `DataType` is an enum used to represent data types generically, we often need to map between `DataType` and native C++ types (e.g. `float`, `int32_t`).

- **`TypeMap`**: maps `DataType` to native types. Use the alias `TypeMapType` to get the type directly, e.g. `TypeMapType<dev, DataType::kFloat32>` is `float`. Note, the first template argument is a `Device::Type` since data types like float16 and bfloat16 are not the same across the platforms. Thus, a `Device::Type` is required to specify which native type a `DataType` maps to.
- **`TypeMap`**: maps `DataType` to native types. Use the alias `TypeMapType` to get the type directly, e.g. `TypeMapType<dev, DataType::kFloat32>` is `float`. Note, the first template argument is a `Device::Type` since data types like float16 and bfloat16 are not the same across the platforms. Thus, a `Device::Type` is required to specify which native type a `DataType` maps to.
- **`DataTypeMap`**: maps native types back to `DataType`. Use the alias `DataTypeMapValue`, e.g. `DataTypeMapValue<float>` is `DataType::kFloat32`.

### `DispatchFunc`
Expand Down Expand Up @@ -146,7 +158,7 @@ DispatchFunc<Device::Type::Cpu, FloatTypes>(
"DataType Dispatch");
```

Dispatching `DataType` is a little bit special.
Dispatching `DataType` is a little bit special.

1. Due to the previously mentioned `TypeMap` reason, a `Device::Type` is needed as the first template argument;

Expand Down Expand Up @@ -195,7 +207,7 @@ DispatchFunc<List<Device::Type::kCpu, Device::Type::kNvidia>,
"MultiDeviceTest");
```

Similarly, `DataType` requires a `Device::Type` at the front:
Similarly, `DataType` requires a `Device::Type` at the front:

```cpp
DispatchFunc<Device::Type::kCpu, FloatTypes, List<DataType::kInt32, DataType::kInt64>>(
Expand Down Expand Up @@ -223,9 +235,9 @@ DispatchFunc<FloatTypes, List<Device::Type::kCpu, Device::Type::kNvidia>>(
"MixedDispatch");
```

Note that in mixed multi-type dispatch, `DataType` is not treated specially. Therefore, we neither should nor can place `Device::Type` at the front of the `DataType` list. Inside the lambda, we obtain it as a `DataType` and then convert it to the native type if needed.
Note that in mixed multi-type dispatch, `DataType` is not treated specially. Therefore, we neither should nor can place `Device::Type` at the front of the `DataType` list. Inside the lambda, we obtain it as a `DataType` and then convert it to the native type if needed.

If `DT` is not used within the lambda, you can inline its definition directly into the `using T = ...` statement, like this:
If `DT` is not used within the lambda, you can inline its definition directly into the `using T = ...` statement, like this:

```cpp
using T = TypeMapType<Device::Type::kCpu, ListGet<0>(list_tag)>;
Expand Down
Loading
Loading