Skip to content

Commit

Permalink
Create separate runtime for per-tuple measurements
Browse files Browse the repository at this point in the history
  • Loading branch information
ausbin committed Jul 16, 2024
1 parent 63642ef commit a30ca35
Show file tree
Hide file tree
Showing 8 changed files with 454 additions and 82 deletions.
31 changes: 28 additions & 3 deletions app/qir-xacc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
#include "qiree/Executor.hh"
#include "qiree/Module.hh"
#include "qiree/QuantumNotImpl.hh"
#include "qirxacc/XaccDefaultRuntime.hh"
#include "qirxacc/XaccQuantum.hh"
#include "qirxacc/XaccTupleRuntime.hh"

using namespace std::string_view_literals;

Expand All @@ -27,16 +29,29 @@ namespace app
//---------------------------------------------------------------------------//
void run(std::string const& filename,
std::string const& accel_name,
int num_shots)
int num_shots,
bool print_accelbuf,
bool group_tuples)
{
// Load the input
Executor execute{Module{filename}};

// Set up XACC
XaccQuantum xacc(std::cout, accel_name, num_shots);
std::unique_ptr<RuntimeInterface> rt;
if (group_tuples)
{
rt = std::make_unique<XaccTupleRuntime>(
std::cout, xacc, print_accelbuf);
}
else
{
rt = std::make_unique<XaccDefaultRuntime>(
std::cout, xacc, print_accelbuf);
}

// Run
execute(xacc, xacc);
execute(xacc, *rt);
}

//---------------------------------------------------------------------------//
Expand All @@ -52,6 +67,8 @@ int main(int argc, char* argv[])
int num_shots{1024};
std::string accel_name;
std::string filename;
bool print_accelbuf{true};
bool group_tuples{false};

CLI::App app;
auto* filename_opt
Expand All @@ -63,10 +80,18 @@ int main(int argc, char* argv[])
auto* nshot_opt
= app.add_option("-s,--shots", num_shots, "Number of shots");
nshot_opt->capture_default_str();
app.add_flag("--print-accelbuf,!--no-print-accelbuf",
print_accelbuf,
"Print XACC AcceleratorBuffer");
app.add_flag("--group-tuples,!--no-group-tuples",
group_tuples,
"Print per-tuple measurement statistics rather than "
"per-qubit");

CLI11_PARSE(app, argc, argv);

qiree::app::run(filename, accel_name, num_shots);
qiree::app::run(
filename, accel_name, num_shots, print_accelbuf, group_tuples);

return EXIT_SUCCESS;
}
2 changes: 2 additions & 0 deletions src/qirxacc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

qiree_add_library(qirxacc
XaccQuantum.cc
XaccDefaultRuntime.cc
XaccTupleRuntime.cc
)
target_link_libraries(qirxacc
PUBLIC QIREE::qiree
Expand Down
79 changes: 79 additions & 0 deletions src/qirxacc/XaccDefaultRuntime.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//----------------------------------*-C++-*----------------------------------//
// Copyright 2024 UT-Battelle, LLC, and other QIR-EE developers.
// See the top-level COPYRIGHT file for details.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//---------------------------------------------------------------------------//
//! \file qirxacc/XaccDefaultRuntime.cc
//---------------------------------------------------------------------------//
#include "XaccDefaultRuntime.hh"

#include "qiree/Assert.hh"

namespace qiree
{
//---------------------------------------------------------------------------//
/*!
* Initialize the execution environment, resetting qubits.
*/
void XaccDefaultRuntime::initialize(OptionalCString env)
{
if (env)
{
output_ << "Argument to initialize: " << env << std::endl;
}
}

//---------------------------------------------------------------------------//
/*!
* Execute circuit and mark the following N results as being part of an array
* named tag
*/
void XaccDefaultRuntime::array_record_output(size_type s, OptionalCString tag)
{
this->execute_if_needed();
output_ << "array " << (tag ? tag : "<null>") << " length " << s
<< std::endl;
}

//---------------------------------------------------------------------------//
/*!
* Execute circuit and mark the following N results as being part of a tuple
* named tag.
*/
void XaccDefaultRuntime::tuple_record_output(size_type s, OptionalCString tag)
{
this->execute_if_needed();
output_ << "tuple " << (tag ? tag : "<null>") << " length " << s
<< std::endl;
}

//---------------------------------------------------------------------------//
/*!
* Execute circuit and report a single measurement result
*/
void XaccDefaultRuntime::result_record_output(Result r, OptionalCString tag)
{
this->execute_if_needed();
Qubit q = xacc_.result_to_qubit(r);

// Get a map of string ("0" and "1" ???) -> int
auto counts = xacc_.get_marginal_counts({q});

// Print the result
output_ << "qubit " << q.value << " experiment " << (tag ? tag : "<null>")
<< ": {0: " << counts["0"] << ", 1: " << counts["1"] << '}'
<< std::endl;
}

//---------------------------------------------------------------------------//
// PRIVATE FUNCTIONS
//---------------------------------------------------------------------------//

void XaccDefaultRuntime::execute_if_needed()
{
if (xacc_.execute_if_needed() && print_accelbuf_)
{
xacc_.print_accelbuf();
}
}
} // namespace qiree
76 changes: 76 additions & 0 deletions src/qirxacc/XaccDefaultRuntime.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//----------------------------------*-C++-*----------------------------------//
// Copyright 2024 UT-Battelle, LLC, and other QIR-EE developers.
// See the top-level COPYRIGHT file for details.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//---------------------------------------------------------------------------//
//! \file qirxacc/XaccDefaultRuntime.hh
//---------------------------------------------------------------------------//
#pragma once

#include "qiree/RuntimeInterface.hh"
#include "qirxacc/XaccQuantum.hh"

namespace qiree
{
class XaccQuantum;

//---------------------------------------------------------------------------//
/*!
* Print per-qubit measurement statistics.
*
* (Compare with \ref XaccTupleRuntime.)
*
* Example:
* \code
* tuple ret length 2
* qubit 0 experiment <null>: {0: 509, 1: 515}
* qubit 1 experiment <null>: {0: 509, 1: 515}
* \endcode
*/
class XaccDefaultRuntime final : virtual public RuntimeInterface
{
public:
// Construct with XACC quantum runtime and options
inline XaccDefaultRuntime(std::ostream& output,
XaccQuantum& xacc,
bool print_accelbuf);

//!@{
//! \name Runtime interface
// Initialize the execution environment, resetting qubits
void initialize(OptionalCString env) override;

//! Mark the following N results as being part of an array named tag
void array_record_output(size_type, OptionalCString tag) final;

//! Mark the following N results as being part of a tuple named tag
void tuple_record_output(size_type, OptionalCString) final;

// Save one result
void result_record_output(Result result, OptionalCString tag) final;
//!@}

private:
std::ostream& output_;
XaccQuantum& xacc_;
bool const print_accelbuf_;

void execute_if_needed();
};

//---------------------------------------------------------------------------//
/*!
* Construct an \c XaccDefaultRuntime.
*
* The \c print_accelbuf argument determines whether the XACC \c
* AcceleratorBuffer is dumped after execution.
*/
XaccDefaultRuntime::XaccDefaultRuntime(std::ostream& output,
XaccQuantum& xacc,
bool print_accelbuf = true)
: output_(output), xacc_(xacc), print_accelbuf_(print_accelbuf)
{
}

//---------------------------------------------------------------------------//
} // namespace qiree
95 changes: 33 additions & 62 deletions src/qirxacc/XaccQuantum.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ void XaccQuantum::set_up(EntryPointAttrs const& attrs)
QIREE_VALIDATE(attrs.required_num_qubits > 0,
<< "input is not a quantum program");

executed_ = false;
buffer_ = xacc::qalloc(attrs.required_num_qubits);
cur_circuit_ = provider_->createComposite("quantum_circuit");
result_to_qubit_.resize(attrs.required_num_results);
Expand Down Expand Up @@ -148,68 +149,6 @@ QState XaccQuantum::read_result(Result r)
return QState::one;
}

