ARTIQのRTIO、量子実験のパルスを予定時刻にそろえる仕組み

不規則に並ぶ小片から淡青の通路へつながり、決まった間隔で二つの面が立ち上がる抽象アート。命令の準備と予定された実行を表す。

量子実験では、レーザーやマイクロ波を「どの順番で動かすか」だけでなく、「いつ動かすか」も重要になります。ところが、制御プログラムが計算や通信に使う時間は、毎回まったく同じとは限りません。命令を書いた順番だけで、必要なパルスの間隔までそろえられるのでしょうか。

実験制御システムARTIQは、CPUが命令を準備する時刻と、装置がその命令を実行する予定時刻を分けて扱います。その中心にあるのがRTIO(Real-Time Input/Output)です。Open Quantum Designのハードウェア資料も、リアルタイム制御の構成要素としてARTIQを案内しています。ここでは、予定を先に渡す仕組みと、その予定が間に合わなくなる条件を見ていきます。

簡単にまとめると?

  • RTIOでは、CPUが時刻付きの出力命令を準備し、ハードウェアが指定された時刻に実行します。プログラムの処理時間とパルスの幅を切り離せます。
  • 予定時刻とハードウェアの現在時刻の差が、slack(余裕時間)です。過去の時刻への出力は間に合わず、RTIOUnderflowになります。
  • 予定を未来へずらす、実時刻の到来を待つ、装置を初期化する、という操作は別物です。実験の時刻関係を保ちたいのか、処理の遅れを吸収したいのかで使い分けます。

「今」が二つある理由

ARTIQの実験は、ホスト側のコンピューターと、時間を厳密に扱うコア装置に役割を分けられます。コア装置のCPU上で動くプログラムをkernelと呼びます。CPUが出力イベントを時刻付きでバッファーへ送り、FPGAに実装された回路が、その時刻になったときに出力します。FIFOは、このようなイベントを一時的に蓄える待ち行列です。

ここで区別したいのは、プログラムが予定を置くタイムラインのカーソルと、装置内で進み続けるハードウェアの時計です。now_mu()が返すのは前者であり、CPUが呼び出した瞬間の実時刻ではありません。一方、get_rtio_counter_mu()はハードウェアのカウンターを読みます。ただし、読み取り結果がプログラムへ戻るまでにも時間が進むため、返された値は、その後の実時刻の下限として扱う必要があります。

muはmachine unit、つまり装置の時間単位です。何秒に相当するかは構成に依存します。以下では、特定の装置の性能を仮定せず、時刻も間隔もmuで表します。

3,000 muのパルスを、先に予約する

TTL出力は、デジタル信号をオンまたはオフにする基本的な出力です。説明用に、タイムラインのカーソルを12,000 muに置き、オン、3,000 mu進める、オフ、の順で処理するとします。delay_mu(3000)は予定を3,000 mu先へ動かす操作です。CPUを3,000 muの間その場で待たせる、という意味ではありません。実際のTTLドライバーのpulse_mu()も、このオン・カーソル移動・オフの構成になっています。

次の数値は仕組みを説明するために置いた架空の値であり、実機で測った処理時間ではありません。イベントの受け渡しが完了した時点など、比較する瞬間をそろえて余裕時間を計算します。

見る瞬間 ハードウェア時刻 カーソル 差=余裕時間
オンの予定を受け渡した時点 4,000 mu 12,000 mu 8,000 mu
カーソルを3,000 mu進めた時点 4,700 mu 15,000 mu 10,300 mu
オフの予定を受け渡した時点 5,200 mu 15,000 mu 9,800 mu

受け渡しが間に合い、ほかの出力条件も満たされれば、オンは12,000 mu、オフは15,000 muで実行されます。両者の差は3,000 muです。CPUがオンとオフの予定を送り出した時刻の差、5,200−4,000=1,200 muが、そのままパルス幅になるわけではありません。

CPUは4,000 muと5,200 muで予定を渡し、RTIOは12,000 muにオン、15,000 muにオフを実行する説明図。パルス幅は3,000 muで、提出時刻の間隔1,200 muとは異なる。
図1:独自に置いた数値による模式図。CPUの受け渡しと出力の実行を、同じ時刻軸の別の段に描いています。実機測定や原資料の図の転載ではありません。

この分離が、計算や通信の揺れを出力タイミングへ直接持ち込まないための土台です。ただし、「CPUの速度は関係ない」という意味ではありません。CPUには、必要なイベントを締切までに準備する役目が残ります。

余裕時間は、命令を準備するための持ち時間

slackは、カーソルからハードウェアの現在時刻を引いた差です。カーソルを先へ進めれば増え、カーソルを動かさず計算などに時間を使えば減ります。たとえば、オフの予定時刻を15,000 muにしたまま、送ろうとした時点で時計が15,500 muまで進んでいたら、差は−500 muです。すでに過去の予定となり、RTIOUnderflowが起きます。間に合わなかったイベントは破棄されます。

