Skip to content

Commit

Permalink
Merge branch 'main' into pr-change-sample-for-backends
Browse files Browse the repository at this point in the history
  • Loading branch information
bmhowe23 authored Jan 11, 2024
2 parents 2707095 + 6dc9c44 commit 92cee73
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 60 deletions.
6 changes: 6 additions & 0 deletions lib/Optimizer/Transforms/Mapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,12 @@ struct Mapper : public cudaq::opt::impl::MappingPassBase<Mapper> {
deviceDef = deviceDef.ltrim();
if (deviceDef.consume_back(")")) {
deviceFilename = deviceDef;
// Remove any leading and trailing single quotes that may have been
// added in order to pass files with spaces into the pass (required
// for parsePassPipeline).
if (deviceFilename.size() >= 2 && deviceFilename.front() == '\'' &&
deviceFilename.back() == '\'')
deviceFilename = deviceFilename.drop_front(1).drop_back(1);
// Make sure the file exists before continuing
if (!llvm::sys::fs::exists(deviceFilename)) {
llvm::errs() << "Path " << deviceFilename << " does not exist\n";
Expand Down
2 changes: 2 additions & 0 deletions runtime/cudaq/algorithms/observe.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
#include "cudaq/spin_op.h"
#include "host_config.h"
#include <functional>
#if CUDAQ_USE_STD20
#include <ranges>
#endif
#include <type_traits>
#include <vector>

Expand Down
19 changes: 16 additions & 3 deletions runtime/cudaq/platform/default/rest/RemoteRESTQPU.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2022 - 2023 NVIDIA Corporation & Affiliates. *
* Copyright (c) 2022 - 2024 NVIDIA Corporation & Affiliates. *
* All rights reserved. *
* *
* This source code and the accompanying materials are made available under *
Expand Down Expand Up @@ -233,8 +233,21 @@ class RemoteRESTQPU : public cudaq::QPU {
std::to_string(split.size()));

// Add to the backend configuration map
for (std::size_t i = 1; i < split.size(); i += 2)
backendConfig.insert({split[i], split[i + 1]});
for (std::size_t i = 1; i < split.size(); i += 2) {
// No need to decode trivial true/false values
if (split[i + 1].starts_with("base64_")) {
split[i + 1].erase(0, 7); // erase "base64_"
std::vector<char> decoded_vec;
if (auto err = llvm::decodeBase64(split[i + 1], decoded_vec))
throw std::runtime_error("DecodeBase64 error");
std::string decodedStr(decoded_vec.data(), decoded_vec.size());
cudaq::info("Decoded {} parameter from '{}' to '{}'", split[i],
split[i + 1], decodedStr);
backendConfig.insert({split[i], decodedStr});
} else {
backendConfig.insert({split[i], split[i + 1]});
}
}
}

// Turn on emulation mode if requested
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2022 - 2023 NVIDIA Corporation & Affiliates. *
* Copyright (c) 2022 - 2024 NVIDIA Corporation & Affiliates. *
* All rights reserved. *
* *
* This source code and the accompanying materials are made available under *
Expand Down Expand Up @@ -271,9 +271,12 @@ IQMServerHelper::generateRequestHeader() const {

void IQMServerHelper::updatePassPipeline(
const std::filesystem::path &platformPath, std::string &passPipeline) {
// Note: the leading and trailing single quotes are needed in case there are
// spaces in the filename.
std::string pathToFile =
platformPath / std::string("mapping/iqm") /
(backendConfig["qpu-architecture"] + std::string(".txt"));
std::string("'") +
std::string(platformPath / std::string("mapping/iqm") /
(backendConfig["qpu-architecture"] + std::string(".txt'")));
passPipeline =
std::regex_replace(passPipeline, std::regex("%QPU_ARCH%"), pathToFile);
}
Expand Down
5 changes: 1 addition & 4 deletions runtime/cudaq/qis/execution_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@
#include "execution_manager.h"
#include "cudaq/platform.h"

namespace cudaq {
bool __nvqpp__MeasureResultBoolConversion(int result) {
bool cudaq::__nvqpp__MeasureResultBoolConversion(int result) {
auto &platform = get_platform();
auto *ctx = platform.get_exec_ctx();
if (ctx && ctx->name == "tracer")
ctx->registerNames.push_back("");

return result == 1;
}
} // namespace cudaq
73 changes: 35 additions & 38 deletions runtime/cudaq/qis/execution_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,45 +10,41 @@

#include "common/QuditIdTracker.h"
#include "cudaq/spin_op.h"
#include <cassert>
#include <complex>
#include <cstddef>
#include <deque>
#include <span>
#include <string_view>
#include <vector>

namespace cudaq {
class ExecutionContext;
using SpinMeasureResult = std::pair<double, sample_result>;

// A QuditInfo, to the ExecutionManager, is a type encoding
// the number of levels and the id of the qudit.
/// A QuditInfo is a type encoding the number of \a levels and the \a id of the
/// qudit to the ExecutionManager.
struct QuditInfo {
std::size_t levels = 0;
std::size_t id = 0;
QuditInfo(const std::size_t &_levels, const std::size_t &_id)
: levels(_levels), id(_id) {}
QuditInfo(std::size_t _levels, std::size_t _id) : levels(_levels), id(_id) {}
bool operator==(const QuditInfo &other) {
return levels == other.levels && id == other.id;
}
};

extern "C" {
bool __nvqpp__MeasureResultBoolConversion(int);
}

#ifdef CUDAQ_LIBRARY_MODE

/// @brief In library mode, we model the return type of
/// a qubit measurement result via the measure_result type.
/// This allows us to keep track of when the result is
/// implicitly cast to a boolean (likely in the case of
/// conditional feedback), and affect the simulation accordingly
/// In library mode, we model the return type of a qubit measurement result via
/// the measure_result type. This allows us to keep track of when the result is
/// implicitly cast to a boolean (likely in the case of conditional feedback),
/// and affect the simulation accordingly.
class measure_result {
private:
/// @brief The intrinsic measurement result
/// The intrinsic measurement result
int result = 0;

/// @brief Unique integer for measure result identification
/// Unique integer for measure result identification
std::size_t uniqueId = 0;

public:
Expand All @@ -59,16 +55,16 @@ class measure_result {
operator bool() { return __nvqpp__MeasureResultBoolConversion(result); }
};
#else
/// @brief When compiling with MLIR, we default to a boolean
/// When compiling with MLIR, we default to a boolean.
using measure_result = bool;
#endif

/// The ExecutionManager provides a base class describing a
/// concrete sub-system for allocating qudits and executing quantum
/// instructions on those qudits. This type is templated on the concrete
/// qudit type (`qubit`, `qmode`, etc). It exposes an API for getting an
/// available qudit id, returning that id, setting and resetting the
/// current execution context, and applying specific quantum instructions.
/// The ExecutionManager provides a base class describing a concrete sub-system
/// for allocating qudits and executing quantum instructions on those qudits.
/// This type is templated on the concrete qudit type (`qubit`, `qmode`, etc).
/// It exposes an API for getting an available qudit id, returning that id,
/// setting and resetting the current execution context, and applying specific
/// quantum instructions.
class ExecutionManager {
protected:
/// Available qudit indices
Expand All @@ -77,8 +73,8 @@ class ExecutionManager {
/// Total qudits available
std::size_t totalQudits;

/// @brief Utility type tracking qudit unique
/// identifiers as they are allocated and deallocated.
/// Utility type tracking qudit unique identifiers as they are allocated and
/// deallocated.
QuditIdTracker tracker;

/// Internal - return the next qudit index
Expand Down Expand Up @@ -106,10 +102,10 @@ class ExecutionManager {
/// Reset the execution context
virtual void resetExecutionContext() = 0;

/// Apply the quantum instruction with the given name, on the provided
/// target qudits. Supports input of control qudits and rotational parameters.
/// Can also optionally take a spin_op as input to affect a general
/// Pauli rotation.
/// Apply the quantum instruction with the given name, on the provided target
/// qudits. Supports input of control qudits and rotational parameters. Can
/// also optionally take a spin_op as input to affect a general Pauli
/// rotation.
virtual void apply(const std::string_view gateName,
const std::vector<double> &params,
const std::vector<QuditInfo> &controls,
Expand All @@ -124,33 +120,34 @@ class ExecutionManager {
/// End the adjoint region
virtual void endAdjointRegion() = 0;

/// Start a region of code where all operations will be
/// controlled on the given qudits.
/// Start a region of code where all operations will be controlled on the
/// given qudits.
virtual void
startCtrlRegion(const std::vector<std::size_t> &control_qubits) = 0;
/// End the control region
virtual void endCtrlRegion(std::size_t n_controls) = 0;

/// Measure the qudit and return the observed state (0,1,2,3,...)
/// e.g. for qubits, this can return 0 or 1;
// Measure the qudit and return the observed state \f$(0,1,2,3,...)\f$; e.g.,
// for qubits this can return 0 or 1.
virtual int measure(const QuditInfo &target) = 0;

/// Measure the current state in the given Pauli basis, return
/// the expectation value <term>.
/// Measure the current state in the given Pauli basis, return the expectation
/// value <term>.
virtual SpinMeasureResult measure(cudaq::spin_op &op) = 0;

/// Synchronize - run all queue-ed instructions
virtual void synchronize() = 0;
virtual ~ExecutionManager() = default;
};

/// Get the default execution manager instance.
ExecutionManager *getExecutionManager();
} // namespace cudaq

// The following macro is to be used by ExecutionManager subclass
// developers. It will define the global thread_local execution manager
// pointer instance, and define the factory function for clients to
// get reference to the execution manager
// The following macro is to be used by ExecutionManager subclass developers. It
// will define the global thread_local execution manager pointer instance, and
// define the factory function for clients to get reference to the execution
// manager.
#define CUDAQ_REGISTER_EXECUTION_MANAGER(Manager) \
namespace cudaq { \
ExecutionManager *getExecutionManager() { \
Expand Down
2 changes: 1 addition & 1 deletion runtime/cudaq/qis/qview.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

#include "cudaq/qis/qudit.h"
#include "host_config.h"
#include <ranges>
#if CUDAQ_USE_STD20
#include <ranges>
#include <span>
#endif

Expand Down
28 changes: 17 additions & 11 deletions tools/nvqpp/nvq++.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash

# ============================================================================ #
# Copyright (c) 2022 - 2023 NVIDIA Corporation & Affiliates. #
# Copyright (c) 2022 - 2024 NVIDIA Corporation & Affiliates. #
# All rights reserved. #
# #
# This source code and the accompanying materials are made available under #
Expand Down Expand Up @@ -307,7 +307,7 @@ LIBRARY_MODE=true
CXX=${LLVMBIN}clang++${llvm_suffix}
LINKER_CXX=${CXX}
CMAKE_FALLBACK_HOST_CXX=${CXX}
TARGET_ARGS=
TARGET_ARGS=()

if [[ $# -eq 0 ]]; then
SHOW_HELP=true
Expand All @@ -331,17 +331,23 @@ done
while [ $# -ne 0 ]; do
# Filter out any target-specific options.
if [[ $# -gt 1 ]] && [[ -n "${TARGET_CONFIG}" ]]; then
if [[ "$1" = --${TARGET_CONFIG}-* ]]; then
# Assume always has an additional value
TARGET_ARGS="${TARGET_ARGS} $1 $2"
shift 2
continue
elif [[ "$1" = --${TARGET_CONFIG}-*=* ]]; then
# Separate the value of argument
if [[ "$1" = --${TARGET_CONFIG}-*=* ]]; then
# Separate the value of argument. Perform base64 encoding on
# the parameter value in case it has spaces. The runtime will be
# responsible for decoding the value.
param="$1"
TARGET_ARGS="${TARGET_ARGS} ${param%=*} ${param#*=}"
ESC2="base64_"$(echo -n ${param#*=} | base64 --wrap=0)
TARGET_ARGS+=(${param%=*} $ESC2)
shift 1
continue
elif [[ "$1" = --${TARGET_CONFIG}-* ]]; then
# Assume always has an additional value. Perform base64 encoding on
# the parameter value in case it has spaces. The runtime will be
# responsible for decoding the value.
ESC2="base64_"$(echo -n $2 | base64 --wrap=0)
TARGET_ARGS+=($1 $ESC2)
shift 2
continue
fi
fi

Expand Down Expand Up @@ -570,7 +576,7 @@ if [ -n "${TARGET_CONFIG}" ]; then
TARGET_CONFIG_FILE="${install_dir}/targets/${TARGET_CONFIG}.config"
if [ -f "${TARGET_CONFIG_FILE}" ]; then
GEN_TARGET_BACKEND=false
. "${TARGET_CONFIG_FILE}" ${TARGET_ARGS}
. "${TARGET_CONFIG_FILE}" "${TARGET_ARGS[@]}"

if ${GEN_TARGET_BACKEND}; then
# Add a function that will run before main and set the target
Expand Down

0 comments on commit 92cee73

Please sign in to comment.