ci: test that extensions load into Triton (#84)#85
Conversation
31a133e to
131fde4
Compare
|
Due to changes in what lands into the Triton build artifacts, the current cached version on GH needs to be busted for this to work (or have some mechanism to detect artifacts that would be now stale) |
131fde4 to
9546c69
Compare
Adds the runtime integration test from triton-lang#79 (testing/test_plugins.py) plus the artifact change that makes it actually work in CI: the Triton artifact now bundles the importable Python package under <triton_install_dir>/python, not just the C++ install tree (cmake --install only copies *.h from python/). Symlinks are dereferenced so the package is complete after extraction. The CI step puts that package on PYTHONPATH and runs pytest, loading each built extension via TRITON_PLUGIN_PATHS to confirm it imports, passes the plugin/Triton version check, and lowers a basic kernel.
9546c69 to
b647ebd
Compare
| --transform="s|^build/install|${{ env.triton_install_dir }}/cpp|" \ | ||
| --transform="s|^python|${{ env.triton_install_dir }}/python|" \ |
There was a problem hiding this comment.
Now this is completely personal preference but: I would be more in favor with keeping the C++ artifacts where the are (<install dir>/{bin,include,lib}) and just adding a new python directory amongst them. The cpp indirection just feels a bit unconventional... I could be convinced otherwise.
| PYTHONPATH: ${{ github.workspace }}/${{ steps.build-triton.outputs.triton_install_dir }}/python | ||
| TRITON_EXT_BUILD_DIR: build | ||
| run: | | ||
| python -m pip install --quiet pytest |
There was a problem hiding this comment.
I'm not sure we need another pip install here given the pip install -r requirements.txt elsewhere. But if removing this line breaks things, leave it in and I will fix this later.
| - name: Test that extensions load into Triton | ||
| env: | ||
| PYTHONPATH: ${{ github.workspace }}/${{ steps.build-triton.outputs.triton_install_dir }}/python | ||
| TRITON_EXT_BUILD_DIR: build | ||
| run: | | ||
| python -m pip install --quiet pytest | ||
| python -c "import triton; print('triton', triton.__version__)" | ||
| python -m pytest testing/test_plugins.py -v |
There was a problem hiding this comment.
I think this whole block can be subsumed into the Makefile so that it is run as a part of make test. Like in upstream Triton, we probably want to split the test target into test-lit and test-unit. My reasoning: it is very convenient to just run a single command locally to run tests.
| script = """ | ||
| import sys | ||
| import triton | ||
| import triton.language as tl | ||
|
|
||
| @triton.jit | ||
| def kernel(in_ptr, out_ptr, BLOCK: tl.constexpr): | ||
| offs = tl.arange(0, BLOCK) | ||
| tl.store(out_ptr + offs, tl.load(in_ptr + offs)) | ||
|
|
||
| try: | ||
| target = triton.runtime.driver.active.get_current_target() | ||
| except Exception as e: | ||
| print(f"No target ({type(e).__name__}: {e}); skipping compile.") | ||
| sys.exit(0) | ||
| src = triton.compiler.ASTSource( | ||
| fn=kernel, | ||
| signature={"in_ptr": "*fp32", "out_ptr": "*fp32"}, | ||
| constexprs={"BLOCK": 128}, | ||
| ) | ||
| triton.compile(src, target=target) | ||
| """ |
There was a problem hiding this comment.
Here's another opinion: this might as well be a separate file so that, if something were to go wrong, we can just run TRITON_PLUGIN_PATHS=... this-script.py and debug things manually. This avoids creating the temporary file above, too. To help out with this case, we probably want to log the command to run (equivalent to _run_with_plugin) if the test fails.
| import triton # noqa: F401 | ||
| import utlx_plugin # noqa: F401 (registers triton.language.extra.tlx) | ||
| from triton.language.extra import tlx | ||
| for n in ("local_alloc", "local_view", "local_store", "local_load"): | ||
| assert hasattr(tlx, n), f"missing tlx.{n}" | ||
| """ |
There was a problem hiding this comment.
The same comment above applies here.
…andalone debug scripts - Revert the cpp/ install-dir indirection; C++ tree stays at the artifact root with the python package alongside it. - Run the plugin-load tests via `make test` (split into test-lit + test-unit) so the whole suite runs from one command locally. - Drop the redundant pytest install; requirements.txt already provides it. - Move the kernel-compile and tlx-DSL scenarios into standalone scripts under testing/scripts/ so they can be run by hand; print the reproduce command on failure.
The previous pin already has a cached artifact with the old layout; bumping to a fresh commit forces a cold rebuild with the current packaging without reusing a stale-layout artifact.
abrown
left a comment
There was a problem hiding this comment.
Nice! Thanks again for this contribution.
Merging triton-lang#85 revealed a problem with how the Python virtual environment is set up in our primary `ci.yml` file. This change reorders some steps and ensures that the primary `python` executable used is the one from our `.venv` directory. Hopefully this resolves the missing `pytest` dependency [error] on `main`. [error]: https://github.com/triton-lang/triton-ext/actions/runs/26238904449/job/77219652269#step:12:36
Merging #85 revealed a problem with how the Python virtual environment is set up in our primary `ci.yml` file. This change reorders some steps and ensures that the primary `python` executable used is the one from our `.venv` directory. Hopefully this resolves the missing `pytest` dependency [error] on `main`. [error]: https://github.com/triton-lang/triton-ext/actions/runs/26238904449/job/77219652269#step:12:36
Out-of-tree Apple Metal backend for Triton-ext: TTGIR -> LLVM IR -> AIR -> .metallib. The metal-ir lowering pipeline (passes + serializer + C bridge) lives under lib/MetalIR/ alongside the TritonGPU->LLVM conversion, built into libMetalIRBridge.dylib which the Python driver loads via ctypes. Rebased onto main (incl. triton-lang#84/triton-lang#85/triton-lang#86).
Out-of-tree Apple Metal backend for Triton-ext: TTGIR -> LLVM IR -> AIR -> .metallib. The metal-ir lowering pipeline (passes + serializer + C bridge) lives under lib/MetalIR/ alongside the TritonGPU->LLVM conversion, built into libMetalIRBridge.dylib which the Python driver loads via ctypes. Rebased onto main (incl. triton-lang#84/triton-lang#85/triton-lang#86).
Out-of-tree Apple Metal backend for Triton-ext: TTGIR -> LLVM IR -> AIR -> .metallib. The metal-ir lowering pipeline (passes + serializer + C bridge) lives under lib/MetalIR/ alongside the TritonGPU->LLVM conversion, built into libMetalIRBridge.dylib which the Python driver loads via ctypes. Rebased onto main (incl. triton-lang#84/triton-lang#85/triton-lang#86).
Out-of-tree Apple Metal backend for Triton-ext: TTGIR -> LLVM IR -> AIR -> .metallib. The metal-ir lowering pipeline (passes + serializer + C bridge) lives under lib/MetalIR/ alongside the TritonGPU->LLVM conversion, built into libMetalIRBridge.dylib which the Python driver loads via ctypes. Rebased onto main (incl. triton-lang#84/triton-lang#85/triton-lang#86).
Out-of-tree Apple Metal backend for Triton-ext: TTGIR -> LLVM IR -> AIR -> .metallib. The metal-ir lowering pipeline (passes + serializer + C bridge) lives under lib/MetalIR/ alongside the TritonGPU->LLVM conversion, built into libMetalIRBridge.dylib which the Python driver loads via ctypes. Rebased onto main (incl. triton-lang#84/triton-lang#85/triton-lang#86).
Out-of-tree Apple Metal backend for Triton-ext: TTGIR -> LLVM IR -> AIR -> .metallib. The metal-ir lowering pipeline (passes + serializer + C bridge) lives under lib/MetalIR/ alongside the TritonGPU->LLVM conversion, built into libMetalIRBridge.dylib which the Python driver loads via ctypes. Rebased onto main (incl. triton-lang#84/triton-lang#85/triton-lang#86).
Adds the runtime integration test from #79 (testing/test_plugins.py) plus the artifact change that makes it actually work in CI: the Triton artifact now bundles the importable Python package under <triton_install_dir>/python, not just the C++ install tree (cmake --install only copies *.h from python/). Symlinks are dereferenced so the package is complete after extraction.
The CI step puts that package on PYTHONPATH and runs pytest, loading each built extension via TRITON_PLUGIN_PATHS to confirm it imports, passes the plugin/Triton version check, and lowers a basic kernel.
Example passing CI: https://github.com/imperatormk/triton-ext/actions/runs/26187798359/job/77047943148
Closes #84