//---------------------------------------------------------------------------//
/*!
* Initialize the execution environment, resetting qubits.
*/
void XaccQuantum::initialize(OptionalCString env)
{
if (env)
{
output_
<< "What's env for? No one knows! But here is some value: " << env
<< std::endl;
}
}

//---------------------------------------------------------------------------//
/*!
* Execute the circuit and read outputs.
*/
void XaccQuantum::array_record_output(size_type, OptionalCString)
{
try
{
accelerator_->execute(buffer_, cur_circuit_);
}
catch (std::exception const& e)
{
output_ << "Failed to execute XACC: " << e.what() << std::endl;
}
buffer_->print(output_);
}

//---------------------------------------------------------------------------//
/*!
* Mark the start of an array and its size.
*/
void XaccQuantum::result_record_output(Result r, OptionalCString tag)
{
QIREE_EXPECT(r.value < this->num_results());
using BitOrder = xacc::AcceleratorBuffer::BitOrder;

auto q = result_to_qubit_[r.value];

// Get a map of string ("0" and "1" ???) -> int
auto counts = buffer_->getMarginalCounts(
{static_cast<int>(q.value)},
endian_ == Endianness::little ? BitOrder::LSB : BitOrder::MSB);

// Print the result
output_ << "qubit " << q.value << " experiment " << (tag ? tag : "<null>")
<< ": {0: " << counts["0"] << ", 1: " << counts["1"] << '}'
<< std::endl;
}

//---------------------------------------------------------------------------//
/*!
* No one uses tuples!
*/
void XaccQuantum::tuple_record_output(size_type, OptionalCString)
{
QIREE_NOT_IMPLEMENTED("XaccQuantum::tuple_record_output");
}

//---------------------------------------------------------------------------//
// QUANTUM INSTRUCTION MAPPING
//---------------------------------------------------------------------------//
Expand Down Expand Up @@ -332,6 +271,38 @@ XaccQuantum::get_marginal_counts(std::vector<Qubit> const& qubits)
indices, endian_ == Endianness::little ? BitOrder::LSB : BitOrder::MSB);
}

//---------------------------------------------------------------------------//
/*!
* Run the circuit on the accelerator if we have not already
*/
bool XaccQuantum::execute_if_needed()
{
if (executed_)
{
return false;
}

try
{
accelerator_->execute(buffer_, cur_circuit_);
executed_ = true;
}
catch (std::exception const& e)
{
output_ << "Failed to execute XACC: " << e.what() << std::endl;
}
return executed_;
}

//---------------------------------------------------------------------------//
/*!
* Print the results in the \c xacc::AcceleratorBuffer to the output
*/
void XaccQuantum::print_accelbuf()
{
buffer_->print(output_);
}

//---------------------------------------------------------------------------//
// PRIVATE FUNCTIONS
//---------------------------------------------------------------------------//
Expand Down
Loading

0 comments on commit a30ca35

Please sign in to comment.