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
36 changes: 34 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,40 @@ jobs:
python -m pip install cibuildwheel==2.2.2
- name: Build wheels
env:
CIBW_BEFORE_ALL: "yum install -y yum-utils wget && wget https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel6-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm && rpm -i cuda-repo-rhel6-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm && yum clean all && yum -y install cuda-10-1 openblas-devel"
CIBW_SKIP: "*-manylinux_i686 pp* *musllinux*"
CIBW_BEFORE_ALL: "yum install -y yum-utils wget && wget -q https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel6-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm && rpm -i cuda-repo-rhel6-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm && yum clean all && yum -y install cuda-10-1 openblas-devel"
CIBW_SKIP: "*-manylinux_i686 cp310* pp* cp36* *musllinux*"
CIBW_ENVIRONMENT: QISKIT_AER_PACKAGE_NAME=qiskit-aer-gpu AER_THRUST_BACKEND=CUDA CUDACXX=/usr/local/cuda/bin/nvcc
run: |
python -m cibuildwheel --output-dir wheelhouse
- uses: actions/upload-artifact@v2
with:
path: ./wheelhouse/*.whl
- name: Publish Wheels
env:
TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}
TWINE_USERNAME: qiskit
run : |
pip install -U twine
twine upload wheelhouse/*
gpu-build-310:
name: Build qiskit-aer-gpu wheels
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
name: Install Python
with:
python-version: '3.7'
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.0.2
if: runner.os == 'Windows'
- name: Install cibuildwheel
run: |
python -m pip install cibuildwheel==2.2.2
- name: Build wheels
env:
CIBW_BEFORE_ALL: "yum install -y yum-utils wget && wget -q https://developer.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.105-418.39-1.0-1.x86_64.rpm && rpm -i cuda-repo-rhel7-10-1-local-10.1.105-418.39-1.0-1.x86_64.rpm && yum clean all && yum -y install cuda-10-1 openblas-devel"
CIBW_BUILD: "cp310-manylinux_x86_64"
CIBW_ENVIRONMENT: QISKIT_AER_PACKAGE_NAME=qiskit-aer-gpu AER_THRUST_BACKEND=CUDA CUDACXX=/usr/local/cuda/bin/nvcc
run: |
python -m cibuildwheel --output-dir wheelhouse
Expand Down
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ if(STATIC_LINKING)
endif()

if(NOT MSVC)
enable_cxx_compiler_flag_if_supported("-ffast-math")
if(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le")
# PowerPC builds are not meant to be redistributable, we build them
# in place, so we can have CPU = native.
Expand Down
5 changes: 5 additions & 0 deletions constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ scipy>=1.0
# with modern importlib-metadata (4.8.1). importlib-metadata is only needed on
# Python <3.8.
importlib-metadata==4.6.4

# Jinja2 3.1.0 is incompatible with sphinx and/or jupyter until they are updated
# to work with the new jinja version (the jinja maintainers aren't going to
# fix things) pin to the previous working version.
jinja2==3.0.3
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
# The short X.Y version
version = ''
# The full version, including alpha/beta/rc tags
release = '0.10.3'
release = '0.10.4'

# -- General configuration ---------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion qiskit/providers/aer/VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.10.3
0.10.4
29 changes: 29 additions & 0 deletions qiskit/providers/aer/backends/aerbackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,30 @@ def _run(self, qobj, job_id='', format_result=True):
# Start timer
start = time.time()

# Take metadata from headers of experiments to work around JSON serialization error
metadata_list = []
metadata_index = 0
for expr in qobj.experiments:
if hasattr(expr.header, "metadata"):
metadata_copy = expr.header.metadata.copy()
metadata_list.append(metadata_copy)
expr.header.metadata.clear()
if "id" in metadata_copy:
expr.header.metadata["id"] = metadata_copy["id"]
expr.header.metadata["metadata_index"] = metadata_index
metadata_index += 1

# Run simulation
output = self._execute(qobj)

# Recover metadata
metadata_index = 0
for expr in qobj.experiments:
if hasattr(expr.header, "metadata"):
expr.header.metadata.clear()
expr.header.metadata.update(metadata_list[metadata_index])
metadata_index += 1

# Validate output
if not isinstance(output, dict):
logger.error("%s: simulation failed.", self.name())
Expand All @@ -305,6 +326,14 @@ def _run(self, qobj, job_id='', format_result=True):
output["backend_name"] = self.name()
output["backend_version"] = self.configuration().backend_version

# Push metadata to experiment headers
for result in output["results"]:
if ("header" in result and
"metadata" in result["header"] and
"metadata_index" in result["header"]["metadata"]):
metadata_index = result["header"]["metadata"]["metadata_index"]
result["header"]["metadata"] = metadata_list[metadata_index]

# Add execution time
output["time_taken"] = time.time() - start

Expand Down
12 changes: 12 additions & 0 deletions qiskit/providers/aer/noise/device/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ def _device_thermal_relaxation_error(qubits,
error = None
for qubit in qubits:
t1, t2, freq = relax_params[qubit]
t2 = _truncate_t2_value(t1, t2)
population = _excited_population(freq, temperature)
if first:
error = thermal_relaxation_error(t1, t2, gate_time, population)
Expand All @@ -255,6 +256,17 @@ def _device_thermal_relaxation_error(qubits,
return error


def _truncate_t2_value(t1, t2):
"""Return t2 value truncated to 2 * t1 (for t2 > 2 * t1)"""
new_t2 = t2
if t2 > 2 * t1:
new_t2 = 2 * t1
warn("Device model returned an invalid T_2 relaxation time greater than"
f" the theoretical maximum value 2 * T_1 ({t2} > 2 * {t1})."
" Truncating to maximum value.", UserWarning)
return new_t2


def _excited_population(freq, temperature):
"""Return excited state population"""
population = 0
Expand Down
5 changes: 0 additions & 5 deletions qiskit/providers/aer/noise/device/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,6 @@ def thermal_relaxation_values(properties):
# Convert to Gigahertz
freq *= _GHZ_UNITS.get(freq_params.unit, 1)

# NOTE: T2 cannot be larger than 2 * T1 for a physical noise
# channel, however if a backend erroneously reports such a value we
# truncated it here:
t2 = min(2 * t1, t2)

values.append((t1, t2, freq))
return values

Expand Down
17 changes: 11 additions & 6 deletions qiskit/providers/aer/noise/noise_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@
from numpy import ndarray

from qiskit.circuit import Instruction, Delay
from qiskit.providers import BaseBackend, BackendV1, BackendV2
from qiskit.providers.exceptions import BackendPropertyError
from qiskit.providers.models import BackendProperties
from qiskit.transpiler import PassManager
from .device.models import _excited_population
from .device.models import _excited_population, _truncate_t2_value
from .device.models import basic_device_gate_errors
from .device.models import basic_device_readout_errors
from .errors.quantum_error import QuantumError
Expand Down Expand Up @@ -303,10 +302,14 @@ def from_backend(cls, backend,
Raises:
NoiseError: If the input backend is not valid.
"""
if isinstance(backend, BackendV2):
backend_interface_version = getattr(backend, "version", None)
if not isinstance(backend_interface_version, int):
backend_interface_version = 0

if backend_interface_version == 2:
raise NoiseError(
"NoiseModel.from_backend does not currently support V2 Backends.")
if isinstance(backend, (BaseBackend, BackendV1)):
if backend_interface_version <= 1:
properties = backend.properties()
configuration = backend.configuration()
basis_gates = configuration.basis_gates
Expand Down Expand Up @@ -373,9 +376,11 @@ def from_backend(cls, backend,
except BackendPropertyError:
excited_state_populations = None
try:
t1s = [properties.t1(q) for q in range(num_qubits)]
t2s = [properties.t2(q) for q in range(num_qubits)]
delay_pass = RelaxationNoisePass(
t1s=[properties.t1(q) for q in range(num_qubits)],
t2s=[properties.t2(q) for q in range(num_qubits)],
t1s=t1s,
t2s=[_truncate_t2_value(t1, t2) for t1, t2 in zip(t1s, t2s)],
dt=dt,
op_types=Delay,
excited_state_populations=excited_state_populations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

from warnings import warn
from collections import OrderedDict
from qiskit.providers import BaseBackend, Backend
from qiskit.providers import Backend
from ...aererror import AerError
from .hamiltonian_model import HamiltonianModel

Expand Down Expand Up @@ -94,7 +94,7 @@ def from_backend(cls, backend, subsystem_list=None):
AerError: If channel or u_channel_lo are invalid.
"""

if not isinstance(backend, (BaseBackend, Backend)):
if not isinstance(backend, Backend):
raise AerError("{} is not a Qiskit backend".format(backend))

# get relevant information from backend
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
fixes:
- |
Fix cache blocking transpiler to recognize superop to be cache blocked.
This is fix for
`issue 1479 <https://github.com/Qiskit/qiskit-aer/issues/1479>`
now density_matrix with noise models can be parallelized.
New test, test_noise.TestNoise.test_kraus_gate_noise_on_QFT_cache_blocking
is added to verify this issue.
Also this fix include fix for
`issue 1483 <https://github.com/Qiskit/qiskit-aer/issues/1483>`
discovered by adding new test case.
This fixes measure over chunks for statevector.
12 changes: 12 additions & 0 deletions releasenotes/notes/fix-invalid-t2-error-a3685e4a3ad0a1e7.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
fixes:
- |
Fixes a bug in ``NoiseModel.from_backend()`` that raised an error when
T2 value greater than 2 * T1 was supplied by the backend.
After this fix, it becomes to truncate T2 value up to 2 * T1 and
issue a user warning if truncates.
The bug was introduced at #1391 and, before that, ``NoiseModel.from_backend()`` had
truncated the T2 value up to 2 * T1 silently.

See `Issue 1464 <https://github.com/Qiskit/qiskit-aer/issues/1464>`__
for details.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
device=Thrust was very slow for small number of qubits because OpenMP
threading was always applied. This fix applies OpenMP threads as same
as device=CPU by using statevector_parallel_threshold.
18 changes: 18 additions & 0 deletions releasenotes/notes/no-fast-math-1de357a9650094f3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
upgrade:
- |
Qiskit Aer is no longer compiled with unsafe floating-point optimisations.
While most of the effects should have been localised to Qiskit Aer, some
aspects of subnormal handling may previously have been leaked into user code
by the library incorrectly setting the "flush to zero" mode. This will not
happen any more.
fixes:
- |
Qiskit Aer will no longer set the floating-point mode to "flush to zero"
when loaded. Downstream users may previously have seen warnings from Numpy
such as:

The value of the smallest subnormal for <class 'numpy.float64'> type is zero.

These will now no longer be emitted, and the floating-point handling will be
correct.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
fixes:
- |
Fixed a potential issue with running simulations on circuits that have the
:attr:`.QuantumCircuit.metadata` attribute set. The :attr:`~.QuantumCircuit.metadata`
attribute can be any python dictionary and previously qiskit-aer would attempt to
JSON serialize the contents of the attribute to process it with the rest of the rest
of the circuit input, even if the contents were not JSON serializable. This no longer
occurs as the :attr:`.QuantumCircuit.metadata` attribute is not used to run the
simulation so now the contents are no serialized and instead are directly attached
to the :class:`qiskit.result.Result` object without attempting to JSON serialize
the contents.
Fixed `#1435 <https://github.com/Qiskit/qiskit-aer/issues/1435>`__
12 changes: 8 additions & 4 deletions src/controllers/aer_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1930,10 +1930,14 @@ bool Controller::validate_state(const state_t &state, const Circuit &circ,
size_t required_mb = state.required_memory_mb(circ.num_qubits, circ.ops) / num_process_per_experiment_;
size_t mem_size = (sim_device_ == Device::GPU) ? max_memory_mb_ + max_gpu_memory_mb_ : max_memory_mb_;
memory_valid = (required_mb <= mem_size);
}
if (throw_except && !memory_valid) {
error_msg << "Insufficient memory to run circuit " << circ_name;
error_msg << " using the " << state.name() << " simulator.";
if (throw_except && !memory_valid) {
error_msg << "Insufficient memory to run circuit " << circ_name;
error_msg << " using the " << state.name() << " simulator.";
error_msg << " Required memory: " << required_mb << "M, max memory: " << max_memory_mb_ << "M";
if (sim_device_ == Device::GPU) {
error_msg << " (Host) + " << max_gpu_memory_mb_ << "M (GPU)";
}
}
}

if (noise_valid && circ_valid && memory_valid) {
Expand Down
4 changes: 0 additions & 4 deletions src/simulators/extended_stabilizer/ch_runner.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,11 +664,7 @@ void Runner::metropolis_step(AER::RngEngine &rng)
}
complex_t ampsum(real_part, imag_part);
double p_threshold = std::norm(ampsum)/std::norm(old_ampsum_);
#ifdef __FAST_MATH__ //isnan doesn't behave well under fastmath, so use absolute tolerance check instead
if(std::isinf(p_threshold) || std::abs(std::norm(old_ampsum_)-0.) < 1e-8)
#else
if(std::isinf(p_threshold) || std::isnan(p_threshold))
#endif
{
accept_ = true;
old_ampsum_ = ampsum;
Expand Down
26 changes: 23 additions & 3 deletions src/simulators/statevector/chunk/chunk_container.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,10 @@ class ChunkContainer : public std::enable_shared_from_this<ChunkContainer<data_t
uint_t num_cmemory_;
mutable int_t conditional_bit_;
bool keep_conditional_bit_; //keep conditional bit alive
int_t num_pow2_qubits_; //largest number of qubits that meets num_chunks_ = m*(2^num_pow2_qubits_)
bool density_matrix_;

int_t omp_threads_; //number of threads can be used for parallelization on CPU
public:
ChunkContainer()
{
Expand All @@ -498,6 +502,8 @@ class ChunkContainer : public std::enable_shared_from_this<ChunkContainer<data_t
conditional_bit_ = -1;
keep_conditional_bit_ = false;
matrix_bits_ = AER_DEFAULT_MATRIX_BITS;
density_matrix_ = false;
omp_threads_ = 1;
}
virtual ~ChunkContainer(){}

Expand Down Expand Up @@ -569,6 +575,11 @@ class ChunkContainer : public std::enable_shared_from_this<ChunkContainer<data_t
keep_conditional_bit_ = keep;
}

void set_omp_threads(int_t nthreads)
{
omp_threads_ = nthreads;
}

virtual thrust::complex<data_t>& operator[](uint_t i) = 0;

virtual uint_t Allocate(int idev,int chunk_bits,int num_qubits,uint_t chunks,uint_t buffers = AER_MAX_BUFFERS,bool multi_shots = false,int matrix_bit = AER_DEFAULT_MATRIX_BITS) = 0;
Expand Down Expand Up @@ -820,7 +831,10 @@ void ChunkContainer<data_t>::Execute(Function func,uint_t iChunk,uint_t count)
#else
uint_t size = count * func.size(chunk_bits_);
auto ci = thrust::counting_iterator<uint_t>(0);
thrust::for_each_n(thrust::device, ci , size, func);
if(omp_threads_ > 1)
thrust::for_each_n(thrust::device, ci , size, func);
else
thrust::for_each_n(thrust::seq, ci , size, func);
#endif

}
Expand Down Expand Up @@ -971,7 +985,10 @@ void ChunkContainer<data_t>::ExecuteSum(double* pSum,Function func,uint_t iChunk
auto ci = thrust::counting_iterator<uint_t>(0);

double sum;
sum = thrust::transform_reduce(thrust::device, ci, ci + size, func,0.0,thrust::plus<double>());
if(omp_threads_ > 1)
sum = thrust::transform_reduce(thrust::device, ci, ci + size, func,0.0,thrust::plus<double>());
else
sum = thrust::transform_reduce(thrust::seq, ci, ci + size, func,0.0,thrust::plus<double>());
if(count == 1 && pSum){
*pSum = sum;
}
Expand Down Expand Up @@ -1108,7 +1125,10 @@ void ChunkContainer<data_t>::ExecuteSum2(double* pSum,Function func,uint_t iChun

auto ci = thrust::counting_iterator<uint_t>(0);

ret = thrust::transform_reduce(thrust::device, ci, ci + size, func,zero,complex_sum());
if(omp_threads_ > 1)
ret = thrust::transform_reduce(thrust::device, ci, ci + size, func,zero,complex_sum());
else
ret = thrust::transform_reduce(thrust::seq, ci, ci + size, func,zero,complex_sum());

if(count == 1 && pSum){
*((thrust::complex<double>*)pSum) = ret;
Expand Down
Loading