跳转至

提交任务,再决定何时执行

通过一个单比特 X 线路,观察本地 Backend 和 Job 接口。请先完成第一个实验,在安装好的环境中从仓库根目录运行。

X 把 |0⟩ 变为 |1⟩。在理想演化下,16 次测量都应得到 1。这个预测没有采样分布上的歧义,便于专注观察计算何时发生。

观察本地任务的延迟执行

"""通过统一的 Backend 和 Job 接口提交本地程序。

``LocalBackend.run`` 返回 lazy Job,调用方可以先查看 status,再通过 result 触发
执行并读取终态。整个过程只使用本地后端,不包含云端或硬件 transport。
"""

from __future__ import annotations

import json

from cascaqit import Circuit, LocalBackend


def main() -> None:
    """观察一个完整的本地 Job 生命周期。"""
    circuit = Circuit(1, program_id="lesson.platform.beginner").x(0).measure_all()
    backend = LocalBackend(seed=401)

    # Job 创建和结果物化是两个不同步骤。
    job = backend.run(circuit, shots=16)
    queued = job.status()
    result = job.result()
    completed = job.status()
    cached = job.result()

    payload = {
        "track": "sdk_platform_engineer",
        "level": "beginner",
        "lesson": "backend_job",
        "facts": {
            "queued_state": queued.state,
            "completed_state": completed.state,
            "executions_before_result": queued.execution_count,
            "executions_after_result": completed.execution_count,
            "executions_after_cached_read": job.status().execution_count,
            "cached_result_matches": cached.stable_hash() == result.stable_hash(),
            "backend_id": completed.backend_id,
            "counts": result.counts,
            "counts_total": sum(result.counts.values()),
        },
        "boundaries": {
            "hardware_execution": False,
            "cloud_execution": False,
            "network_accessed": False,
            "credentials_loaded": False,
        },
    }
    print(json.dumps(payload, sort_keys=True))


if __name__ == "__main__":
    main()

下载完整脚本

python3 examples/user/tracks/sdk_platform_engineer/01_beginner_backend_job_zh.py

backend.run(...) 完成校验和准备,返回 Job 句柄。调用 job.result() 时才开始数值执行。job.status() 只读取当前状态,不会启动运行器。本地任务在获取结果的调用中同步执行,queued 不表示已经发送到远程工作节点。

{
  "boundaries": {
    "cloud_execution": false,
    "credentials_loaded": false,
    "hardware_execution": false,
    "network_accessed": false
  },
  "facts": {
    "backend_id": "local.simulator",
    "cached_result_matches": true,
    "completed_state": "completed",
    "counts": {
      "1": 16
    },
    "counts_total": 16,
    "executions_after_cached_read": 1,
    "executions_after_result": 1,
    "executions_before_result": 0,
    "queued_state": "queued"
  },
  "lesson": "backend_job",
  "level": "beginner",
  "track": "sdk_platform_engineer"
}

第一次状态快照是 queued,执行次数为零。获取结果时,任务经过 running 到达 completed,执行次数变为一。脚本只在同步调用前后读取状态,因此不会直接看到中间的 running。

第二次 result() 返回缓存结果。cached_result_matches 应为 true,执行次数仍为一。重复读取同一个句柄,与再次调用 backend.run(...) 不同;后者会创建另一个内存中的任务。本课没有启用持久化存储或幂等键。

任务状态与量子结果需要分别检查。即使任务完成,如果线路写错或解释方式不对,物理分布也可能不符合预期。本例需要同时满足两个条件:任务完成,且计数恰好是 16 个 1。

尝试取消任务和改变初态制备

  1. 在第一次 job.result() 前插入 job.cancel(),查看状态,再尝试获取结果。
  2. 在任务完成后调用 job.cancel(),它会撤销结果或改变终态吗?
  3. 把 X 改成 H。哪些生命周期信息不变,计数预测怎样变化?

取消排队中的任务后,状态为 cancelled,尚未执行;获取结果会报 LOCAL_EXECUTION_JOB_CANCELLED。完成后再取消,终态不变。H 对应的两个状态概率相等,但 16 次采样不一定各占一半;延迟执行和缓存读取的行为仍然相同。

任务生命周期列出了公共状态和转换关系。反复轮询状态不会触发这里的本地计算,需要执行时应调用 result()。下一课查看结果与诊断。

English version

SDK 1.0.8a · `6eff6362`