Repository navigation
[fix] Move codegen out of QPU::launchKernel - #5770
Conversation
Signed-off-by: Luca Mondada <luca@mondada.net>
Signed-off-by: Luca Mondada <luca@mondada.net>
Signed-off-by: Luca Mondada <luca@mondada.net>
|
This PR has already been reviewed and approved in #5755 |
CI Summary (
|
| Job | Result |
|---|---|
binaries |
⏩ skipped |
build_and_test |
✅ success |
changes |
✅ success |
config_devdeps |
✅ success |
config_source_build |
⏩ skipped |
config_wheeldeps |
✅ success |
devdeps |
✅ success |
docker_image |
⏩ skipped |
documentation |
✅ success |
gen_code_coverage |
⏩ skipped |
metadata |
✅ success |
python_devel_wheel |
⏩ skipped |
python_metapackages |
⏩ skipped |
python_wheels |
⏩ skipped |
python_wheels_cu12_validation |
⏩ skipped |
python_wheels_cu13 |
⏩ skipped |
source_build |
⏩ skipped |
wheeldeps |
✅ success |
⏩ Skipped jobs (10) — intentionally skipped on PR builds; run on merge_group / workflow_dispatch
| Job |
|---|
binaries |
config_source_build |
docker_image |
gen_code_coverage |
python_devel_wheel |
python_metapackages |
python_wheels_cu12_validation |
python_wheels_cu13 |
python_wheels |
source_build |
All sub-jobs (47) — every matrix leg, with links
| Job | Status | Link |
|---|---|---|
| Build and test (amd64, gcc12, openmpi) / Dev environment (Debug) | ✅ success | view |
| Build and test (amd64, gcc12, openmpi) / Dev environment (Python) | ✅ success | view |
| Build and test (amd64, llvm, openmpi) / Dev environment (Debug) | ✅ success | view |
| Build and test (amd64, llvm, openmpi) / Dev environment (Python) | ✅ success | view |
| Build and test (arm64, llvm, openmpi) / Dev environment (Debug) | ✅ success | view |
| Build and test (arm64, llvm, openmpi) / Dev environment (Python) | ✅ success | view |
| CI Summary | ❔ in_progress | view |
| Check for stable CUDA-Q changes | ✅ success | view |
| Configure build (devdeps) | ✅ success | view |
| Configure build (source_build) | ⏩ skipped | view |
| Configure build (wheeldeps) | ✅ success | view |
| Create CUDA 12 Python wheels | ⏩ skipped | view |
| Create CUDA 13 Python wheels | ⏩ skipped | view |
| Create CUDA Quantum installer | ⏩ skipped | view |
| Create Docker images | ⏩ skipped | view |
| Create Python metapackages | ⏩ skipped | view |
| Create shared Python development wheel | ⏩ skipped | view |
| Documentation / Build and check docs | ✅ success | view |
| Gen code coverage | ⏩ skipped | view |
| Load dependencies (amd64, gcc12) / Caching | ✅ success | view |
| Load dependencies (amd64, gcc12) / Finalize | ✅ success | view |
| Load dependencies (amd64, gcc12) / Metadata | ✅ success | view |
| Load dependencies (amd64, llvm) / Caching | ✅ success | view |
| Load dependencies (amd64, llvm) / Finalize | ✅ success | view |
| Load dependencies (amd64, llvm) / Metadata | ✅ success | view |
| Load dependencies (arm64, gcc12) / Caching | ✅ success | view |
| Load dependencies (arm64, gcc12) / Finalize | ✅ success | view |
| Load dependencies (arm64, gcc12) / Metadata | ✅ success | view |
| Load dependencies (arm64, llvm) / Caching | ✅ success | view |
| Load dependencies (arm64, llvm) / Finalize | ✅ success | view |
| Load dependencies (arm64, llvm) / Metadata | ✅ success | view |
| Load source build cache | ⏩ skipped | view |
| Load wheel dependencies (amd64, 12.6) / Caching | ✅ success | view |
| Load wheel dependencies (amd64, 12.6) / Finalize | ✅ success | view |
| Load wheel dependencies (amd64, 12.6) / Metadata | ✅ success | view |
| Load wheel dependencies (amd64, 13.0) / Caching | ✅ success | view |
| Load wheel dependencies (amd64, 13.0) / Finalize | ✅ success | view |
| Load wheel dependencies (amd64, 13.0) / Metadata | ✅ success | view |
| Load wheel dependencies (arm64, 12.6) / Caching | ✅ success | view |
| Load wheel dependencies (arm64, 12.6) / Finalize | ✅ success | view |
| Load wheel dependencies (arm64, 12.6) / Metadata | ✅ success | view |
| Load wheel dependencies (arm64, 13.0) / Caching | ✅ success | view |
| Load wheel dependencies (arm64, 13.0) / Finalize | ✅ success | view |
| Load wheel dependencies (arm64, 13.0) / Metadata | ✅ success | view |
| Prepare cache clean-up | ❔ in_progress | view |
| Retrieve PR info | ✅ success | view |
| Validate CUDA 12 Python wheels | ⏩ skipped | view |
✅ Required checks (7/7) — declared in .github/required-checks.yml for push
| Required check | Status | Link |
|---|---|---|
| Build and test (amd64, llvm, openmpi) / Dev environment (Debug) | ✅ success | view |
| Build and test (amd64, llvm, openmpi) / Dev environment (Python) | ✅ success | view |
| Build and test (arm64, llvm, openmpi) / Dev environment (Debug) | ✅ success | view |
| Build and test (arm64, llvm, openmpi) / Dev environment (Python) | ✅ success | view |
| Build and test (amd64, gcc12, openmpi) / Dev environment (Debug) | ✅ success | view |
| Build and test (amd64, gcc12, openmpi) / Dev environment (Python) | ✅ success | view |
| Documentation / Build and check docs | ✅ success | view |
Signed-off-by: Luca Mondada <luca@mondada.net>
88f71f2 to
166e35f
Compare
Signed-off-by: Luca Mondada <luca@mondada.net>
schweitzpgi
left a comment
There was a problem hiding this comment.
The size of this change is a bit surprising. I was thinking with all the work on unifying the launch process this would be more terse and just moving some compilation steps.
Yeah, we never got to work on codegen (that's why it was still bundled in the launch). The diff in this PR is mostly due to clean-ups: name changes, breaking out code into separate functions etc. It's quite mechanical. We keep getting closer to perfection, I guess 😅 |
Signed-off-by: Luca Mondada <luca@mondada.net>
1441ebb to
dcaed50
Compare
CI Summary (
|
| Job | Result |
|---|---|
binaries |
⏩ skipped |
build_and_test |
✅ success |
changes |
✅ success |
config_devdeps |
✅ success |
config_source_build |
⏩ skipped |
config_wheeldeps |
⏩ skipped |
devdeps |
✅ success |
docker_image |
⏩ skipped |
documentation |
⏩ skipped |
gen_code_coverage |
⏩ skipped |
metadata |
✅ success |
python_devel_wheel |
⏩ skipped |
python_metapackages |
⏩ skipped |
python_wheels |
⏩ skipped |
python_wheels_cu12_validation |
⏩ skipped |
python_wheels_cu13 |
⏩ skipped |
source_build |
⏩ skipped |
wheeldeps |
⏩ skipped |
⏩ Skipped jobs (13) — intentionally skipped on PR builds; run on merge_group / workflow_dispatch
| Job |
|---|
binaries |
config_source_build |
config_wheeldeps |
docker_image |
documentation |
gen_code_coverage |
python_devel_wheel |
python_metapackages |
python_wheels_cu12_validation |
python_wheels_cu13 |
python_wheels |
source_build |
wheeldeps |
All sub-jobs (28) — every matrix leg, with links
| Job | Status | Link |
|---|---|---|
| Build and test (amd64, llvm, openmpi) / Dev environment (Debug) | ✅ success | view |
| Build and test (amd64, llvm, openmpi) / Dev environment (Python) | ✅ success | view |
| Build and test (arm64, llvm, openmpi) / Dev environment (Debug) | ✅ success | view |
| Build and test (arm64, llvm, openmpi) / Dev environment (Python) | ✅ success | view |
| CI Summary | ❔ in_progress | view |
| Check for stable CUDA-Q changes | ✅ success | view |
| Configure build (devdeps) | ✅ success | view |
| Configure build (source_build) | ⏩ skipped | view |
| Configure build (wheeldeps) | ⏩ skipped | view |
| Create CUDA 12 Python wheels | ⏩ skipped | view |
| Create CUDA 13 Python wheels | ⏩ skipped | view |
| Create CUDA Quantum installer | ⏩ skipped | view |
| Create Docker images | ⏩ skipped | view |
| Create Python metapackages | ⏩ skipped | view |
| Create shared Python development wheel | ⏩ skipped | view |
| Documentation | ⏩ skipped | view |
| Gen code coverage | ⏩ skipped | view |
| Load dependencies (amd64, llvm) / Caching | ✅ success | view |
| Load dependencies (amd64, llvm) / Finalize | ✅ success | view |
| Load dependencies (amd64, llvm) / Metadata | ✅ success | view |
| Load dependencies (arm64, llvm) / Caching | ✅ success | view |
| Load dependencies (arm64, llvm) / Finalize | ✅ success | view |
| Load dependencies (arm64, llvm) / Metadata | ✅ success | view |
| Load source build cache | ⏩ skipped | view |
| Load wheel dependencies | ⏩ skipped | view |
| Prepare cache clean-up | ❔ in_progress | view |
| Retrieve PR info | ✅ success | view |
| Validate CUDA 12 Python wheels | ⏩ skipped | view |
✅ Required checks (4/4) — declared in .github/required-checks.yml for merge_group_fast
| Required check | Status | Link |
|---|---|---|
| Build and test (amd64, llvm, openmpi) / Dev environment (Debug) | ✅ success | view |
| Build and test (amd64, llvm, openmpi) / Dev environment (Python) | ✅ success | view |
| Build and test (arm64, llvm, openmpi) / Dev environment (Debug) | ✅ success | view |
| Build and test (arm64, llvm, openmpi) / Dev environment (Python) | ✅ success | view |
These changes were originally motivated by a bug that @cabreraam has pointed out in NVIDIA#5746, all credits go to him! Thank you! # The issue NVIDIA#5005 introduced the possibility to define a custom `CompileTarget` and store it directly in the platform. However, the QPUs were not consulting the platform when getting a hold of the current `CompileTarget` instance, which is needed to drive codegen within `QPU::launchKernel`. As a result, the codegen config was still derived from the QPU's compile target object, even if it had been overridden in the quantum platform. # The solution `QPU::launchKernel` shouldn't need to know about `CompileTarget`: it should only concern itself with runtime matters and leave compiler-y stuff to the compiler. Instead of adding a way of reaching back from the QPU into the platform, the 'right' thing to do is to move codegen out of `QPU::launchKernel`. This is what this PR does: codegen is now run right after the compilation pipeline, within the JIT compiler's `Compiler::compile` method. The codegen-ed code is stored in `CompiledModule` as a string. This gets passed to `QPU::launchKernel`, which instead of running codegen can simply read that string and proceed with launching the kernel as before. Whilst I was modifying this code, I've made some clean ups and renames: - refactored get_compile_options to reuse the same logic in multiple places - renamed `QPU::unifiedLaunchModule` to `QPU::compileAndLaunchKernel`. This describes much better what it does and makes the relationship to the 'normal' `launchKernel` methods obvious. Its function signature also needed an update to take the compiler options explicitly as argument. - renamed `Compiler::runPassPipeline` to `Compiler::compile`. The method does much more than just running a pipeline. --------- Signed-off-by: Luca Mondada <luca@mondada.net>
CUDA-Q Logical compiles a kernel that it imports directly, without a launch, and needs that compile to use a Logical target's compile target and endpoint, whatever target is installed. Until now Python could compile a kernel only for the current platform, so a compile under an installed emulated target was emulated, built a JIT engine, and used that target's pipeline. `cudaq_runtime.compile_module(kernel_name, module, is_entry_point, compile_target=None, is_remote=None, is_emulated=None, supports_jit=None, args=())` compiles without launching and returns a `CompiledModule`. The traits describe a `RuntimeEndpoint`, and an omitted trait comes from the current platform. `getCompileConfig` takes the compile target and that endpoint, and resolves the options for the endpoint through a new `quantum_platform::getCompileOptions(policy, seed, endpoint)`, which the per-QPU overload now calls, so a compile for another endpoint follows the same rules as a launch on it. Whether the compile substitutes the arguments follows the compile target it is given, through `specializesArguments`, so the packing always matches the compile. `marshal_and_retain_module` shares this implementation with no target or endpoint given, and still never runs code generation. `CompiledModule.entry_point` is now `None` when the module carries no JIT artifact, instead of dereferencing a missing one. The binding stays internal. The public `cudaq.compile`, `save_temps`, `load_build`, and the removal of Logical's `import_cudaq` remain in NVIDIA#5660, which can rebase onto this commit. This is Andres Paz's binding from NVIDIA#5660, adapted to pass the specialization decision that step 3b added and the endpoint resolution that NVIDIA#5770 added. Tested through CUDA-Q Logical's direct-import tests in a following commit, which compile with an emulated target installed and check that no JIT engine is built. Co-authored-by: Andres Paz <andresp@nvidia.com> Signed-off-by: Thomas Alexander <talexander@nvidia.com>
CUDA-Q Logical compiles a kernel that it imports directly, without a launch, and needs that compile to use a Logical target's compile target and endpoint, whatever target is installed. Until now Python could compile a kernel only for the current platform, so a compile under an installed emulated target was emulated, built a JIT engine, and used that target's pipeline. `cudaq_runtime.compile_module(kernel_name, module, is_entry_point, compile_target=None, is_remote=None, is_emulated=None, supports_jit=None, args=())` compiles without launching and returns a `CompiledModule`. The traits describe a `RuntimeEndpoint`, and an omitted trait comes from the current platform. `getCompileConfig` takes the compile target and that endpoint, and resolves the options for the endpoint through a new `quantum_platform::getCompileOptions(policy, seed, endpoint)`, which the per-QPU overload now calls, so a compile for another endpoint follows the same rules as a launch on it. Whether the compile substitutes the arguments follows the compile target it is given, through `specializesArguments`, so the packing always matches the compile. `marshal_and_retain_module` shares this implementation with no target or endpoint given, and still never runs code generation. `CompiledModule.entry_point` is now `None` when the module carries no JIT artifact, instead of dereferencing a missing one. The binding stays internal. The public `cudaq.compile`, `save_temps`, `load_build`, and the removal of Logical's `import_cudaq` remain in NVIDIA#5660, which can rebase onto this commit. This is Andres Paz's binding from NVIDIA#5660, adapted to pass the specialization decision that step 3b added and the endpoint resolution that NVIDIA#5770 added. Tested through CUDA-Q Logical's direct-import tests in a following commit, which compile with an emulated target installed and check that no JIT engine is built. Co-authored-by: Andres Paz <andresp@nvidia.com> Signed-off-by: Thomas Alexander <talexander@nvidia.com>
These changes were originally motivated by a bug that @cabreraam has pointed out in #5746, all credits go to him! Thank you!
The issue
#5005 introduced the possibility to define a custom
CompileTargetand store it directly in the platform. However, the QPUs were not consulting the platform when getting a hold of the currentCompileTargetinstance, which is needed to drive codegen withinQPU::launchKernel. As a result, the codegen config was still derived from the QPU's compile target object, even if it had been overridden in the quantum platform.The solution
QPU::launchKernelshouldn't need to know aboutCompileTarget: it should only concern itself with runtime matters and leave compiler-y stuff to the compiler. Instead of adding a way of reaching back from the QPU into the platform, the 'right' thing to do is to move codegen out ofQPU::launchKernel.This is what this PR does: codegen is now run right after the compilation pipeline, within the JIT compiler's
Compiler::compilemethod. The codegen-ed code is stored inCompiledModuleas a string. This gets passed toQPU::launchKernel, which instead of running codegen can simply read that string and proceed with launching the kernel as before.Whilst I was modifying this code, I've made some clean ups and renames:
QPU::unifiedLaunchModuletoQPU::compileAndLaunchKernel. This describes much better what it does and makes the relationship to the 'normal'launchKernelmethods obvious. Its function signature also needed an update to take the compiler options explicitly as argument.Compiler::runPassPipelinetoCompiler::compile. The method does much more than just running a pipeline.