Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.

Conversation

@sam-jaques
Copy link
Contributor

This PR adds a new simulator that uses memory-efficient representations of sparse quantum states.

@ghost
Copy link

ghost commented Jul 5, 2021

CLA assistant check
All CLA requirements met.

Comment on lines 149 to 150
logical_qubit_id shift;
logical_qubit_id target_2;
Copy link
Contributor

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
Copy link
Contributor

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.

Copy link
Contributor

@cgranade cgranade left a 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
Copy link
Contributor

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.

/// <summary>
/// Returns a string that represents the phase of the amplitude.
/// </summary>
private string FormatAngle(double magnitude, double angle)
Copy link
Contributor

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.

return mask;
}
// power of square root of -1
inline amplitude iExp(int power)
Copy link
Contributor

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
Copy link
Contributor

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.

Comment on lines +3 to +4
var release_configuration = Argument("configuration", "Release");
var debug_configuration = Argument("configuration", "Debug");
Copy link
Contributor

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;
Copy link
Contributor

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?

}
else
{
_simulators[emptySlot] = std::shared_ptr<SparseSimulator>(new SparseSimulator(num_qubits));
Copy link
Contributor

@kuzminrobin kuzminrobin Jul 7, 2021

Choose a reason for hiding this comment

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

Comment on lines +59 to +64
std::shared_ptr<SparseSimulator>& getSimulator(unsigned id)
{
std::shared_lock<std::shared_mutex> shared_lock(_mutex);

return _simulators[id];
}
Copy link
Contributor

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;
Copy link
Contributor

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.

@bettinaheim
Copy link
Contributor

@sam-jaques Thanks for putting this together!
I'll create a feature branch shortly for this to be merged into, and @DmitryVasilevsky will coordinate and work with you on updating this branch with the latest and processing the feedback.

@kuzminrobin
Copy link
Contributor

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.
Copy link
Contributor

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?

Copy link
Contributor Author

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.

@bettinaheim bettinaheim changed the base branch from main to feature/sparse-simulator July 9, 2021 01:34
size_t emptySlot = -1;
for (auto const& s : _simulators)
{
if (s == NULL)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
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
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
std::vector<logical_qubit_id> controls_arg
const std::vector<logical_qubit_id>& controls_arg

Comment on lines +81 to +82
template<size_t num_qubits>
class QuantumState : public BasicQuantumState
Copy link
Contributor

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.

Comment on lines +81 to +82
template<size_t num_qubits>
class QuantumState : public BasicQuantumState
Copy link
Contributor

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)];
Copy link
Contributor

@kuzminrobin kuzminrobin Sep 9, 2021

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).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants