Skip to content

精度与能力 -- 精度选择、模拟器注册表、SIMD 诊断 ​

pyqpanda3.core 的每个 CPU 系列模拟器都在构造时接受算术 precision("float32" 或 "float64"),报告其支持的精度,并在有意义的地方以原生 dtype 返回状态。两个新的查询面与这些旋钮互补:simulator_capabilities() 注册表无需构造任何对象即可回答"这里能运行什么";pyqpanda3.core.simd 子模块暴露运行时 SIMD 分派决定。本页所有接口均为 pyqpanda3 0.5.0 新增。

导入 ​

python
from pyqpanda3.core import (
    CPUQVM,
    DensityMatrixSimulator,
    InvalidPrecisionError,
    MPSQVM,
    PrecisionConversionError,
    UnsupportedPrecisionError,
    simulator_capabilities,
)
from pyqpanda3.core import simd

精度选择 ​

构造关键字 ​

precision 是 CPUQVM、DensityMatrixSimulator、MPSQVM、PartialAmplitudeQVM、SingleAmplitudeQVM、SparseHeisenbergSimulator 与 GPUQVM 的构造关键字。它在每个实例上不可变,各处默认为 "float64"。

python
import numpy as np
from pyqpanda3.core import CPUQVM

seed = np.array([0.5, 0.5, 0.5, 0.5], dtype=np.complex64)

qvm32 = CPUQVM(precision="float32")
qvm32.init_state(seed)
print(qvm32.current_state().dtype, qvm32.current_state().shape, qvm32.precision,
      tuple(qvm32.supported_precisions))

qvm64 = CPUQVM()
qvm64.init_state(seed)
print(qvm64.current_state().dtype, qvm64.current_state().shape, qvm64.precision)

运行结果:

text
complex64 (4,) float32 ('float32', 'float64')
complex128 (4,) float64
属性类型说明
precisionstr该实例构造时的算术精度。只读。
supported_precisionstuple[str, ...]该模拟器类支持的精度。只读。

Stabilizer 报告 precision == "exact" 且 supported_precisions == ("exact",);它以 UnsupportedPrecisionError 拒绝算术精度。

CPUQVM.current_state / MPSQVM.current_state ​

python
CPUQVM.current_state() -> numpy.ndarray
MPSQVM.current_state() -> numpy.ndarray

以模拟器原生精度的 NumPy 数组返回状态("float32" 对应 complex64,"float64" 对应 complex128)。与 result().get_state_vector() 不同,不发生任何 dtype 转换。

两者返回的状态不同,这一区别至关重要:

模拟器current_state() 返回什么
CPUQVM最近一次 init_state(...) 装入的状态。run() 不会填充它——在任何 init_state(...) 调用之前,它是 dtype 正确但内容为空的数组。要读取 run() 产生的状态,请用 result().get_state_vector()。
MPSQVM最近一次 run() 产生的实时状态。
python
import numpy as np
from pyqpanda3.core import CPUQVM, MPSQVM, CNOT, H, QProg, measure

# CPUQVM:current_state() 镜像 init_state(),run() 不会改变它。
cpu = CPUQVM(precision="float32")
cpu.run(QProg() << H(0) << CNOT(0, 1) << measure([0, 1], [0, 1]), 100)
print("before init_state:", len(cpu.current_state()))
cpu.init_state(np.array([0.5, 0.5, 0.5, 0.5], dtype=np.complex64))
print("after init_state:", cpu.current_state().dtype, cpu.current_state().shape)
print("after run (result path):", len(cpu.result().get_state_vector()))

# MPSQVM:current_state() 就是 run() 之后的状态。
mps = MPSQVM(precision="float32")
mps.run(QProg() << H(0) << CNOT(0, 1), 2)
print("mps:", mps.current_state().dtype, mps.current_state().shape)

运行结果:

text
before init_state: 0
after init_state: complex64 (4,)
after run (result path): 4
mps: complex64 (4,)

DensityMatrixSimulator.density_matrix_native ​

python
DensityMatrixSimulator.density_matrix_native() -> numpy.ndarray

以模拟器原生 dtype 的 NumPy 数组返回密度矩阵。需要恒为 complex128 的视图时使用 density_matrix();需要原生 dtype 向下游流动时使用本方法。

MPS 截断选项与运行统计 ​

python
MPSQVM(precision: str = "float64", truncation_atol: float | None = None, max_bond_dimension: int | None = None)
参数类型说明
precisionstr"float32" 或 "float64"。默认 "float64"。
truncation_atolfloat 或 None每次 SVD 后低于该权重的奇异值被丢弃。默认依精度而定:float32 为 1e-6,float64 为 1e-12。
max_bond_dimensionint 或 None截断后保留键维的硬上限。None 表示仅按容差驱动截断。
python
MPSQVM.stats() -> MPSRunStats

MPSRunStats 是只读记录,含 discarded_weight(截断至今丢弃的总概率权重)与 max_bond_dimension_seen(至今物化过的最大键维)。

python
import numpy as np
from pyqpanda3.core import MPSQVM, QProg, RY, CZ

rng = np.random.default_rng(7)
prog = QProg()
for q in range(6):
    prog << RY(q, rng.uniform(0, np.pi))
for layer in range(4):
    pairs = [(0, 1), (2, 3), (4, 5)] if layer % 2 == 0 else [(1, 2), (3, 4)]
    for a, b in pairs:
        prog << CZ(a, b) << RY(a, rng.uniform(0, np.pi)) << RY(b, rng.uniform(0, np.pi))

