-
Notifications
You must be signed in to change notification settings - Fork 90
Sparse simulator #767
Sparse simulator #767
Conversation
src/Simulation/Simulators/SparseSimulator/Native/SparseSimulator.h
Outdated
Show resolved
Hide resolved
src/Simulation/Simulators/SparseSimulator/Native/SparseSimulator.h
Outdated
Show resolved
Hide resolved
| logical_qubit_id shift; | ||
| logical_qubit_id target_2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: A number of data members stay uninitialized in a number of constructors.
You may find useful the Non-static data member initializers.
| @@ -0,0 +1,846 @@ | |||
| #pragma once | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Up to you)
This is a C++ file.
You may want to change the extension from .h to .hpp.
You may want to break up the file into .hpp and .cpp.
src/Simulation/Simulators/SparseSimulator/Native/SparseSimulator.h
Outdated
Show resolved
Hide resolved
cgranade
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for opening this and for your contribution, @sam-jaques! I took a quick look through and left some comments, but happy to expand on anything that would be helpful. I think my overall feedback, though, is that it would be good to integrate this into the build pipelines and to make sure that your new simulator could be used from Python.
| return QVoid.Instance; | ||
| } | ||
|
|
||
| // This generates the channel, then calls it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to be intercepted by IQ# and Python hosts, this dump needs to be written out to SimulatorBase.OnDisplayableDiagnostic rather than to Message.
src/Simulation/Simulators/SparseSimulator/SparseSimulatorCS/Probes.cs
Outdated
Show resolved
Hide resolved
| /// <summary> | ||
| /// Returns a string that represents the phase of the amplitude. | ||
| /// </summary> | ||
| private string FormatAngle(double magnitude, double angle) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this may be duplicated with other angle formatting functionality.
src/Simulation/Simulators/SparseSimulator/Native/SparseSimulator.h
Outdated
Show resolved
Hide resolved
src/Simulation/Simulators/SparseSimulator/Native/CMakeLists.txt
Outdated
Show resolved
Hide resolved
| return mask; | ||
| } | ||
| // power of square root of -1 | ||
| inline amplitude iExp(int power) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like you have a mix of snake_case and camelCase here?
| #ifndef PCH_H | ||
| #define PCH_H | ||
|
|
||
| // add headers that you want to pre-compile here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this file needed? It looks like there's no headers nominated for precompilation.
| var release_configuration = Argument("configuration", "Release"); | ||
| var debug_configuration = Argument("configuration", "Debug"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd recomend camelCase instead of snake_case here.
| #include<chrono> | ||
| #include<thread> | ||
|
|
||
| std::string sample_string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This definition is pretty far from where it's used; a comment or such would be helpful here. More to the point, though, it looks like there's a single std::string shared between each simulator— what happens if multiple simulators are being run in different threads, with each running sample at the same time?
This isn't as contrived as it may sound, as that kind of issue can easily arise when running unit tests. Many test harnesses will parallelize by default, such that guarding shared resources with a mutex or other kind of lock may be necessary.
It looks like _mutex guards the vector of simulators, but once a simulator is extracted from the vector, a race condition may still be possible?
src/Simulation/Simulators/SparseSimulator/Native/SparseSimulator.h
Outdated
Show resolved
Hide resolved
| } | ||
| else | ||
| { | ||
| _simulators[emptySlot] = std::shared_ptr<SparseSimulator>(new SparseSimulator(num_qubits)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the future FYI: Item 21: Prefer std::make_unique and std::make_shared to direct use of new.
| std::shared_ptr<SparseSimulator>& getSimulator(unsigned id) | ||
| { | ||
| std::shared_lock<std::shared_mutex> shared_lock(_mutex); | ||
|
|
||
| return _simulators[id]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: Returns a non-const reference to the element of a container, thus enabling the update of the element in a non-thread-safe manner. E.g. someone can call getSimulator(..).reset() (the reset() call is not protected with _mutex) while some other thread can be accessing that same element (access protected with _mutex).
Consider returning by value:
std::shared_ptr<SparseSimulator> getSimulator(unsigned id) (no ampersand &).
| #include<chrono> | ||
| #include<thread> | ||
|
|
||
| std::string sample_string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider making sample_string a local variable (and a const reference to std::string). It is accessed in one function only.
|
@sam-jaques Thanks for putting this together! |
|
I made a quick run through the C/C++ code (but not C# code). I'm done with the first review round. |
| @@ -0,0 +1,1502 @@ | |||
| // Copyright Malte Skarupke 2017. | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an STL version of this? Can it be used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This hash map has better performance than the STL hash map, so it would be better if we can use this one. If we can't, the only functional difference from the STL hash map is the "jump_forward" function defined here, which makes the multi-threading faster.
src/Simulation/Simulators/SparseSimulator/SparseSimulatorTests/TestHelpers.cpp
Outdated
Show resolved
Hide resolved
…ck-2 More fixes from feedback
| size_t emptySlot = -1; | ||
| for (auto const& s : _simulators) | ||
| { | ||
| if (s == NULL) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if (s == NULL) | |
| if (s == nullptr) |
| std::vector<logical_qubit_id> controls; | ||
| operation(OP gate_type_arg, | ||
| logical_qubit_id target_arg, | ||
| std::vector<logical_qubit_id> controls_arg |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| std::vector<logical_qubit_id> controls_arg | |
| const std::vector<logical_qubit_id>& controls_arg |
| template<size_t num_qubits> | ||
| class QuantumState : public BasicQuantumState |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI:
See Item 44: Factor parameter-independent code out of templates in Effective C++: 55 Specific Ways to Improve Your Programs, 3rd edition, by Scott Meyers.
| template<size_t num_qubits> | ||
| class QuantumState : public BasicQuantumState |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file (and this class in particular) will definitely benefit from breaking-up into multiple files.
Or at least it would be good to separate the definition of the class from the definition of the member functions:
// Definition of the class:
template<size_t num_qubits>
class QuantumState : public BasicQuantumState
{
public:
QuantumState(); // The member functions are declared only, but not defined here.
. . .
private:
// Member variables.
};
// Definition of the member functions (if it is a template class then in the same .hpp file):
template<size_t num_qubits>
QuantumState::QuantumState() {
. . .
}|
|
||
| if (isLogging) | ||
| { | ||
| stackDepth = stackDepth[0..(stackDepth.Length - 1)]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know C# but I have an impression that this line does not change anything (assigns the value to itself, same as stackDepth = stackDepth).
…ck-3 Unit tests, comments and feedback from review
…ck-3 Some build fixes
Include and library dirs for OpenMP
Iterator dereference fix
Used std::unordered_map and removed parallel execution
This PR adds a new simulator that uses memory-efficient representations of sparse quantum states.