ここでは、DAQシステムを動かす上で最低限理解しておきたい NestDAQ の概要を説明する。詳しい情報はこのページのリンクの項目、もしくは本マニュアルのリンク集を参照のこと。
NestDAQ は連続読み出し FEE のために開発された DAQ ソフトウェアフレームワークである。高いスケーラビリティを持つことを目標に設計されており、データ処理のプロセスをネットワーク上のコンピュータに分散可能な、いわゆるネットワーク分散型の DAQ ソフトウェアである。小規模実験から中規模実験の加速器物理実験における連続読み出し型 DAQ システムを念頭に設計されているが、汎用のフレームワークであるため、連続読み出しを行いたい計測機器やトリガー型 DAQ にも対応可能であると考えられる。
NestDAQ は GSI FAIR で開発されている DAQ フレームワーク FairMQ をベースにしている。DAQ プロセス間の接続トポロジーの管理には、in-memory key-value データベースである Redis を用いる。さらに、NestDAQ では DAQ のスタータス情報、メトリックス情報といった情報を取得するための各種プラグインが用意されている。非常に単純化するならば、"NestDAQ = FairMQ + Redis + 各種プラグイン"と言うことができる。ここで、FairMQ は ZeroMQ と呼ばれるライブラリを用いて作られており、FAIR + ZeroMQ = FairMQ ということでこの名前になったと予想される。
NestDAQ はネットワーク分散型の DAQ であり、1 つまたは複数のコンピュータにおいて DAQ プログラムのプロセスを走らせ、Redis データベース経由で各プロセスの制御を行う。 NestDAQ では、各プロセスのことを FairMQ デバイスと呼ぶ。また、Redisデータベースでは DAQ の状態 (Runが走っているか、または止まっているかなどの状態) の情報も保持している。この情報をもとに NestDAQ は DAQ の状態管理を行っている。各 FairMQ デバイスは Redis と通信を行っており (?)、Redis に対してコマンドが発行されると、そのコマンドは各 FairMQ デバイスに転送される。例えば Run をスタートさせる場合、Redis に対して Run スタートのコマンドを発行 (Publish) すると、Redis が各プロセスに Run スタートの情報を伝達し、すべての DAQ プロセスが Run 状態に遷移して、データ収集が開始する。ランストップといった他のコントロールも同様にして行われる。通常、DAQ のコントロールは、Web ブラウザ上の DAQ コントローラと呼ばれるユーザーインターフェースから行う。Web コントローラでは、グラフィカルにスタートボタンやストップボタンといったボタンをクリックすることで、簡単に DAQ のコントロールが可能となっている。ただ、必ずしもこのコントローラを使用する必要はなく、Linux のコマンドライン上から redis-cli というコマンドを用いて直接 Publish コマンドを Redis に対して発行することで DAQ のコントロールが可能である。つまり、最低限 FairMQ デバイスと Redis データベースが立ち上がっていればデータ収集が可能であり、言い換えると DAQ ソフトウェアの最小構成は FairMQ デバイスと Redis データベースであると言える。場合によっては Web コントローラを用いず、DAQ の ランスタート、ランストップのシェルスクリプトを用いて DAQ の制御を行うこともある。FairMQ デバイスと Redis、もしくは Redis と Web コントローラはそれぞれ弱く結合するように設計されており、これによってシステムの堅牢性を確保している。(一般に、強く結合したシステムは一箇所に不具合が起きただけで全体に影響がおよぶため、堅牢性が低下し、脆弱なシステムとなる。)
各 FairMQ デバイスはデータを前段の FairMQ デバイス (Sampler の場合は FEE) からデータを受け取り、なんらかの処理を行なって後段のFiarMQ デバイス (Sink の場合はストレージ) に送る。ここで、どのデバイスがどのデバイスにデータを送るかという送信元と送信先の接続情報を、すべてのデバイスに対して決めたものをトポロジーと呼ぶ。一般に、トポロジーとは要素間の接続のされ方を端的に表現したものであり、例えば、スター型接続、デイジーチェーン(数珠つなぎ)接続、網目状(蜘蛛の巣状)接続といった幾何学的な接続の様式を一言で表したものである。NestDAQでは、各FairMQデバイス間の接続が 1 対 1 であったり、n 対 m であったりするが、すべてのデバイスをどのように接続するかを決めたものをトポロジーと呼んでいる。具体的にトポロジーを設定するには、設定スクリプトを書き、それを走らせることで、トポロジーの設定を行う。実際のスクリプトの書き方については、チュートリアルを参照のこと。
各 FairMQ デバイスに対して、しばしば何らかの値、すなわちパラメータを渡したいことがある。このパラメータも Redis データベースによって管理されており、ランのスタート、もしくはストップの前後のタイミングで Redis データベースからパラメータの値を読み込んで利用する。例えば、FEEの IPアドレスなどの設定もパラメータを用いて設定している。一方、Redis 経由でパラメータを設定する他に、FairMQ 立ち上げ時にコマンドラインの引数としてパラメータの値を設定することも可能となっている。具体的にパラメータを設定するには、設定スクリプトを書き、それを走らせることで、パラメータの設定を行う。実際のスクリプトの書き方についてはチュートリアルを参照のこと。FairMQデバイスにおいてどのようなパラメータが存在するかは、FairMQ デバイスを実行する際に、--help オプションをつけて実行するとパラメータの一覧とその役割が確認できる。ただ、網羅されていない場合もあり、--help オプションで見つけられないパラメータはソースコードを読んでパラメータの役割を理解し、値を設定する。
各 FairMQ デバイスはユーザー権限で実行できる通常の Linux プロセスである。具体的に FairMQ デバイスを立ち上げるには、コマンドラインから FairMQ のバイナリファイルを実行すればよい。ただ、FairMQ デバイスの数が多い場合、いちいちコマンドを打つのは面倒なので、専用のシェルスクリプトを書き、それを走らせることですべての FairMQ デバイスを立ち上げる。現在、よく利用される方法は、tmux プログラムを用いて管理しやすいように各 FairMQ デバイスを走らせることである。tmux については、 Google で情報を調べれば出てくるが、タブという概念があり、各タブにおいてプログラムを実行することが可能となっている。NestDAQ を走らせるためによくやる方法としては、例えば Sampler が10 個、Sub Time Frame Builder が 10 個、Time Frame Builder が 3 個、 File Sink 1 個を走らせたい場合、Sampler, Sub Time Frame Builder, Time Frame Builder, File Sink 用にそれぞれ 1 つずつ xterm のウィンドウを用意し、各 xterm のウィンドウで tmux のセッションを走らせ、Sampler 用の xterm では tmux のタブ 10 個を用意し、各タブに 10 個の Sampler を走らせるというようにすることができる。各 xterm の tmux ではタブを切り替えることで、各 FairMQ デバイスが Error を出さずに動いているかといったことが確認できる。実際のスクリプトの書き方についてはチュートリアルを参照のこと。
NestDAQ では Front End Electronics (FEE) から止めどなく (Stream のように) 流れてくるデータを Sampler プロセス (FairMQ デバイス) が受けとり、処理を行なって次の FairMQ デバイスに流し、さらにその FairMQ デバイスで処理をして次の FairMQ デバイスに流すということを繰り返して、止めどなく処理を行っていく。(このように、データを処理するプロセッサを直列につなぎ、あるプロセッサの出力があるプロセッサの入力になるように処理することをパイプライン処理と呼ぶ(あってる?)。)FairMQデバイス間の通信は具体的には ZeroMQ ライブラリが管理しており、データのバッファリング処理などは ZeroMQ が“よしな”に処理している。(ただ、ZeroMQのブラックボックス的な仕様のため、キューに詰まっているデータの量といった基本的な情報が取得できないようで、NestDAQ 開発陣は苦労しているとのこと。)FairMQにはデータを受け取る in ポートと out ポートというものが存在するが、他にも 特殊な out のポートとして、dqm ポートと decimater ポートが存在する。データ収集のメインのデータは in ポートと out ポートを用いて送受信が行われる。dqm ポートは検出器の健全性をオンラインの解析でチェックするために用いられるポートである。また、decimater ポートは Time Frame Builder が持つポートであり詳しくは、Time Frame Builder の項目を参照のこと。以下では、NestDAQ で用いられているそれぞれの FairMQ デバイスの役割を説明する。
Sampler は AMANEQ、CIRASAME といった FEE に TCP/IP プロトコルで接続し、TDC データ、及びデリミタデータを TCP 通信で読み出すための FairMQ デバイスである。https://github.com/spadi-alliance/nestdaq-user-impl のソースコードでは、AmQStrTdcSampler というデバイス名になっている。CIRASAME の出力データ構造は AMANEQ と同じであるため、CIRASAME のデータは AmQStrTdcSampler を用いて読み出すことが可能である。Sampler は各 FEE ボードと 1 対 1で通信を行うため、FEE ボード 1 台につき 1 つの Sampler を立ち上げる必要がある。AmQStrTdcSampler に与えるパラメータは Front End Electronics の IP アドレスと FEM (Front End Module) type と呼ばれる番号である。FEM type は現状で以下のように設定するのが慣例である。(ユーザーが定義することもできるが、混乱を招かないように、新しい番号を利用する場合は SPADI Alliance で議論することが望ましい。)
Firmware | データ構造 | FEM type |
AMANEQ LR-TDC v1.? 以前 | AMANEQ LR-TDC v1.? 以前のデータ構造 | 1? |
AMANEQ HR-TDC v1.? 以前 | AMANEQ HR-TDC v1.? 以前のデータ構造 | 2? |
AMANEQ LR-TDC v2.? 以降 | AMANEQ LR-TDC v2.? 以降のデータ構造 | 3? |
AMANEQ HR-TDC v2.? 以降 | AMANEQ HR-TDC v2.? 以降のデータ構造 | 4? |
AMANEQ MIKUMARI Primary v2.? 以降 | AMANEQ LR-TDC v2.? 以降のデータ構造と compatible | 4? |
AMANEQ MIKUMARI Hub v2.? 以降 | AMANEQ LR-TDC v2.? 以降のデータ構造と compatible | 4? |
CIRASAME v?.? 以降 | AMANEQ LR-TDC v2.? 以降のデータ構造と compatible | 4? |
Sub-Time Frame Builder (STFB) は sampler からのデータを Time Frame ごとに切り分け (?)、ヘッダー情報を付加するための FairMQ デバイスである。https://github.com/spadi-alliance/nestdaq-user-impl のソースコードでは、STFBuilder というデバイス名になっている。Sampler に 1 対 1 で接続してデータを受けとり、処理を行って後段の FairMQ デバイスにデータを出力する。FEE - Sampler - STFB の接続はすべて 1 対 1 の接続となるため、例えば FEE が 10 台ある場合、Sampler は 10 プロセス、STFB も 10 プロセス立ち上げる必要がある。一方で、STFB 以降の FairMQ デバイスは、N 対 M (N 対 1 もしくは 1 対 N を含む) で接続可能である。
Time Frame Builder は各 Sub-Time Frame Builder の出力を受けとり、同じ Time Frame のデータをすべての FEE から集め、ひとまとまりの Time Frame Build されたデータとする。https://github.com/spadi-alliance/nestdaq-user-impl のソースコードでは、TimeFrameBuilder というデバイス名になっている。このひとまとまりの Time Frame データに Time Frame Header と呼ばれる Header 情報を付加し、下流の FairMQ デバイスに出力される。一つの Time Frame Build されたデータには、すべての FEE における同一 Time Frame のデータが含まれている。Sampler と STFB は、FEE の数と同じ数だけ立ち上げる必要があるが、Time Frame Builder を立ち上げる数は FEE の数と同じである必要はない。処理が間に合えば Time Frame Builder は 1 つでも構わない。Time Frame Builder を 2 つ以上立ち上げる場合は、Sub-Time Frame Builder からのデータが適切に各 Time Frame Builder に割り振られるように FairMQ デバイスの auto sub channel のパラメータを true に設定する必要がある(?要確認)。
このデバイスの理解を深めるため、例をもとに説明しよう。例えば、Sub-Time Frame Builder が 2 つ (STFB A, STFB B)、Time Frame Builder が 3 つ (TFB A, TFB B, TFB C) あったと仮定しよう。STFB A, STFB B にはそれぞれ上流の 2 つの FEE からのデータが流れてきている。ここで、各 STFB の各 Time Frame に対して番号が 1 から順番に割り振られるとしよう。このとき、STFB A, STFB B からの Time Frame 番号 1 番のデータが TFB A に行き、Time Frame 番号 2 番のデータが TFB B, Time Frame 番号 3 番のデータが TFB C、Time Frame 番号 4 番のデータが TFB A に行きというように順番に流れていけば、TFB A では Time Frame 番号が 1, 4, 7, 10, ...、TFB B では Time Frame 番号が 2, 5, 8, 11, ... 、TFB C では Time Frame 番号が 3, 6, 9, 12, ... というようにSTFB A, STFB B の同一 Time Frame 番号のデータをビルドできる。一方、STFB A と STFB B の出力先をうまく設定できていない場合、例えば、STFB A の Time Frame 番号 1 番のデータが TFB A に行き、STFB B の Time Frame 番号 1 番のデータが TFB B に行った場合、TFB A では STFB B からの Time Frame 番号 1 番のデータが来ないために正しくTime Frame build できないことになるし、TFB B でも同じ問題が生じる。このように、Sub-Time Frame Builder と Time Frame Builder の接続は注意して正しく設定しないと、Time Frame Build ができないことになる。
また、Time Frame Builder はこのプロセスの負荷に応じて処理が間に合うように立ち上げる数を調整する必要がある。処理が間に合っているかどうかという判断は経験が必要な場合があるが、Time Frame Builder の Elapsed time を調べたり、CPU 使用率、メモリ使用率、DAQが止まらないかといったことを見て判断する。
Time Frame Builder の一つの機能として、build した Time Frame の一部を間引いて、decimater ポートから出力することができる。このポートに後述する File Sink をつなげることで、Filter プロセスなどでバイアスがかからない生のデータを単に間引いたものを保存することができる。このデータを解析することにより、バイアスなしのビームの数などの分母の情報がわかるので、これをもとに物理イベントの断面積などが計算可能になる。
Logic Filter は Time Frame Builder から出力されたデータを受け取り、コインシデンス条件といった情報に基づいて、Time Frame データにコインシデンスのフラグを挿入するための FairMQ デバイスである (?)。https://github.com/spadi-alliance/nestdaq-user-impl のソースコードでは、LogicFilter というデバイス名になっている。このデバイス名には Filter とついているが、実際にこのデバイスでデータが減らされているわけではなく (?要確認)、実際にデータが削減されるのは、下流に接続されるTime Frame Slicer である。Logic Filter という名前よりも、Coincidence Logic checker とか、Conincidence Logic Flag Samper とかのほうがわかりやすいかもしれない。このデバイスが出力するデータには、?? Header と呼ばれる Header 情報が付加され、下流の FairMQ デバイスにデータが送られる。
このデバイスの理解を深めるため、例をもとに説明しよう。FEE のボードが 2 つ (FEE A, FEE B)、Sampler が 2 つ (Sampler A, Sampler B)、 Sub Time Frame Builder が 2 つ (STFB A, STFB B) 、Time Frame Builder が 1 つ (TFB A) あったと仮定しよう。さらに、FEE A は Sampler A を経由して STFB A にデータを送っており、FEE B は Sampler B を経由して STFB B にデータを送っていると仮定しよう。測定したいイベントがもし 10 kHz 程度であった場合、TFB A で Time Frame Build されたデータにおいて、1 つの Time Frame あたり、?? 回のイベントが記録されている。ここで、測定したいイベントが発生した際は、必ずあるプラスチックシンチレータのスタートカウンターが鳴ると仮定しよう。さらに、このプラスチックは両読みになっており、FEE A からのデータのチャンネル 0 とチャンネル 1 に信号が入っていると仮定しよう。このとき、FEE A のチャンネル 0 とチャンネル 1 がある時間幅の中で同時に鳴ったときに、測定したいイベントが発生したと考える。Logic Filter では、コインシデンス判定を行う時間幅(コインシデンスウィンドウ)を設定し、さらに、コインシデンスの判定を行うチャンネルの設定も行う。このような条件に基づいて Logic Filter ではデータの処理を行い、FEE A のチャンネル 0 とチャンネル 1 がコインシデンスウィンドウ内で同時に鳴った場合、フラグビットを True にして、その付加情報を Header に加え、下流の FairMQ デバイスに送る。
コインシデンスの判定方法のアルゴリズムをもう少し詳しく説明しておこう。現在の Logic Filter の仕様では、Look Up Table を用いて、コインシデンスの判定を行う。また、Look Up Table の時間の最小単位は 4 ns に設定されている。そのため、 1 つの Time Frame は ??? 分割されることになる。ここで、FEE A のチャンネル 0 とチャンネル 1 が 10 kHz 程度で鳴っているとする。このとき、以下の図のように、FEE A のチャンネル 0 とチャンネル 1、さらに他のチャンネルのヒットのパターンを表したとする。色で塗った部分は 4 ns の時間幅の中で少なくとも 1 回鳴ったことを表している。このとき、?? 番目と ?? 番目の時間区間でチャンネル 0 とチャンネル 1 が同時に鳴っており、測定したいイベントが発生したと考える。この時間の区間のフラグビットを True にすることで、この時間幅内のデータを保持し、この時間幅以外のデータを棄却できるようになる。
Time Frame Slicer は Logic Filter が付加した情報をもとに、コインシデンスフラグが立った時刻の前後で Time Frame のデータを切り取り、Time Frame 単位ではなく、もっと短い時間間隔のデータの単位に変換するための FairMQ デバイスである。ここでは、新たにヘッダーも付加して、下流の FairMQ デバイスに送っている。https://github.com/spadi-alliance/nestdaq-user-impl のソースコードでは、TimeFrameSlicerByLogicTiming というデバイス名になっている。ByLogicTiming といっているのは、???という理由からである。Time Frame Slicer を用いる理由は、解析ソフトウェアにおける解析速度の向上とデータの削減である。Time Frame Slicer を用いることで、データ解析の速度が向上する理由は次のようなものである。Time Frame は ?? usec と長い単位であるため、測定したいイベントが一つの Time Frame に複数入っていることになる。そのため、この単位のデータの解析を行うとすると、解析ソフトウェアにおいて、コインシデンスウィンドウを定義して、データをすべて舐めて、イベントを切り出して、表示するということが必要になり、処理に時間がかかる。このような処理は DAQ のプロセスで行う方が素直であるため、FairMQ デバイスとして用意されている。このFairMQデバイスにおいて、コインシデンス時刻情報に基づいてスライスを行うということは、測定したいイベント毎にある時間幅でイベントを切り出していることになる。これはイベントビルドをしていることに相当し、さらに、コインシデンスイベント以外のデータを削除も行っている。
Time Frame Slicer からのデータを受けとり、それを解析して、データの取捨選択を行うための FairMQ デバイスである。https://github.com/spadi-alliance/nestdaq-user-impl では、FilterTimeFrameSliceBySomething という FairMQ デバイスがサンプルとしてあり、この FairMQ デバイスのソースコードを編集して、好きな Filter ロジックを実装する。Time Frame Slicer からのデータはコインシデンスしたイベントの単位 (スライス) になっているため、このデータをオンラインで解析することで、各スライスを下流の FairMQ デバイスに送るか否か、すなわちスライスの取捨選択を行う。例えば、J-PARC MARQ スペクトロメータ T103 実験の例では、各スライスの TOF カウンターの情報から TOF を計算し、K中間子とパイ中間子の識別を行い、スライスの取捨選択を行った。この Filter では、他にもドリフトチェンバーのトラッキングを行ってスライスの取捨選択を行ったりすることも原理的には可能であると考えられる。現在、このような高度な Filter の開発が進んでいる。
上流の FairMQ デバイスから送らてきたデータを受けとり、ファイルに保存する FairMQ デバイスである。ファイルの最初と最後には File Sink Header と File Sink Trailer と呼ばれる情報を付加している。https://github.com/spadi-alliance/nestdaq-user-impl のソースコードでは、FileSink というデバイス名になっている。File Sink は Sub Time Builder, Time Frame Builder, Logic Filter, Time Frame Slicer, High Level Filter といったほぼすべての FairMQ デバイスに接続し、そのデータをファイルとしてストレージに保存することができる。
Data Quarity Monitor (DQM) はさまざまな種類の実装が考えられるが、検出器のデータの健全性や、FairMQ デバイスのデータの健全性を確認するための FairMQ デバイスの総称である。このデバイスは上流の FairMQ デバイスの dqm ポートに接続して用いる。例えば、Logic Filter の時間のコインシデンスを決定する際に、Logic Filter の dqm ポートに Trigger View と呼ばれる Data Quarity Monitor を接続し、このプロセスのグラフィカルなヒストグラムの出力結果を見ながら、Logic Filter のコインシデンスウィンドウの時間調整などを行う。また、Sub Time Frame Builder の dqm ポートに DQM を接続し、AMANEQの Heart Beat Frame Delimiter Flag をオンラインでチェックし、AMANEQ が正しく動いているかを確認することもある。
NestDAQ は RedHat 系の Linux 上での運用を想定しており、現時点 (2024年9月) における推奨実行環境は AlmaLinux 最新版の AlmaLinux 9.4 である。CentOS 7, AlmaLinux 8, AlmaLinux 9 などの RedHat Enterprise Linux (RHEL) のクローンにおいて稼働実績があり、最近の RedHat 系 Linux ではだいたい運用可能であると考えられる。また、Ubuntu 22.04.3 LTS といった Ubuntu/Debian 系の Linux でもコンパイル実績はあるが、本番実験で使用された例はない。また、ソースコードの軽微な修正を行うことで MacOS (Intel CPU) でも clang を用いてコンパイルが通ることがわかっているが、詳しく動作確認された例はない。最近では Windows において Windows Subsystem for Linux (WSL) を用いることで Linux が利用可能になっており、おそらく NestDAQ も動くと考えられるが、検証された例はない。CPU のアーキテクチャーは 64 bit の x86_64 であれば特に問わず、普通の Intel もしくは AMD のデスクトップ用もしくはサーバー用CPU で動作すると考えられる。(32-bit OS は全く動作検証がなされていないが、32-bit OS で NestDAQ を動かそうとする人はいないであろう。)
NestDAQ は ZeroMQ、Boost といったライブラリが必要であり、NestDAQ をインストールする際は事前に各種ライブラリをインストールしておく必要がある。詳細はインストールのインストラクションを参照のこと。C++ のコンパイラとして比較的新しい GCC の g++ が必要である。clang によるコンパイルはあまり実績がないため、g++ によるコンパイルが望ましい。
また、KEK INPS の千代氏が Apptainer 用のコンテナを用意しており、これを用いることでOS非依存にインストールを行わずに NestDAQ を利用可能である。
2024/10/18 小林 信之 (大阪大学RCNP)