Skip to content

Commit

Permalink
Merge branch 'master' into save-state
Browse files Browse the repository at this point in the history
  • Loading branch information
vvilpas authored Mar 11, 2021
2 parents 3daed71 + 1994b35 commit d31271f
Show file tree
Hide file tree
Showing 32 changed files with 2,086 additions and 825 deletions.
18 changes: 8 additions & 10 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@

# Generic rule for the repository. This pattern is actually the one that will
# apply unless specialized by a later rule
* @chriseclectic @vvilpas @atilag
* @chriseclectic @vvilpas

# Individual folders on root directory
/qiskit @chriseclectic @atilag @vvilpas
/cmake @atilag @vvilpas
/doc @chriseclectic @atilag @vvilpas
/examples @chriseclectic @atilag @vvilpas
/contrib @chriseclectic @atilag @vvilpas
/test @chriseclectic @atilag @vvilpas
/src @chriseclectic @atilag @vvilpas

# AER specific folders
/qiskit @chriseclectic @vvilpas @mtreinish
/test @chriseclectic @vvilpas @mtreinish
/doc @chriseclectic @vvilpas @mtreinish
/releasenotes @chriseclectic @vvilpas @mtreinish
/cmake @vvilpas
/contrib @chriseclectic @vvilpas @hhorii
/src @chriseclectic @vvilpas @hhorii
172 changes: 87 additions & 85 deletions CONTRIBUTING.md

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ To install from source, follow the instructions in the [contribution guidelines]

## Installing GPU support

