Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
17 changes: 2 additions & 15 deletions runtime/cudaq/algorithms/run.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,6 @@ void (*get_run_entry_point(qkernel<R(As...)>, const std::string &name))(As...) {

} // namespace details

#if CUDAQ_USE_STD20
// Type checking helper.
template <typename T>
struct isVectorType : std::false_type {};

template <typename T, typename A>
struct isVectorType<std::vector<T, A>> : std::true_type {};
#endif

/// @brief Run a kernel \p shots number of times and return a `std::vector` of
/// results.
/// @tparam QuantumKernel Quantum kernel type (must return a non-void result)
Expand All @@ -118,9 +109,7 @@ struct isVectorType<std::vector<T, A>> : std::true_type {};
template <typename QuantumKernel, typename... ARGS>
#if CUDAQ_USE_STD20
requires(!std::is_void_v<std::invoke_result_t<std::decay_t<QuantumKernel>,
std::decay_t<ARGS>...>> &&
!isVectorType<std::invoke_result_t<std::decay_t<QuantumKernel>,
std::decay_t<ARGS>...>>::value)
std::decay_t<ARGS>...>>)
#endif
std::vector<
std::invoke_result_t<std::decay_t<QuantumKernel>, std::decay_t<ARGS>...>>
Expand Down Expand Up @@ -167,9 +156,7 @@ run(std::size_t shots, QuantumKernel &&kernel, ARGS &&...args) {
template <typename QuantumKernel, typename... ARGS>
#if CUDAQ_USE_STD20
requires(!std::is_void_v<std::invoke_result_t<std::decay_t<QuantumKernel>,
std::decay_t<ARGS>...>> &&
!isVectorType<std::invoke_result_t<std::decay_t<QuantumKernel>,
std::decay_t<ARGS>...>>::value)
std::decay_t<ARGS>...>>)
#endif
std::vector<
std::invoke_result_t<std::decay_t<QuantumKernel>, std::decay_t<ARGS>...>>
Expand Down
9 changes: 9 additions & 0 deletions runtime/cudaq/qis/execution_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ class measure_result {

operator int() const { return result; }
operator bool() const { return __nvqpp__MeasureResultBoolConversion(result); }

static std::vector<bool>
to_bool_vector(const std::vector<measure_result> &results) {
std::vector<bool> boolResults;
boolResults.reserve(results.size());
for (const auto &res : results)
boolResults.push_back(static_cast<bool>(res));
return boolResults;
}
};
#else
/// When compiling with MLIR, we default to a boolean.
Expand Down
135 changes: 92 additions & 43 deletions targettests/execution/cudaq_run.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,25 @@ __qpu__ std::vector<bool> vector_bool_test() {
return vec;
}

__qpu__ bool mz_test() {
cudaq::qubit q;
h(q);
return mz(q);
}

struct vector_mz_test {
std::vector<bool> operator()() __qpu__ {
cudaq::qvector q(5);
cudaq::qubit p;
x(q);
#ifdef CUDAQ_LIBRARY_MODE
return cudaq::measure_result::to_bool_vector(mz(q));
#else
return mz(q);
#endif
}
};

