Skip to content
Open
Show file tree
Hide file tree
Changes from 10 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
6 changes: 6 additions & 0 deletions python/extension/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ declare_mlir_python_extension(CUDAQuantumPythonSources.Extension
../../runtime/common/RuntimePyMLIR.cpp
../../runtime/common/JIT.cpp
../../runtime/common/Compiler.cpp
../../runtime/common/PassPipelineLogging.cpp
../../runtime/cudaq/platform/default/rest_server/RemoteRuntimeClient.cpp
../../runtime/cudaq/platform/orca/OrcaExecutor.cpp
../../runtime/cudaq/platform/orca/OrcaQPU.cpp
Expand All @@ -110,12 +111,17 @@ declare_mlir_python_extension(CUDAQuantumPythonSources.Extension
OptCodeGen
OptTransforms
MLIRPass
MLIRSupport
CUDAQTargetConfigUtil
cudaq-python-interop
cudaq-platform-default
cudaq-qir-verifier
)

set_source_files_properties(
../../runtime/common/PassPipelineLogging.cpp
PROPERTIES COMPILE_OPTIONS "-fno-rtti"
)
target_include_directories(CUDAQuantumPythonSources.Extension INTERFACE
${CMAKE_SOURCE_DIR}/python
${CMAKE_SOURCE_DIR}/python/utils
Expand Down
5 changes: 5 additions & 0 deletions python/runtime/cudaq/platform/py_alt_launch_kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "common/ArgumentConversion.h"
#include "common/ArgumentWrapper.h"
#include "common/Environment.h"
#include "common/PassPipelineLogging.h"
#include "cudaq/Optimizer/Builder/Marshal.h"
#include "cudaq/Optimizer/Builder/Runtime.h"
#include "cudaq/Optimizer/CAPI/Dialects.h"
Expand Down Expand Up @@ -1079,6 +1080,7 @@ static MlirModule synthesizeKernel(py::object kernel, py::args runtimeArgs) {
context->disableMultithreading();
if (enablePrintMLIREachPass)
pm.enableIRPrinting();
cudaq_internal::maybeLogPassPipeline(pm, "python-jit-argument-synth");
if (failed(pm.run(cloned))) {
engine.eraseHandler(handlerId);
throw std::runtime_error(
Expand Down Expand Up @@ -1112,6 +1114,7 @@ static void executeMLIRPassManager(ModuleOp mod, PassManager &pm) {
tm.setEnabled(cudaq::isTimingTagEnabled(cudaq::TIMING_JIT_PASSES));
auto timingScope = tm.getRootScope(); // starts the timer
pm.enableTiming(timingScope); // do this right before pm.run
cudaq_internal::maybeLogPassPipeline(pm, "python-jit");

if (failed(pm.run(mod))) {
engine.eraseHandler(handlerId);
Expand All @@ -1131,6 +1134,7 @@ static ModuleOp cleanLowerToCodegenKernel(ModuleOp mod,
PassManager pm(ctx);
std::string transport = getTransportLayer();
cudaq::opt::addAOTPipelineConvertToQIR(pm, transport);
cudaq_internal::maybeLogPassPipeline(pm, "python-aot-qir");
executeMLIRPassManager(mod, pm);
return mod;
}
Expand Down Expand Up @@ -1273,6 +1277,7 @@ void cudaq::bindAltLaunchKernel(py::module &mod,
cudaq::opt::createPySynthCallableBlockArgs(
SmallVector<StringRef>(funcNames.begin(), funcNames.end()),
true));
cudaq_internal::maybeLogPassPipeline(pm, "python-synth-callable");
if (failed(pm.run(m)))
throw std::runtime_error(
"cudaq::jit failed to remove callable block arguments.");
Expand Down
103 changes: 103 additions & 0 deletions python/tests/backends/test_pipeline_logging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# ============================================================================ #
# Copyright (c) 2026 NVIDIA Corporation & Affiliates. #
# All rights reserved. #
# #
# This source code and the accompanying materials are made available under #
# the terms of the Apache License 2.0 which accompanies this distribution. #
# ============================================================================ #

import json

import cudaq
import pytest
from cudaq import spin


@pytest.fixture(autouse=True)
def reset_target():
cudaq.reset_target()
yield
cudaq.reset_target()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we calling reset_target() before and after the test? Should it be just after the test?



TARGET_CONFIGS = [
# `run` is not currently supported on these backend targets.
pytest.param("infleqtion", {"emulate": True}, False, id="openqasm"),
pytest.param("quantinuum", {"emulate": True}, False, id="qir"),
pytest.param("remote-mqpu", {"auto_launch": "1"},
True,
id="remote-simulator"),
# Keep one local/default case that also exercises `run`.
pytest.param("qpp-cpu", {}, True, id="default"),
]


@cudaq.kernel
def sample_kernel():
qubit = cudaq.qubit()
h(qubit)
mz(qubit)


@cudaq.kernel
def run_kernel() -> int:
qubit = cudaq.qubit()
h(qubit)
return mz(qubit)


@cudaq.kernel
def observe_kernel():
qubit = cudaq.qubit()
h(qubit)


@pytest.mark.parametrize("target,target_kwargs,supports_run", TARGET_CONFIGS)
def test_pipeline_logging_decorator(tmp_path, monkeypatch, target,
target_kwargs, supports_run):
log_path = tmp_path / "pipeline.jsonl"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we move out this hard coded value in a constant outside?

monkeypatch.setenv("CUDAQ_PIPELINE_LOG", str(log_path))

if not cudaq.has_target(target):
pytest.skip(f"target '{target}' not available")
cudaq.set_target(target, **target_kwargs)

try:
cudaq.sample(sample_kernel, shots_count=1)
cudaq.observe(observe_kernel, spin.z(0))
if supports_run:
cudaq.run(run_kernel, shots_count=1)
except RuntimeError as err:
raise

assert log_path.exists()

entries = [
json.loads(line)
for line in log_path.read_text().splitlines()
if line.strip()
]
assert any(entry.get("type") == "configured" for entry in entries)
assert any(entry.get("type") == "executed" for entry in entries)


def test_pipeline_logging_builder_default(tmp_path, monkeypatch):
log_path = tmp_path / "pipeline.jsonl"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here. Wondering if the same log_file can be reused for these tests?

monkeypatch.setenv("CUDAQ_PIPELINE_LOG", str(log_path))

kernel = cudaq.make_kernel()
qubit = kernel.qalloc()
kernel.h(qubit)
kernel.mz(qubit)

cudaq.sample(kernel, shots_count=1)

assert log_path.exists()

entries = [
json.loads(line)
for line in log_path.read_text().splitlines()
if line.strip()
]
assert any(entry.get("type") == "configured" for entry in entries)
assert any(entry.get("type") == "executed" for entry in entries)
5 changes: 5 additions & 0 deletions runtime/common/BaseRestRemoteClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "common/ArgumentConversion.h"
#include "common/Environment.h"
#include "common/JsonConvert.h"
#include "common/PassPipelineLogging.h"
#include "common/RemoteKernelExecutor.h"
#include "common/RestClient.h"
#include "common/RuntimeMLIR.h"
Expand Down Expand Up @@ -205,6 +206,8 @@ class BaseRemoteRestRuntimeClient : public RemoteRuntimeClient {
moduleOp.getContext()->disableMultithreading();
pm.enableIRPrinting();
}
cudaq_internal::maybeLogPassPipeline(pm,
name + ":" + passName + "-synth");
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: just a thought. Should we have a function which constructs name + ":" + passName + "-synth" and returns it?

if (failed(pm.run(moduleOp)))
throw std::runtime_error("Could not successfully apply " + passName +
" synth.");
Expand Down Expand Up @@ -247,6 +250,7 @@ class BaseRemoteRestRuntimeClient : public RemoteRuntimeClient {
tm.setEnabled(cudaq::isTimingTagEnabled(cudaq::TIMING_JIT_PASSES));
auto timingScope = tm.getRootScope(); // starts the timer
pm.enableTiming(timingScope); // do this right before pm.run
cudaq_internal::maybeLogPassPipeline(pm, name + ":client");
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here.

if (failed(pm.run(moduleOp)))
throw std::runtime_error(
"Remote rest platform: applying IR passes failed.");
Expand Down Expand Up @@ -300,6 +304,7 @@ class BaseRemoteRestRuntimeClient : public RemoteRuntimeClient {
mlir::PassManager pm(ctx);
// For now, the server side expects full-QIR.
opt::addAOTPipelineConvertToQIR(pm);
cudaq_internal::maybeLogPassPipeline(pm, name + ":aot-qir");
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here.


if (failed(pm.run(moduleOp)))
throw std::runtime_error(
Expand Down
6 changes: 6 additions & 0 deletions runtime/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ add_library(cudaq-mlir-runtime
RuntimeMLIR.cpp
RuntimeCppMLIR.cpp
LayoutInfo.cpp
PassPipelineLogging.cpp
)
set_property(GLOBAL APPEND PROPERTY CUDAQ_RUNTIME_LIBS cudaq-mlir-runtime)

Expand All @@ -126,6 +127,11 @@ set_source_files_properties(
RuntimeMLIR.cpp
)

set_source_files_properties(
PassPipelineLogging.cpp
PROPERTIES COMPILE_OPTIONS "-fno-rtti"
)

target_include_directories(cudaq-mlir-runtime
PRIVATE .
${CMAKE_SOURCE_DIR}/tpls/spdlog/include
Expand Down
6 changes: 6 additions & 0 deletions runtime/common/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "common/ExecutionContext.h"
#include "common/FmtCore.h"
#include "common/NoiseModel.h"
#include "common/PassPipelineLogging.h"
#include "common/Resources.h"
#include "common/RuntimeMLIR.h"
#include "cudaq/Optimizer/Builder/Runtime.h"
Expand Down Expand Up @@ -243,6 +244,7 @@ std::vector<cudaq::KernelExecution> Compiler::lowerQuakeCodePart2(
moduleOpIn.getContext()->disableMultithreading();
if (enablePrintMLIREachPass)
pm.enableIRPrinting();
cudaq_internal::maybeLogPassPipeline(pm, kernelName);
if (failed(pm.run(moduleOpIn)))
throw std::runtime_error("Remote rest platform Quake lowering failed.");
};
Expand Down Expand Up @@ -311,6 +313,7 @@ std::vector<cudaq::KernelExecution> Compiler::lowerQuakeCodePart2(
moduleOp.getContext()->disableMultithreading();
if (enablePrintMLIREachPass)
pm.enableIRPrinting();
cudaq_internal::maybeLogPassPipeline(pm, kernelName + ":quake-synth");
if (failed(pm.run(moduleOp)))
throw std::runtime_error("Could not successfully apply quake-synth.");
}
Expand Down Expand Up @@ -370,6 +373,8 @@ std::vector<cudaq::KernelExecution> Compiler::lowerQuakeCodePart2(
pm.addPass(mlir::createCanonicalizerPass());
if (enablePrintMLIREachPass)
pm.enableIRPrinting();
cudaq_internal::maybeLogPassPipeline(pm, kernelName +
":resource-count-preprocess");
if (failed(pm.run(moduleOp)))
throw std::runtime_error(
"Could not successfully apply resource count preprocess.");
Expand Down Expand Up @@ -451,6 +456,7 @@ std::vector<cudaq::KernelExecution> Compiler::lowerQuakeCodePart2(
tmpModuleOp.getContext()->disableMultithreading();
if (enablePrintMLIREachPass)
pm.enableIRPrinting();
cudaq_internal::maybeLogPassPipeline(pm, kernelName + ":observe-ansatz");
if (failed(pm.run(tmpModuleOp)))
throw std::runtime_error("Could not apply measurements to ansatz.");
// The full pass pipeline was run above, but the ansatz pass can
Expand Down
2 changes: 2 additions & 0 deletions runtime/common/JIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "JIT.h"
#include "common/Environment.h"
#include "common/PassPipelineLogging.h"
#include "common/Timing.h"
#include "cudaq/Frontend/nvqpp/AttributeNames.h"
#include "cudaq/Optimizer/Builder/Runtime.h"
Expand Down Expand Up @@ -299,6 +300,7 @@ cudaq::JitEngine cudaq::createQIRJITEngine(ModuleOp &moduleOp,
tm.setEnabled(cudaq::isTimingTagEnabled(cudaq::TIMING_JIT_PASSES));
auto timingScope = tm.getRootScope(); // starts the timer
pm.enableTiming(timingScope); // do this right before pm.run
cudaq_internal::maybeLogPassPipeline(pm, "createQIRJITEngine");
if (failed(pm.run(module))) {
engine.eraseHandler(handlerId);
throw std::runtime_error("[createQIRJITEngine] Lowering to QIR for "
Expand Down
Loading
Loading