Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
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
38 changes: 19 additions & 19 deletions src/Simulation/Native/src/simulator/capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ MICROSOFT_QUANTUM_DECL void destroy(_In_ unsigned id)

MICROSOFT_QUANTUM_DECL void seed(_In_ unsigned id, _In_ unsigned s)
{
psis[id]->seed(s);
Microsoft::Quantum::Simulator::get(id)->seed(s);
}

// non-quantum
MICROSOFT_QUANTUM_DECL std::size_t random_choice(_In_ unsigned id, _In_ std::size_t n, _In_reads_(n) double* p)
{
return psis[id]->random(n, p);
return Microsoft::Quantum::Simulator::get(id)->random(n, p);
}

MICROSOFT_QUANTUM_DECL double JointEnsembleProbability(_In_ unsigned id, _In_ unsigned n, _In_reads_(n) int* b, _In_reads_(n) unsigned* q)
Expand All @@ -36,35 +36,35 @@ MICROSOFT_QUANTUM_DECL double JointEnsembleProbability(_In_ unsigned id, _In_ un
for (unsigned i = 0; i < n; ++i)
bv.push_back(static_cast<Gates::Basis>(*(b + i)));
std::vector<unsigned> qv(q, q + n);
return psis[id]->JointEnsembleProbability( bv, qv);
return Microsoft::Quantum::Simulator::get(id)->JointEnsembleProbability( bv, qv);
}


MICROSOFT_QUANTUM_DECL void allocateQubit(_In_ unsigned id, _In_ unsigned q)
{
psis[id]->allocateQubit(q);
Microsoft::Quantum::Simulator::get(id)->allocateQubit(q);
}

MICROSOFT_QUANTUM_DECL void release(_In_ unsigned id, _In_ unsigned q)
{
psis[id]->release(q);
Microsoft::Quantum::Simulator::get(id)->release(q);
}

MICROSOFT_QUANTUM_DECL unsigned num_qubits(_In_ unsigned id)
{
return psis[id]->num_qubits();
return Microsoft::Quantum::Simulator::get(id)->num_qubits();
}

#define FWDGATE1(G) \
MICROSOFT_QUANTUM_DECL void G(_In_ unsigned id, _In_ unsigned q) \
{ \
psis[id]->G(q); \
Microsoft::Quantum::Simulator::get(id)->G(q); \
}
#define FWDCSGATE1(G) \
MICROSOFT_QUANTUM_DECL void MC##G(_In_ unsigned id, _In_ unsigned n, _In_reads_(n) unsigned* c, _In_ unsigned q) \
{ \
std::vector<unsigned> vc(c, c + n); \
psis[id]->C##G(vc, q); \
Microsoft::Quantum::Simulator::get(id)->C##G(vc, q); \
}
#define FWD(G) FWDGATE1(G) FWDCSGATE1(G)

Expand All @@ -88,14 +88,14 @@ FWD(AdjT)

MICROSOFT_QUANTUM_DECL void R(_In_ unsigned id, _In_ unsigned b, _In_ double phi, _In_ unsigned q)
{
psis[id]->R(static_cast<Gates::Basis>(b), phi, q);
Microsoft::Quantum::Simulator::get(id)->R(static_cast<Gates::Basis>(b), phi, q);
}

// multi-controlled rotations
MICROSOFT_QUANTUM_DECL void MCR(_In_ unsigned id, _In_ unsigned b, _In_ double phi, _In_ unsigned nc, _In_reads_(nc) unsigned* c, _In_ unsigned q)
{
std::vector<unsigned> cv(c, c + nc);
psis[id]->CR(static_cast<Gates::Basis>(b), phi, cv, q);
Microsoft::Quantum::Simulator::get(id)->CR(static_cast<Gates::Basis>(b), phi, cv, q);
}

