From 0cb6adc354cd1598a7571aae3cb05660486a1a47 Mon Sep 17 00:00:00 2001 From: Craig Gidney Date: Wed, 1 Feb 2023 11:04:07 -0800 Subject: [PATCH] Increase OS and future C++ version compatibility (#487) - Port over some changes needed for eventual C++20 compatibility - Enable compiler optimizations on Windows --- BUILD | 2 +- setup.py | 41 ++++++++++++------- src/stim/benchmark_main.perf.cc | 18 ++++---- .../diagram/timeline/timeline_ascii_drawer.cc | 4 +- src/stim/gen/circuit_gen_params.cc | 12 ++++-- src/stim/gen/circuit_gen_params.h | 2 +- src/stim/gen/gen_color_code.cc | 6 +-- src/stim/gen/gen_rep_code.cc | 6 +-- src/stim/gen/gen_surface_code.cc | 10 ++--- src/stim/mem/simd_bits.h | 2 + src/stim/mem/simd_bits.inl | 10 +++++ src/stim/mem/simd_bits_range_ref.h | 4 +- src/stim/mem/simd_bits_range_ref.inl | 4 +- src/stim/stabilizers/pauli_string.cc | 6 +++ src/stim/stabilizers/pauli_string.h | 2 + 15 files changed, 84 insertions(+), 45 deletions(-) diff --git a/BUILD b/BUILD index c2b02ce44..fe07940f3 100644 --- a/BUILD +++ b/BUILD @@ -93,7 +93,7 @@ cc_binary( "-fvisibility=hidden", "-march=native", "-DSTIM_PYBIND11_MODULE_NAME=stim", - "-DVERSION_INFO=0.0.dev" + "-DVERSION_INFO=0.0.dev", ], includes = ["src/"], linkopts = ["-lpthread"], diff --git a/setup.py b/setup.py index 0b0a79df2..14ad2847e 100644 --- a/setup.py +++ b/setup.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import sys from setuptools import setup, Extension import glob @@ -26,13 +27,27 @@ version = '1.11.dev0' -common_compile_args = [ - '-std=c++11', - '-fno-strict-aliasing', - '-O3', - '-g0', - f'-DVERSION_INFO={version}', -] +if sys.platform.startswith('win'): + common_compile_args = [ + '/std:c++11', + '/O2', + f'/DVERSION_INFO={version}', + ] + arch_avx = ['/arch:AVX2'] + arch_sse = ['/arch:SSE2'] + arch_basic = [] +else: + common_compile_args = [ + '-std=c++11', + '-fno-strict-aliasing', + '-O3', + '-g0', + f'-DVERSION_INFO={version}', + ] + arch_avx = ['-mavx2'] + arch_sse = ['-msse2', '-mno-avx2'] + arch_basic = [] + stim_detect_machine_architecture = Extension( 'stim._detect_machine_architecture', sources=MUX_SOURCE_FILES, @@ -40,8 +55,7 @@ language='c++', extra_compile_args=[ *common_compile_args, - '-mno-sse2', - '-mno-avx2', + *arch_basic, ], ) stim_polyfill = Extension( @@ -51,8 +65,7 @@ language='c++', extra_compile_args=[ *common_compile_args, - # I would specify -mno-sse2 but that causes build failures in non-stim code...? - '-mno-avx2', + *arch_basic, '-DSTIM_PYBIND11_MODULE_NAME=_stim_polyfill', ], ) @@ -63,8 +76,7 @@ language='c++', extra_compile_args=[ *common_compile_args, - '-msse2', - '-mno-avx2', + *arch_sse, '-DSTIM_PYBIND11_MODULE_NAME=_stim_sse2', ], ) @@ -77,8 +89,7 @@ # language='c++', # extra_compile_args=[ # *common_compile_args, -# '-msse2', -# '-mavx2', +# *arch_avx, # '-DSTIM_PYBIND11_MODULE_NAME=_stim_avx2', # ], # ) diff --git a/src/stim/benchmark_main.perf.cc b/src/stim/benchmark_main.perf.cc index 0c9661f0f..ee55968c8 100644 --- a/src/stim/benchmark_main.perf.cc +++ b/src/stim/benchmark_main.perf.cc @@ -25,40 +25,40 @@ std::vector all_registered_benchmarks{}; /// Describe quantity as an SI-prefixed value with two significant figures. std::string si2(double val) { - std::string unit = ""; + char unit = ' '; if (val < 1) { if (val < 1) { val *= 1000; - unit = "m"; + unit = 'm'; } if (val < 1) { val *= 1000; - unit = "u"; + unit = 'u'; } if (val < 1) { val *= 1000; - unit = "n"; + unit = 'n'; } if (val < 1) { val *= 1000; - unit = "p"; + unit = 'p'; } } else { if (val > 1000) { val /= 1000; - unit = "k"; + unit = 'k'; } if (val > 1000) { val /= 1000; - unit = "M"; + unit = 'M'; } if (val > 1000) { val /= 1000; - unit = "G"; + unit = 'G'; } if (val > 1000) { val /= 1000; - unit = "T"; + unit = 'T'; } } std::stringstream ss; diff --git a/src/stim/diagram/timeline/timeline_ascii_drawer.cc b/src/stim/diagram/timeline/timeline_ascii_drawer.cc index 207abfa60..b65f83f95 100644 --- a/src/stim/diagram/timeline/timeline_ascii_drawer.cc +++ b/src/stim/diagram/timeline/timeline_ascii_drawer.cc @@ -482,9 +482,11 @@ AsciiDiagram DiagramTimelineAsciiDrawer::make_diagram(const Circuit &circuit) { {0, obj.q2y(q), 1.0, 0.5}, {obj.m2x(obj.cur_moment), obj.q2y(q), 0.0, 0.5}, }; + std::stringstream qubit; + qubit << 'q' << q << ": "; obj.diagram.add_entry(AsciiDiagramEntry{ {0, obj.q2y(q), 1.0, 0.5}, - "q" + std::to_string(q) + ": ", + qubit.str(), }); } diff --git a/src/stim/gen/circuit_gen_params.cc b/src/stim/gen/circuit_gen_params.cc index 7dc2e559f..12b2ddf29 100644 --- a/src/stim/gen/circuit_gen_params.cc +++ b/src/stim/gen/circuit_gen_params.cc @@ -57,19 +57,25 @@ void CircuitGenParameters::append_unitary_2( } void CircuitGenParameters::append_reset(Circuit &circuit, const std::vector targets, char basis) const { - circuit.safe_append_u(std::string("R") + basis, targets); + std::string gate("R"); + gate.push_back(basis); + circuit.safe_append_u(gate, targets); append_anti_basis_error(circuit, targets, after_reset_flip_probability, basis); } void CircuitGenParameters::append_measure(Circuit &circuit, const std::vector targets, char basis) const { + std::string gate("M"); + gate.push_back(basis); append_anti_basis_error(circuit, targets, before_measure_flip_probability, basis); - circuit.safe_append_u(std::string("M") + basis, targets); + circuit.safe_append_u(gate, targets); } void CircuitGenParameters::append_measure_reset( Circuit &circuit, const std::vector targets, char basis) const { + std::string gate("MR"); + gate.push_back(basis); append_anti_basis_error(circuit, targets, before_measure_flip_probability, basis); - circuit.safe_append_u(std::string("MR") + basis, targets); + circuit.safe_append_u(gate, targets); append_anti_basis_error(circuit, targets, after_reset_flip_probability, basis); } diff --git a/src/stim/gen/circuit_gen_params.h b/src/stim/gen/circuit_gen_params.h index b223058f1..3920d2396 100644 --- a/src/stim/gen/circuit_gen_params.h +++ b/src/stim/gen/circuit_gen_params.h @@ -30,7 +30,7 @@ struct CircuitGenParameters { struct GeneratedCircuit { Circuit circuit; - std::map, std::pair> layout; + std::map, std::pair> layout; std::string hint_str; std::string layout_str() const; }; diff --git a/src/stim/gen/gen_color_code.cc b/src/stim/gen/gen_color_code.cc index 5f0f000f4..56cc4733c 100644 --- a/src/stim/gen/gen_color_code.cc +++ b/src/stim/gen/gen_color_code.cc @@ -191,11 +191,11 @@ GeneratedCircuit stim::generate_color_code_circuit(const CircuitGenParameters &p auto full_circuit = head + body * (params.rounds - 2) + tail; // Make 2d layout. - std::map, std::pair> layout; + std::map, std::pair> layout; for (auto q : data_coords) { - layout[{(uint32_t)(q.x * 2), (uint32_t)q.y}] = {q.y == 0 ? "L" : "d", p2q[q]}; + layout[{(uint32_t)(q.x * 2), (uint32_t)q.y}] = {q.y == 0 ? 'L' : 'd', p2q[q]}; } - std::array rgb{"R", "G", "B"}; + std::array rgb{'R', 'G', 'B'}; for (auto q : measure_coords) { auto x = (uint32_t)(q.x * 2); auto y = (uint32_t)q.y; diff --git a/src/stim/gen/gen_rep_code.cc b/src/stim/gen/gen_rep_code.cc index 1bb6a79f1..f66152df6 100644 --- a/src/stim/gen/gen_rep_code.cc +++ b/src/stim/gen/gen_rep_code.cc @@ -81,11 +81,11 @@ GeneratedCircuit stim::generate_rep_code_circuit(const CircuitGenParameters &par Circuit full_circuit = head + body * (params.rounds - 1) + tail; // Produce a 2d layout. - std::map, std::pair> layout; + std::map, std::pair> layout; for (uint32_t k = 0; k < n; k++) { - layout[{k, 0}] = {std::string() + "dZ"[k & 1], k}; + layout[{k, 0}] = {"dZ"[k & 1], k}; } - layout[{0, 0}].first = "L"; + layout[{0, 0}].first = 'L'; return { full_circuit, diff --git a/src/stim/gen/gen_surface_code.cc b/src/stim/gen/gen_surface_code.cc index 9ada5a3b5..4ff30577a 100644 --- a/src/stim/gen/gen_surface_code.cc +++ b/src/stim/gen/gen_surface_code.cc @@ -191,19 +191,19 @@ GeneratedCircuit _finish_surface_code_circuit( Circuit full_circuit = head + body * (params.rounds - 1) + tail; // Produce a 2d layout. - std::map, std::pair> layout; + std::map, std::pair> layout; float scale = x_order[0].x == 0.5 ? 2 : 1; for (auto q : data_coords) { - layout[{(uint32_t)(q.x * scale), (uint32_t)(q.y * scale)}] = {"d", p2q[q]}; + layout[{(uint32_t)(q.x * scale), (uint32_t)(q.y * scale)}] = {'d', p2q[q]}; } for (auto q : x_measure_coords) { - layout[{(uint32_t)(q.x * scale), (uint32_t)(q.y * scale)}] = {"X", p2q[q]}; + layout[{(uint32_t)(q.x * scale), (uint32_t)(q.y * scale)}] = {'X', p2q[q]}; } for (auto q : z_measure_coords) { - layout[{(uint32_t)(q.x * scale), (uint32_t)(q.y * scale)}] = {"Z", p2q[q]}; + layout[{(uint32_t)(q.x * scale), (uint32_t)(q.y * scale)}] = {'Z', p2q[q]}; } for (auto q : chosen_basis_observable) { - layout[{(uint32_t)(q.x * scale), (uint32_t)(q.y * scale)}].first = "L"; + layout[{(uint32_t)(q.x * scale), (uint32_t)(q.y * scale)}].first = 'L'; } return { diff --git a/src/stim/mem/simd_bits.h b/src/stim/mem/simd_bits.h index 1e00e2589..7b2f91bb5 100644 --- a/src/stim/mem/simd_bits.h +++ b/src/stim/mem/simd_bits.h @@ -71,8 +71,10 @@ struct simd_bits { // Equality. bool operator==(const simd_bits_range_ref &other) const; + bool operator==(const simd_bits &other) const; // Inequality. bool operator!=(const simd_bits_range_ref &other) const; + bool operator!=(const simd_bits &other) const; /// Determines whether or not any of the bits in the simd_bits are non-zero. bool not_zero() const; diff --git a/src/stim/mem/simd_bits.inl b/src/stim/mem/simd_bits.inl index af3fa1d27..fcfb3f71c 100644 --- a/src/stim/mem/simd_bits.inl +++ b/src/stim/mem/simd_bits.inl @@ -102,11 +102,21 @@ bool simd_bits::operator==(const simd_bits_range_ref &other) const { return simd_bits_range_ref(*this) == other; } +template +bool simd_bits::operator==(const simd_bits &other) const { + return simd_bits_range_ref(*this) == simd_bits_range_ref(other); +} + template bool simd_bits::operator!=(const simd_bits_range_ref &other) const { return !(*this == other); } +template +bool simd_bits::operator!=(const simd_bits &other) const { + return !(*this == other); +} + template simd_bits simd_bits::random(size_t min_bits, std::mt19937_64 &rng) { simd_bits result(min_bits); diff --git a/src/stim/mem/simd_bits_range_ref.h b/src/stim/mem/simd_bits_range_ref.h index a24d7271e..721b086b9 100644 --- a/src/stim/mem/simd_bits_range_ref.h +++ b/src/stim/mem/simd_bits_range_ref.h @@ -70,9 +70,9 @@ struct simd_bits_range_ref { void swap_with(simd_bits_range_ref other); /// Equality. - bool operator==(const simd_bits_range_ref other) const; + bool operator==(const simd_bits_range_ref &other) const; /// Inequality. - bool operator!=(const simd_bits_range_ref other) const; + bool operator!=(const simd_bits_range_ref &other) const; /// Determines whether or not any of the bits in the referenced range are non-zero. bool not_zero() const; diff --git a/src/stim/mem/simd_bits_range_ref.inl b/src/stim/mem/simd_bits_range_ref.inl index 4eb9b0d4e..d795dbbf2 100644 --- a/src/stim/mem/simd_bits_range_ref.inl +++ b/src/stim/mem/simd_bits_range_ref.inl @@ -75,7 +75,7 @@ void simd_bits_range_ref::clear() { } template -bool simd_bits_range_ref::operator==(const simd_bits_range_ref other) const { +bool simd_bits_range_ref::operator==(const simd_bits_range_ref &other) const { return num_simd_words == other.num_simd_words && memcmp(ptr_simd, other.ptr_simd, num_u8_padded()) == 0; } @@ -89,7 +89,7 @@ bool simd_bits_range_ref::not_zero() const { } template -bool simd_bits_range_ref::operator!=(const simd_bits_range_ref other) const { +bool simd_bits_range_ref::operator!=(const simd_bits_range_ref &other) const { return !(*this == other); } diff --git a/src/stim/stabilizers/pauli_string.cc b/src/stim/stabilizers/pauli_string.cc index 6b1ddcd88..9685ccbd4 100644 --- a/src/stim/stabilizers/pauli_string.cc +++ b/src/stim/stabilizers/pauli_string.cc @@ -115,10 +115,16 @@ PauliString PauliString::random(size_t num_qubits, std::mt19937_64 &rng) { bool PauliString::operator==(const PauliStringRef &other) const { return ref() == other; } +bool PauliString::operator==(const PauliString &other) const { + return ref() == other.ref(); +} bool PauliString::operator!=(const PauliStringRef &other) const { return ref() != other; } +bool PauliString::operator!=(const PauliString &other) const { + return ref() != other.ref(); +} void PauliString::ensure_num_qubits(size_t min_num_qubits, double resize_pad_factor) { assert(resize_pad_factor >= 1); diff --git a/src/stim/stabilizers/pauli_string.h b/src/stim/stabilizers/pauli_string.h index 3b5d5b197..fea16c13e 100644 --- a/src/stim/stabilizers/pauli_string.h +++ b/src/stim/stabilizers/pauli_string.h @@ -91,8 +91,10 @@ struct PauliString { /// Equality. bool operator==(const PauliStringRef &other) const; + bool operator==(const PauliString &other) const; /// Inequality. bool operator!=(const PauliStringRef &other) const; + bool operator!=(const PauliString &other) const; /// Implicit conversion to a reference. operator PauliStringRef();