プログラム上でイベントを順番に書けていても、実時間の締切に遅れることはあります。また、先にオンだけが受理され、オフが間に合わなければ、意図した幅のパルスは完成しません。例外を受け取ったことと、出力が望む状態へ戻ったことは別に確認する必要があります。

入力を待つ処理も、この持ち時間を使います。たとえば検出窓を設けて入力イベントを数える場合、結果の取得は、窓が終わるまで待つことがあります。その間にもハードウェアの時計は進みます。取得した値で分岐してすぐ次の出力を決める実験では、入力待ち、計算、次のイベントの受け渡しに必要な時間を、ひとまとまりで考える必要があります。

逆に、予定を大量に先送りすれば無制限に安心、というわけでもありません。出力FIFOの容量は有限で、満杯になるとCPU側の受け渡しが待たされます。この待ち時間も余裕を消費します。これは、入力側のイベントがあふれるRTIOOverflowとは区別されます。

未来へずらす操作と、実時刻を待つ操作

ARTIQには、遅れを吸収するためのbreak_realtime()があります。今回固定した版では、読み取った時計の値に125,000 muを足した位置と、現在のカーソルを比べ、カーソルが手前なら前者へ進めます。すでに十分先なら動かしません。

たとえば、読み取った時計が200,000 mu、カーソルが150,000 muなら、新しいカーソルは325,000 muになります。一方、カーソルが400,000 muならそのままです。125,000 muはこの実装に書かれた余裕であり、すべての装置で125マイクロ秒になるという意味ではありません。その後の処理が長ければ、この余裕も使い切ります。

使う前に判断したいのは、「後続の出力を遅らせてもよいか」です。計測のまとまりの間で余裕を取り直すなら役立ちますが、外部トリガーから厳密に一定時間後に出力したい場合、途中で予定をずらすと、その約束を変えてしまいます。遅れを解消する操作が、元の時刻関係まで守ってくれるわけではありません。

操作 何をするか 気を付けたい点
break_realtime() 必要ならカーソルを未来へ進める 後続の予定がずれる。FIFOを消去する操作ではない
wait_until_mu(t) ハードウェアの時計がtに達するまで待つ 未来の余裕を作る操作ではない。すでにtを過ぎていればすぐ戻る
reset() RTIOのFIFOを消去し、リセットを解除してカーソルを未来へ置く まだ実行されていない予約イベントも失われる。単なる待機の代わりには使えない

kernelが終了した時点でも、FIFOに未来の出力が残っていることがあります。最後に予約した出力の時刻まで待ちたいなら、その時刻をwait_until_mu()へ渡す、という使い方になります。ただし、タイムラインを途中で戻した場合など、現在のカーソルが必ず最後のイベント時刻を表すとは限りません。また、装置内の時計が到達したことは、外につないだレーザーなどの応答や量子操作の精度を測定したことではありません。

「余裕が正なら成功」とは限らない

正の余裕時間は、未来へ命令を渡すための基本条件です。しかし、時計を読み取ってから送信するまでの時間もあり、小さな正の値を見ただけで締切を保証することはできません。さらに、RTIOにはイベントの並び順、同じ出力への衝突、装置が次の命令を受け付けられる間隔などの条件があります。

これらの違反は、CPUに返るunderflow例外と同じ形で現れるとは限りません。sequence errorやcollision、busy errorでは、不適切なイベントが捨てられ、コア装置のログに記録される場合があります。実験を比べるときは、プログラムが最後まで走ったかだけでなく、予定したイベント、装置側のエラー、観測した出力を突き合わせる必要があります。

RTIOの役割は、準備を間に合わせた時刻付きイベントを、装置の時計に沿って実行することです。本稿で確認したのは公開資料と固定版コード上の仕組みであり、特定の量子装置を動かした測定結果ではありません。装置ごとの時間単位、イベント密度、外部機器の応答を確認して初めて、必要なタイミングを実験全体で満たせるか判断できます。

出典

2026年10月18日に参照したARTIQ文書の表示版は9.9698+a7303a7です。下記のコードと文書原本は、コミット日時が2026年10月7日(UTC+8)の固定版で照合しました。公開コードは実行せず、仕組みの読解に使用しています。

  1. Open Quantum Design — Hardware / Devices:ARTIQにつながるリアルタイム制御の構成。2026年10月18日参照。
  2. ARTIQ — Real-Time I/O concepts:カーソル、slack、入出力イベント、エラー。同文書の固定版原本。
  3. ARTIQ coredevice/core.py(固定版):カウンター読取り、待機、reset、break_realtime。
  4. ARTIQ language/core.py(固定版):delay_mu、now_mu、at_mu。
  5. ARTIQ coredevice/ttl.py(固定版):TTLのオン・オフとpulse_mu。