capped = MPSQVM(precision="float64", max_bond_dimension=2)
capped.run(prog, 1)
print(capped.stats().discarded_weight, capped.stats().max_bond_dimension_seen)

exact = MPSQVM()
exact.run(prog, 1)
print(exact.stats().discarded_weight, exact.stats().max_bond_dimension_seen)

运行结果:

text
0.024353811677256556 2
1.8613363972962274e-34 4

SingleAmplitudeQVM.stats ​

python
SingleAmplitudeQVM.stats() -> SingleAmplitudeStats

SingleAmplitudeStats 是只读记录,含 cache_hit_count、cache_miss_count 与 peak_workspace_bytes,描述最近一次运行的振幅求值工作区行为。

精度异常 ​

非法精度请求会以专属异常类型尽早抛出,均为 ValueError 的子类:

异常抛出时机
InvalidPrecisionError精度字符串不是任何后端可识别的精度名。
UnsupportedPrecisionError精度名合法但该后端不支持。
PrecisionConversionError用户请求的精度转换无法执行。
python
from pyqpanda3.core import CPUQVM, Stabilizer

try:
    CPUQVM(precision="float16")
except ValueError as e:
    print(type(e).__name__, "-", e)

try:
    Stabilizer(precision="float32")
except ValueError as e:
    print(type(e).__name__, "-", e)

运行结果:

text
InvalidPrecisionError - unknown precision 'float16'
UnsupportedPrecisionError - backend 'Stabilizer' does not support precision 'float32'; supported precisions are: exact

BackendUnavailableError(RuntimeError 子类)在构造未注册或构建缺失的模拟器时抛出。注意:无 CUDA 构建中 GPUQVM 不会被注册,pyqpanda3.core.GPUQVM 为 None(导入时发出 ImportWarning),无法构造;能力注册表(下文)以 available=False 报告同一情况。用 simulator_capabilities("GPUQVM").available 判断。

模拟器能力注册表 ​

python
simulator_capabilities(name: str | None = None) -> SimulatorCapabilities | list[SimulatorCapabilities]
参数类型说明
namestr 或 None模拟器类名(例如 "MPSQVM")。省略时返回全部已注册模拟器的记录。

SimulatorCapabilities 是只读记录:

字段类型说明
namestr模拟器类名。
supported_precisionstuple[str, ...]该类支持的精度。
default_precisionstr未指定 precision 时使用的精度。
availablebool该模拟器在当前主机上能否构造(构建存在、硬件存在)。
simd_domainstr模拟器所处的计算域:StateVector、Density、Tensor、Amplitude、Sparse 或 NotApplicable。
python
from pyqpanda3.core import simulator_capabilities

for cap in simulator_capabilities():
    print(f"{cap.name:26s} {','.join(cap.supported_precisions):16s}"
          f" default={cap.default_precision:8s} available={str(cap.available):5s}"
          f" domain={cap.simd_domain}")

运行结果:

text
CPUQVM                     float32,float64  default=float64  available=True  domain=StateVector
DensityMatrixSimulator     float32,float64  default=float64  available=True  domain=Density
GPUQVM                     float64          default=float64  available=False domain=NotApplicable
MPSQVM                     float32,float64  default=float64  available=True  domain=Tensor
PartialAmplitudeQVM        float32,float64  default=float64  available=True  domain=Amplitude
SingleAmplitudeQVM         float32,float64  default=float64  available=True  domain=Amplitude
SparseHeisenbergSimulator  float32,float64  default=float64  available=True  domain=Sparse
Stabilizer                 exact            default=exact    available=True  domain=NotApplicable

SIMD 诊断与偏好 ​

pyqpanda3.core.simd 子模块报告运行时 SIMD 分派,并允许覆盖它。

simd.capabilities ​

python
simd.capabilities() -> SIMDCapabilities

SIMDCapabilities 是不可变快照,包含:

字段类型说明
architecturestr主机架构,例如 x86_64。
compiled_backendslist[str]编译进本构建的后端:x86_64 为 scalar、sse2、avx2、avx512;ARM64 为 scalar、neon、sve、sve2。
available_backendslist[str]主机 CPU 实际可执行的已编译后端。
default_backendstr探测器自动选择的后端。
active_backendstr当前生效的后端(默认或用户偏好)。
fallback_reasonstr请求的后端未被采纳的原因;无则为空。

simd.active_backend ​

python
simd.active_backend() -> str

返回当前生效的后端。

simd.set_preference ​

python
simd.set_preference(backend: str, strict: bool = False) -> None
参数类型说明
backendstr"auto"、"scalar"、"sse2"、"avx2"、"avx512"、"neon"、"sve"、"sve2" 之一(以编译/可用为准)。
strictbool为 True 时,对不可用后端抛出 UnsupportedSIMDBackendError(RuntimeError 子类)而非记录回退。默认 False。
python
from pyqpanda3.core import simd

cap = simd.capabilities()
print(cap.architecture, list(cap.available_backends), cap.active_backend)

simd.set_preference("scalar")
print(simd.active_backend())
simd.set_preference("auto")
print(simd.active_backend())

运行结果(在支持 AVX2 的 x86_64 主机上):

text
x86_64 ['scalar', 'sse2', 'avx2', 'avx512'] avx2
scalar
avx2

该偏好作用于调用之后构造的模拟器。自动提升策略刻意保守:只有当某后端的正确性行全部通过且在发布基准套件上实测运行时间优于下一个安全后端时,它才会成为自动选择(该套件上 AVX2 相对标量的中位加速为 2.13x)。

另见 ​

Released under the MIT License.