In order to install and run the GPU supported simulators, you need CUDA® 10.1 or newer previously installed.
In order to install and run the GPU supported simulators on Linux, you need CUDA® 10.1 or newer previously installed.
CUDA® itself would require a set of specific GPU drivers. Please follow CUDA® installation procedure in the NVIDIA® [web](https://www.nvidia.com/drivers).

If you want to install our GPU supported simulators, you have to install this other package:
Expand All @@ -33,6 +33,11 @@ This will overwrite your current `qiskit-aer` package installation giving you
the same functionality found in the canonical `qiskit-aer` package, plus the
ability to run the GPU supported simulators: statevector, density matrix, and unitary.

**Note**: This package is only available on x86_64 Linux. For other platforms
that have CUDA support you will have to build from source. You can refer to
the [contributing guide](https://github.com/Qiskit/qiskit-aer/blob/master/CONTRIBUTING.md#building-with-gpu-support)
for instructions on doing this.

## Simulating your first quantum program with Qiskit Aer
Now that you have Qiskit Aer installed, you can start simulating quantum circuits with noise. Here is a basic example:

Expand Down
4 changes: 2 additions & 2 deletions qiskit/providers/aer/backends/qasm_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,8 +524,8 @@ def _method_configuration(method=None):
config.custom_instructions = sorted(['roerror', 'snapshot', 'save_statevector',
'save_expval', 'save_expval_var'])
config.basis_gates = sorted([
'cx', 'cz', 'id', 'x', 'y', 'z', 'h', 's', 'sdg', 'sx', 'swap',
'u0', 'u1', 'p', 'ccx', 'ccz', 'delay'
'cx', 'cz', 'id', 'x', 'y', 'z', 'h', 's', 'sdg', 'sx',
'swap', 'u0', 't', 'tdg', 'u1', 'p', 'ccx', 'ccz', 'delay'
] + config.custom_instructions)

return config
55 changes: 55 additions & 0 deletions src/controllers/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "noise/noise_model.hpp"
#include "transpile/basic_opts.hpp"
#include "transpile/truncate_qubits.hpp"
#include "transpile/cacheblocking.hpp"

namespace AER {
namespace Base {
Expand Down Expand Up @@ -216,8 +217,19 @@ class Controller {
set_distributed_parallelization(const std::vector<Circuit> &circuits,
const std::vector<Noise::NoiseModel> &noise);

virtual bool multiple_chunk_required(const Circuit &circuit,
const Noise::NoiseModel &noise) const;

void save_exception_to_results(Result &result,const std::exception &e);


//setting cache blocking transpiler
Transpile::CacheBlocking transpile_cache_blocking(const Circuit& circ,
const Noise::NoiseModel& noise,
const json_t& config,
const size_t complex_size,bool is_matrix) const;


// Get system memory size
size_t get_system_memory_mb();
size_t get_gpu_memory_mb();
Expand Down Expand Up @@ -274,6 +286,8 @@ class Controller {
//process information (MPI)
int myrank_ = 0;
int num_processes_ = 1;

uint_t cache_block_qubit_ = 0;
};

//=========================================================================
Expand Down Expand Up @@ -348,6 +362,11 @@ void Controller::set_config(const json_t &config) {
JSON::get_value(accept_distributed_results_, "accept_distributed_results", config);
}

//enable multiple qregs if cache blocking is enabled
cache_block_qubit_ = 0;
if(JSON::check_key("blocking_qubits", config)){
JSON::get_value(cache_block_qubit_,"blocking_qubits", config);
}
}

void Controller::clear_config() {
Expand Down Expand Up @@ -535,6 +554,21 @@ uint_t Controller::get_distributed_num_processes(bool par_shots) const
}
}

bool Controller::multiple_chunk_required(const Circuit &circ,
const Noise::NoiseModel &noise) const
{
if(circ.num_qubits < 3)
return false;

if(num_process_per_experiment_ > 1 || Controller::get_min_memory_mb() < required_memory_mb(circ, noise))
return true;

if(cache_block_qubit_ >= 2 && cache_block_qubit_ < circ.num_qubits)
return true;

return false;
}

size_t Controller::get_system_memory_mb() {
size_t total_physical_memory = 0;
#if defined(__linux__) || defined(__APPLE__)
Expand Down Expand Up @@ -654,6 +688,27 @@ void Controller::save_exception_to_results(Result &result,const std::exception &
}
}

Transpile::CacheBlocking Controller::transpile_cache_blocking(const Circuit& circ,
const Noise::NoiseModel& noise,
const json_t& config,
const size_t complex_size,bool is_matrix) const
{
Transpile::CacheBlocking cache_block_pass;

cache_block_pass.set_config(config);
if(!cache_block_pass.enabled()){
//if blocking is not set by config, automatically set if required
if(multiple_chunk_required(circ,noise)){
int nplace = num_process_per_experiment_;
if(num_gpus_ > 0)
nplace *= num_gpus_;
cache_block_pass.set_blocking(circ.num_qubits, get_min_memory_mb() << 20, nplace, complex_size,is_matrix);
}
}

return cache_block_pass;
}

//-------------------------------------------------------------------------
// Qobj execution
//-------------------------------------------------------------------------
Expand Down
94 changes: 28 additions & 66 deletions src/controllers/qasm_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,6 @@ class QasmController : public Base::Controller {
const Operations::OpSet &opset,
const json_t& config) const;


Transpile::CacheBlocking transpile_cache_blocking(const Circuit& circ,
const Noise::NoiseModel& noise,
const json_t& config) const;

//----------------------------------------------------------------
// Run circuit helpers
//----------------------------------------------------------------
Expand Down Expand Up @@ -306,9 +301,6 @@ class QasmController : public Base::Controller {

// Controller-level parameter for CH method
bool extended_stabilizer_measure_sampling_ = false;

//using multiple chunks
bool multiple_qregs_ = false;
};

//=========================================================================
Expand Down Expand Up @@ -381,11 +373,6 @@ void QasmController::set_config(const json_t& config) {
"QasmController: initial_statevector is not a unit vector");
}
}

//enable multiple qregs if cache blocking is enabled
if(JSON::check_key("blocking_enable", config)){
JSON::get_value(multiple_qregs_,"blocking_enable", config);
}
}