// Exponential of Pauli operators
Expand All @@ -105,7 +105,7 @@ MICROSOFT_QUANTUM_DECL void Exp(_In_ unsigned id, _In_ unsigned n, _In_reads_(n)
for (unsigned i = 0; i < n; ++i)
bv.push_back(static_cast<Gates::Basis>(*(b + i)));
std::vector<unsigned> qv(q, q + n);
psis[id]->Exp(bv, phi, qv);
Microsoft::Quantum::Simulator::get(id)->Exp(bv, phi, qv);
}
MICROSOFT_QUANTUM_DECL void MCExp(_In_ unsigned id, _In_ unsigned n, _In_reads_(n) unsigned* b, _In_ double phi, _In_ unsigned nc, _In_reads_(nc) unsigned* c, _In_reads_(n) unsigned* q)
{
Expand All @@ -114,55 +114,55 @@ MICROSOFT_QUANTUM_DECL void MCExp(_In_ unsigned id, _In_ unsigned n, _In_reads_(
bv.push_back(static_cast<Gates::Basis>(*(b + i)));
std::vector<unsigned> qv(q, q + n);
std::vector<unsigned> cv(c, c + nc);
psis[id]->CExp(bv, phi, cv, qv);
Microsoft::Quantum::Simulator::get(id)->CExp(bv, phi, cv, qv);
}

// measurements
MICROSOFT_QUANTUM_DECL unsigned M(_In_ unsigned id, _In_ unsigned q)
{
return (unsigned)psis[id]->M(q);
return (unsigned)Microsoft::Quantum::Simulator::get(id)->M(q);
}
MICROSOFT_QUANTUM_DECL unsigned Measure(_In_ unsigned id, _In_ unsigned n, _In_reads_(n) unsigned* b, _In_reads_(n) unsigned* q)
{
std::vector<Gates::Basis> bv;
for (unsigned i = 0; i < n; ++i)
bv.push_back(static_cast<Gates::Basis>(*(b + i)));
std::vector<unsigned> qv(q, q + n);
return (unsigned)psis[id]->Measure(bv, qv);
return (unsigned)Microsoft::Quantum::Simulator::get(id)->Measure(bv, qv);
}

// apply permutation of basis states to the wave function
MICROSOFT_QUANTUM_DECL void PermuteBasis(_In_ unsigned id, _In_ unsigned n, _In_reads_(n) unsigned* q, _In_ std::size_t table_size,
_In_reads_(table_size) std::size_t *permutation_table)
{
const std::vector<unsigned> qs(q, q + n);
psis[id]->permuteBasis(qs, table_size, permutation_table, false);
Microsoft::Quantum::Simulator::get(id)->permuteBasis(qs, table_size, permutation_table, false);
}
MICROSOFT_QUANTUM_DECL void AdjPermuteBasis(_In_ unsigned id, _In_ unsigned n, _In_reads_(n) unsigned* q, _In_ std::size_t table_size,
_In_reads_(table_size) std::size_t *permutation_table)
{
const std::vector<unsigned> qs(q, q + n);
psis[id]->permuteBasis(qs, table_size, permutation_table, true);
Microsoft::Quantum::Simulator::get(id)->permuteBasis(qs, table_size, permutation_table, true);
}


// dump wavefunction to given callback until callback returns false
MICROSOFT_QUANTUM_DECL void Dump(_In_ unsigned id, _In_ bool (*callback)(size_t, double, double))
{
psis[id]->dump(callback);
Microsoft::Quantum::Simulator::get(id)->dump(callback);
}

// dump the wavefunction of the subset of qubits to the given callback returns false
MICROSOFT_QUANTUM_DECL bool DumpQubits(_In_ unsigned id, _In_ unsigned n, _In_reads_(n) unsigned* q, _In_ bool(*callback)(size_t, double, double))
{
std::vector<unsigned> qs(q, q + n);
return psis[id]->dumpQubits(qs, callback);
return Microsoft::Quantum::Simulator::get(id)->dumpQubits(qs, callback);
}

// dump the list of logical qubit ids to given callback
MICROSOFT_QUANTUM_DECL void DumpIds(_In_ unsigned id, _In_ void(*callback)(unsigned))
{
psis[id]->dumpIds(callback);
Microsoft::Quantum::Simulator::get(id)->dumpIds(callback);
}

}
27 changes: 17 additions & 10 deletions src/Simulation/Native/src/simulator/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "config.hpp"
#include "util/cpuid.hpp"
#include <iostream>
#include <shared_mutex>

namespace Microsoft
{
Expand All @@ -31,7 +32,8 @@ namespace Microsoft
{
namespace Simulator
{
mutex_type _mutex;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@dbwz8 This code used to use the #define that resolves to omp_mutex when OpenMP support is enabled. However, this code doesn't interact with any other OpenMP code/classes, so I think it should be safe to use the std class instead, especially since we compile with C++17 across all platforms now. Please let me know if this assumption is safe, and if not we can look at other solutions!

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks OK to me.

std::shared_mutex _mutex;
std::vector<std::shared_ptr<SimulatorInterface>> _psis;

SimulatorInterface* createSimulator(unsigned maxlocal)
{
Expand All @@ -52,39 +54,44 @@ namespace Microsoft

MICROSOFT_QUANTUM_DECL unsigned create(unsigned maxlocal)
{
std::lock_guard<mutex_type> lock(_mutex);
std::lock_guard<std::shared_mutex> lock(_mutex);

size_t emptySlot = -1;
for (auto const& s : psis)
for (auto const& s : _psis)
{
if (s == NULL)
{
emptySlot = &s - &psis[0];
emptySlot = &s - &_psis[0];
break;
}
}

if (emptySlot == -1)
{
psis.push_back(std::shared_ptr<SimulatorInterface>(createSimulator(maxlocal)));
emptySlot = psis.size() - 1;
_psis.push_back(std::shared_ptr<SimulatorInterface>(createSimulator(maxlocal)));
emptySlot = _psis.size() - 1;
}
else
{
psis[emptySlot] = std::shared_ptr<SimulatorInterface>(createSimulator(maxlocal));
_psis[emptySlot] = std::shared_ptr<SimulatorInterface>(createSimulator(maxlocal));
}

return static_cast<unsigned>(emptySlot);
}

MICROSOFT_QUANTUM_DECL void destroy(unsigned id)
{
std::lock_guard<mutex_type> lock(_mutex);
std::lock_guard<std::shared_mutex> lock(_mutex);

psis[id].reset();
_psis[id].reset();
}

MICROSOFT_QUANTUM_DECL std::vector<std::shared_ptr<SimulatorInterface>> psis;
MICROSOFT_QUANTUM_DECL std::shared_ptr<SimulatorInterface>& get(unsigned id)
{
std::shared_lock<std::shared_mutex> shared_lock(_mutex);

return _psis[id];
}

}
}
Expand Down
3 changes: 1 addition & 2 deletions src/Simulation/Native/src/simulator/factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ namespace Microsoft
{
MICROSOFT_QUANTUM_DECL unsigned create(unsigned =0u);
MICROSOFT_QUANTUM_DECL void destroy(unsigned);

extern MICROSOFT_QUANTUM_DECL std::vector<std::shared_ptr<SimulatorInterface>> psis;
MICROSOFT_QUANTUM_DECL std::shared_ptr<SimulatorInterface>& get(unsigned);
}
}
}
2 changes: 1 addition & 1 deletion src/Simulation/Native/src/simulator/factory_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ using namespace Microsoft::Quantum::Simulator;

int main(int argc, char** argv)
{
auto& sim = psis[create()];
auto sim = get(create());

unsigned q=0; // qubit number
sim->allocateQubit(q);
Expand Down