__qpu__ std::vector<int> vector_int_test() {
std::vector<int> result(2);
result[0] = 42;
Expand Down Expand Up @@ -76,27 +95,28 @@ auto struct_test = []() __qpu__ {
};

int main() {
std::size_t shots = 10;
int c = 0;
{
const auto results = cudaq::run(100, nullary_test);
if (results.size() != 100) {
printf("FAILED! Expected 100 shots. Got %lu\n", results.size());
const auto results = cudaq::run(shots, nullary_test);
if (results.size() != shots) {
printf("FAILED! Expected %lu shots. Got %lu\n", shots, results.size());
} else {
for (auto i : results)
printf("%d: %d\n", c++, i);
printf("success!\n");
printf("success - nullary_test\n");
}
}

{
const auto results = cudaq::run(50, unary_test, 4);
const auto results = cudaq::run(shots, unary_test, 4);
c = 0;
if (results.size() != 50) {
printf("FAILED! Expected 50 shots. Got %lu\n", results.size());
if (results.size() != shots) {
printf("FAILED! Expected %lu shots. Got %lu\n", shots, results.size());
} else {
for (auto i : results)
printf("%d: %d\n", c++, i);
printf("success!\n");
printf("success - unary_test\n");
}
}

Expand Down Expand Up @@ -124,98 +144,127 @@ int main() {
// Run async
{
const auto results =
cudaq::run_async(/*qpu_id=*/0, 100, nullary_test).get();
if (results.size() != 100) {
printf("FAILED! Expected 100 shots. Got %lu\n", results.size());
cudaq::run_async(/*qpu_id=*/0, shots, nullary_test).get();
if (results.size() != shots) {
printf("FAILED! Expected %lu shots. Got %lu\n", shots, results.size());
} else {
for (auto i : results)
printf("%d: %d\n", c++, i);
printf("success!\n");
printf("success async - nullary_test\n");
}
}

{
const auto results =
cudaq::run_async(/*qpu_id=*/0, 50, unary_test, 4).get();
cudaq::run_async(/*qpu_id=*/0, shots, unary_test, 4).get();
c = 0;
if (results.size() != 50) {
printf("FAILED! Expected 50 shots. Got %lu\n", results.size());
if (results.size() != shots) {
printf("FAILED! Expected %lu shots. Got %lu\n", shots, results.size());
} else {
for (auto i : results)
printf("%d: %d\n", c++, i);
printf("success!\n");
printf("success async - unary_test\n");
}
}

#if 0
// vector return types are not fully supported yet.
shots = 5;
{
const std::vector<std::vector<bool>> results =
cudaq::run(3, vector_bool_test);
cudaq::run(shots, vector_bool_test);
c = 0;
if (results.size() != 3) {
printf("FAILED! Expected 3 shots. Got %lu\n", results.size());
if (results.size() != shots) {
printf("FAILED! Expected %lu shots. Got %lu\n", shots, results.size());
} else {
for (auto i : results) {
printf("%d: {%d , %d}\n", c++, (bool)i[0], (bool)i[1]);
assert(i[0] == true);
assert(i[1] == false);
}
printf("success!\n");
printf("success - vector_bool_test\n");
}
}

{
const std::vector<bool> results = cudaq::run(shots, mz_test);
c = 0;
if (results.size() != shots) {
printf("FAILED! Expected %lu shots. Got %lu\n", shots, results.size());
} else {
for (auto i : results)
printf("%d: %d\n", c++, (bool)i);
printf("success - mz_test\n");
}
}

{
const std::vector<std::vector<bool>> results =
cudaq::run(shots, vector_mz_test{});
c = 0;
if (results.size() != shots) {
printf("FAILED! Expected %lu shots. Got %lu\n", shots, results.size());
} else {
for (auto i : results) {
printf("%d: {", c++);
for (auto b : i)
printf("%d ", (bool)b);
printf("}\n");
}
printf("success - vector_mz_test\n");
}
}

{
const std::vector<std::vector<int>> results =
cudaq::run(3, vector_int_test);
cudaq::run(shots, vector_int_test);
c = 0;
if (results.size() != 3) {
printf("FAILED! Expected 3 shots. Got %lu\n", results.size());
if (results.size() != shots) {
printf("FAILED! Expected %lu shots. Got %lu\n", shots, results.size());
} else {
for (auto i : results) {
printf("%d: {%d , %d}\n", c++, i[0], i[1]);
assert(i[0] == 42);
assert(i[1] == -13);
}
printf("success!\n");
printf("success - vector_int_test\n");
}
}

{
const std::vector<std::vector<float>> results =
cudaq::run(2, vector_float_test);
cudaq::run(shots, vector_float_test);
c = 0;
if (results.size() != 2) {
printf("FAILED! Expected 2 shots. Got %lu\n", results.size());
if (results.size() != shots) {
printf("FAILED! Expected %lu shots. Got %lu\n", shots, results.size());
} else {
for (auto i : results)
printf("%d: {%f , %f , %f}\n", c++, i[0], i[1], i[2]);
printf("success!\n");
printf("success - vector_float_test\n");
}
}
#endif

{
const auto results = cudaq::run(3, struct_test);
if (results.size() != 3) {
printf("FAILED! Expected 3 shots. Got %lu\n", results.size());
const auto results = cudaq::run(shots, struct_test);
if (results.size() != shots) {
printf("FAILED! Expected %lu shots. Got %lu\n", shots, results.size());
} else {
c = 0;
for (auto i : results)
printf("%d: {%s, %ld, %f}\n", c++, i.boolVal ? "true" : "false",
i.i64Val, i.f64Val);
printf("success!\n");
printf("success - struct_test\n");
}
}

return 0;
}

// CHECK: success!
// CHECK: success!
// CHECK: success!
// CHECK: success!
// XXECK: success!
// XXECK: success!
// XXECK: success!
// CHECK: success!
// CHECK: success - nullary_test
// CHECK: success - unary_test
// CHECK: success async - nullary_test
// CHECK: success async - unary_test
// CHECK: success - vector_bool_test
// CHECK: success - mz_test
// CHECK: success - vector_mz_test
// CHECK: success - vector_int_test
// CHECK: success - vector_float_test
// CHECK: success - struct_test
32 changes: 28 additions & 4 deletions targettests/execution/cudaq_run_emulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,50 @@ __qpu__ int test_kernel(int count) {
return result;
}

__qpu__ std::vector<bool> mz_test(int count) {
cudaq::qvector v(count);
h(v);
return mz(v);
}

int main() {
size_t shots = 20;
int c = 0;
{
constexpr int numQubits = 4;
auto results = cudaq::run(100, test_kernel, numQubits);
if (results.size() != 100) {
printf("FAILED! Expected 100 shots. Got %lu\n", results.size());
auto results = cudaq::run(shots, test_kernel, numQubits);
if (results.size() != shots) {
printf("FAILED! Expected %lu shots. Got %lu\n", shots, results.size());
} else {
for (auto i : results) {
printf("%d: %d\n", c++, i);
if (i != 0 && i != 4)
break;
}
if (c == 100)
if (c == shots)
printf("success!\n");
}
}

// Also test asynchronous API
{
const auto results =
cudaq::run_async(/*qpu_id=*/0, shots, mz_test, 2).get();
c = 0;
if (results.size() != shots) {
printf("FAILED! Expected %lu shots. Got %lu\n", shots, results.size());
} else {
for (auto i : results) {
printf("%d: %d %d\n", c++, (bool)i[0], (bool)i[1]);
}
if (c == shots)
printf("success async!\n");
}
}

return 0;
}

// FAIL: `run` is not yet supported on this target
// CHECK: success!
// CHECK: success async!
15 changes: 6 additions & 9 deletions test/AST-Quake/cudaq_run.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

#include <cudaq.h>

// FIXME: Results that are vectors are dropped on the floor!
struct K9 {
std::vector<bool> operator()() __qpu__ {
cudaq::qvector q(5);
Expand Down Expand Up @@ -50,18 +49,16 @@ struct CliffHanger {
Soap operator()() __qpu__ { return {true, 747}; }
};

// FIXME: Results that are vectors are dropped on the floor!
__qpu__ std::vector<float> unary_test_list(int count) {
cudaq::qvector v(count);
std::vector<float> vec {0, 1};
return vec;
cudaq::qvector v(count);
std::vector<float> vec{0, 1};
return vec;
}

// FIXME: Results that are vectors are dropped on the floor!
__qpu__ std::vector<bool> unary_test_list2(int count) {
cudaq::qvector v(count);
std::vector<bool> vec {false, true};
return vec;
cudaq::qvector v(count);
std::vector<bool> vec{false, true};
return vec;
}

// CHECK-LABEL: func.func @__nvqpp__mlirgen__K9.run()
Expand Down
Loading
Loading