void QasmController::clear_config() {
Expand All @@ -407,7 +394,7 @@ void QasmController::run_circuit(const Circuit& circ,
// Validate circuit for simulation method
switch (simulation_method(circ, noise, true)) {
case Method::statevector: {
if(multiple_qregs_){
if(Base::Controller::multiple_chunk_required(circ,noise)){
if (simulation_precision_ == Precision::double_precision) {
// Double-precision Statevector simulation
return run_circuit_helper<StatevectorChunk::State<QV::QubitVector<double>>>(
Expand Down Expand Up @@ -440,7 +427,7 @@ void QasmController::run_circuit(const Circuit& circ,
"QasmController: method statevector_gpu is not supported on this "
"system");
#else
if(multiple_qregs_ || (parallel_shots_ > 1 || parallel_experiments_ > 1)){
if(Base::Controller::multiple_chunk_required(circ,noise) || (parallel_shots_ > 1 || parallel_experiments_ > 1)){
if (simulation_precision_ == Precision::double_precision) {
// Double-precision Statevector simulation
return run_circuit_helper<
Expand Down Expand Up @@ -478,7 +465,7 @@ void QasmController::run_circuit(const Circuit& circ,
"QasmController: method statevector_thrust is not supported on this "
"system");
#else
if(multiple_qregs_){
if(Base::Controller::multiple_chunk_required(circ,noise)){
if (simulation_precision_ == Precision::double_precision) {
// Double-precision Statevector simulation
return run_circuit_helper<
Expand Down Expand Up @@ -511,7 +498,7 @@ void QasmController::run_circuit(const Circuit& circ,
#endif
}
case Method::density_matrix: {
if(multiple_qregs_){
if(Base::Controller::multiple_chunk_required(circ,noise)){
if (simulation_precision_ == Precision::double_precision) {
// Double-precision density matrix simulation
return run_circuit_helper<
Expand Down Expand Up @@ -548,7 +535,7 @@ void QasmController::run_circuit(const Circuit& circ,
"QasmController: method density_matrix_gpu is not supported on this "
"system");
#else
if(multiple_qregs_ || (parallel_shots_ > 1 || parallel_experiments_ > 1)){
if(Base::Controller::multiple_chunk_required(circ,noise) || (parallel_shots_ > 1 || parallel_experiments_ > 1)){
if (simulation_precision_ == Precision::double_precision) {
// Double-precision density matrix simulation
return run_circuit_helper<
Expand Down Expand Up @@ -586,7 +573,7 @@ void QasmController::run_circuit(const Circuit& circ,
"this "
"system");
#else
if(multiple_qregs_){
if(Base::Controller::multiple_chunk_required(circ,noise)){
if (simulation_precision_ == Precision::double_precision) {
// Double-precision density matrix simulation
return run_circuit_helper<
Expand Down Expand Up @@ -938,42 +925,6 @@ Transpile::Fusion QasmController::transpile_fusion(Method method,
return fusion_pass;
}

Transpile::CacheBlocking QasmController::transpile_cache_blocking(const Circuit& circ,
const Noise::NoiseModel& noise,
const json_t& config) const
{
Transpile::CacheBlocking cache_block_pass;

cache_block_pass.set_config(config);
if(!cache_block_pass.enabled()){
//if blocking is not set by config, automatically set if required
if(Base::Controller::num_process_per_experiment_ > 1 || Base::Controller::get_min_memory_mb() < required_memory_mb(circ, noise)){
int nplace = Base::Controller::num_process_per_experiment_;
if(Base::Controller::num_gpus_ > 0)
nplace *= Base::Controller::num_gpus_;

size_t complex_size = (simulation_precision_ == Precision::single_precision) ? sizeof(std::complex<float>) : sizeof(std::complex<double>);

switch (simulation_method(circ, noise, false)) {
case Method::statevector:
case Method::statevector_thrust_cpu:
case Method::statevector_thrust_gpu:
cache_block_pass.set_blocking(circ.num_qubits, Base::Controller::get_min_memory_mb() << 20, nplace, complex_size,false);
break;
case Method::density_matrix:
case Method::density_matrix_thrust_cpu:
case Method::density_matrix_thrust_gpu:
cache_block_pass.set_blocking(circ.num_qubits, Base::Controller::get_min_memory_mb() << 20, nplace, complex_size,true);
break;
default:
throw std::runtime_error("QasmController: No enough memory to simulate this method on the sysytem");
}
}
}

return cache_block_pass;
}

void QasmController::set_parallelization_circuit(
const Circuit& circ,
const Noise::NoiseModel& noise_model) {
Expand Down Expand Up @@ -1148,9 +1099,19 @@ void QasmController::run_circuit_helper(const Circuit& circ,
auto fusion_pass = transpile_fusion(method, opt_circ.opset(), config);
fusion_pass.optimize_circuit(opt_circ, dummy_noise, state.opset(), result);

auto cache_block_pass = transpile_cache_blocking(opt_circ,noise,config);
bool is_matrix = false;
if(method == Method::density_matrix || method == Method::density_matrix_thrust_gpu || method == Method::density_matrix_thrust_cpu)
is_matrix = true;
auto cache_block_pass = transpile_cache_blocking(opt_circ,noise,config,(simulation_precision_ == Precision::single_precision) ? sizeof(std::complex<float>) : sizeof(std::complex<double>),is_matrix);
cache_block_pass.optimize_circuit(opt_circ, dummy_noise, state.opset(), result);

uint_t block_bits = 0;
if(cache_block_pass.enabled())
block_bits = cache_block_pass.block_bits();

//allocate qubit register
state.allocate(Base::Controller::max_qubits_,block_bits);

// Run simulation
run_multi_shot(opt_circ, shots, state, initial_state, method, result, rng);
}
Expand Down Expand Up @@ -1179,9 +1140,6 @@ void QasmController::run_multi_shot(const Circuit& circ,
// Implement measure sampler
auto pos = circ.first_measure_pos; // Position of first measurement op

//allocate qubit register
state.allocate(Base::Controller::max_qubits_);

// Run circuit instructions before first measure
std::vector<Operations::Op> ops(circ.ops.begin(),
circ.ops.begin() + pos);
Expand All @@ -1197,9 +1155,6 @@ void QasmController::run_multi_shot(const Circuit& circ,
// Add measure sampling metadata
result.metadata.add(true, "measure_sampling");
} else {
//allocate qubit register
state.allocate(Base::Controller::max_qubits_);

// Perform standard execution if we cannot apply the
// measurement sampling optimization
while (shots-- > 0) {
Expand All @@ -1225,10 +1180,10 @@ void QasmController::run_circuit_with_sampled_noise(const Circuit& circ,
measure_pass.set_config(config);
Noise::NoiseModel dummy_noise;

auto cache_block_pass = transpile_cache_blocking(circ,noise,config);

//allocate qubit register
state.allocate(Base::Controller::max_qubits_);
bool is_matrix = false;
if(method == Method::density_matrix || method == Method::density_matrix_thrust_gpu || method == Method::density_matrix_thrust_cpu)
is_matrix = true;
auto cache_block_pass = transpile_cache_blocking(circ,noise,config,(simulation_precision_ == Precision::single_precision) ? sizeof(std::complex<float>) : sizeof(std::complex<double>),is_matrix);

// Sample noise using circuit method
while (shots-- > 0) {
Expand All @@ -1238,6 +1193,13 @@ void QasmController::run_circuit_with_sampled_noise(const Circuit& circ,
fusion_pass.optimize_circuit(noise_circ, dummy_noise, state.opset(), result);
cache_block_pass.optimize_circuit(noise_circ, dummy_noise, state.opset(), result);

uint_t block_bits = 0;
if(cache_block_pass.enabled())
block_bits = cache_block_pass.block_bits();

//allocate qubit register
state.allocate(Base::Controller::max_qubits_,block_bits);

run_single_shot(noise_circ, state, initial_state, result, rng);
}
}
Expand Down
Loading

0 comments on commit d31271f

Please sign in to comment.