この記事はTouchDesigner Advent Calendar 2021の21日目の記事です。
刻みTD
**刻みTD (きざみてぃーでぃー、きざみたっち)**とは:**toeで構築する1つのネットワーク全体を、個別モジュールのプロセス間通信に置き換える(toeを刻む)**ことにより、システム全体の開発性と安定性、パフォーマンス向上を試みる。というものです。さらに記事の後半では、刻みTDをすることによる複数モジュールの複数人同時開発に関しても紹介いたします。
なお、この名称はチーム内で勝手につけているものなので、公式でもなんでもないです
本記事で使用しているサンプルファイルはこちらにあります。
刻みTDの作り方
TouchDesignerでは、Base COMP
やContainer COMP
のように全体のネットワークの一部分を機能モジュールのようにまとめることができます。Componentとしてまとめた上で、In - Out Operator
を用いることで、Componentごとをネットワークで接続して、より抽象化した状態で、機能モジュールごとを接続して開発をすることができます。さらに、個別のComponentに対して、Component Extention
によってスクリプト処理を追加することで、複雑な処理を内包する場合でもシンプルに1つの機能モジュールとして扱う事ができます。このComponentによってモジュール化を行い、モジュール同士をネットワークで接続して全体のシステムを構築することで、全体として見通しの良いシステム構築ができると思います。
一方で、システムが大きくなるほど、1つのネットワーク(toe)で複数の処理を同居させた場合に、一部の処理が全体のパフォーマンスを律速してしまう、一部の処理が止まってしまうとシステム全体を止めざる負えない、などの問題が発生します。TouchDesignerでは、基本的には1つのtoeで実行されるシステムは1つのプロセスで実行されます。
そこで、toeで構築する1つのネットワーク全体を、複数のtoeに分割することで複数のプロセスに分割し、個別モジュールのプロセス間通信に置き換える(toeを刻む)ことで、システム全体の開発性と安定性、パフォーマンス向上を試み、さらに複数人開発も容易にする。という設計を可能にします。本記事では、刻みTDの特徴、基本的な刻み方、刻みTDによる開発に関して紹介したいと思います。
基本的な刻み方
非常に単純な例として、モジュールA→B→C→D
のように処理の結果を順次渡していき、最終的な画面表示や外部モジュールの動作を行うシステムを想定します。
通常のTouchDesignerのネットワークでは、図にあるように、A→B→C→Dの機能ごとにネットワークをつくります。かつ、それぞれの処理モジュールをコンポーネントにまとめることで、視覚的にもA→B→C→Dもモジュールがわかりやすくなります。
F2で表示して、パフォーマンス実行状態を観察しても、コンポーネントA, B, C, Dが一連のプロセスとして処理されていることがわかります。
ここで、それぞれのコンポーネントごとをつなぐリンクの代わりに、TouchOUT
, TouchIN
などのプロセス間通信を用いることで、toeを刻みます。具体的には、コンポーネントA→B→C→Dで構成されていた、システムをそれぞれ、A.toe
, B.toe
, C.toe
and D.toe
のように別のtoeとして作成し、各toe間をTouchIN-OUT
で繋ぎます。リンクの代わりに、別のTouchIN/OUT
を構成する必要があるので、それぞれ異なるポート番号を割り当てます。ここでは、A→(8001)→B→(8002)→C→(8003)→D
としています。
これにより、A.toe
, B.toe
, C.toe
and D.toe
はそれぞれ別のプロセスとして動作したうえで、処理内容はTouchOUT-IN
で伝搬していくのでシステム全体としてはA→B→C→D
を一つのtoeで構成していたときと(ほぼ)同じシステムを構築することができます。
それぞれのパフォーマンスモニターをみると、先述のコンポーネントA, B, C, Dが一連のプロセスとして処理していたのに対して、4つのtoeに処理が分割されていることがわかります。
刻みTDによるの利点と欠点
刻みTDの利点は下記になります。
- 別プロセスとして処理負荷を分散することができる。
- 個別モジュールにすることで、ユニット開発やテストが容易になる。
- 個別モジュールごとのversion管理が容易になる。
- 個別モジュールのフレームレートを可変、個別指定できる。
一方で、刻みTDの欠点も留意する必要があります。
- プロセス間通信の際に発生する、処理・通信遅延が発生する。刻むごとに、プロセス通信とアプリケーションフレームの関係で、システム全体の遅延が蓄積する。
- モジュール間のやり取りする内容を変えるのに手間がかかる。(システム全体の中で、何の情報をどこのコンポーネントが用いるかが明らかでない場合には、刻むと大変)
- モジュール間での処理の実行タイミングが不定になる。
このように、盲目的に刻むのではなく、システム全体や開発状況に応じて、まとめておくか、刻むかを判断する必要があります。なお、刻んだ後に繋ぐ、といった方法も後述いたします。
- 刻みTDによる効果が期待されるユースケース
- 一連の処理の中で、処理負荷が高くアプリケーション全体のフレームレート低下や極端なフレームドロップ発生を防ぎたい。
- システム一連の中で、描画フレームレート以上(例えば60Fps以上)の処理フレームレートで実行したい。
- システム一連の中で、可変フレームレートでの処理と固定フレームレートでの描画を実現したい。
- 処理負荷分散や、機材物理的制約から複数のマシンで一連システムを構築したい。
- 複数モジュールを複数人で同時開発しつつコンフリクトを避けたい。
- システムの一部が不安定になったとしても、システムの全体は止めずに部分的にリカバリー可能にしたい。
このような場面において、刻みTDは効果を発揮することが期待されます。
刻むためのプロセス間通信:TouchIN/OUT
TDを刻む場合、TouchIN/OUT
などのプロセス間通信を用いることになります。しかし、プロセス間通信を用いる以上、その処理や入出力タイミングのズレによって発生する遅延に注意する必要があります。例として、Queue
数やMaximum Queue
を調整することで、遅延を最小化することもできます。
参考:
刻みtoeでBuffer最小のTouchOUT-IN / TouchOUT-INで往復させた場合、欠損があるが安定すると1フレーム遅延で帰ってくる。いいかも。刻みtoe TT作戦 #TouchDesigner https://t.co/5MAuLMr1xK pic.twitter.com/Y1bm6d7OPm
— Shunichi Kasahara (@shn_kasa) October 10, 2021
一方で実行環境によっては値抜けなど発生するので、実行環境でテストしたほうがよいです。
参考:https://forum.derivative.ca/t/touchin-touchout-lag/4674/7
TouchIN/OUT CHOP, DAT, TOP
-
TouchIN/OUT CHOP
では、CHOPオペレーターで扱うような数値情報をプロセス間でやり取りできます。TouchIN/OUT CHOP
では、複数チャンネルの情報も送受信できますが、1サンプル以上のCHOPデータを送る事ができません。つまり、音声データをやり取りするのは現時点では向きません。(記事作成時点)しかし、DATデータにへ変更することで1サンプル以上の系列のデータを送受信できるようになります。 -
TouchIN/OUT DAT
では、DATオペレーターで扱うようなテキストデータや、テーブルデータをプロセス間でやり取りできます。
-
TouchIN/OUT TOP
では、TOPオペレーターで扱うようなテクスチャデータをプロセス間でやり取りできます。CHOPやDATと異なり、TOPではテクスチャデータを(HapQ
などの圧縮、もしくは非圧縮)送受信するため高負荷が予想されます。まず、同一マシン内であれば、Spout (Windows)
もしくはSyphon (Mac)
のテクスチャ共有を使用する選択肢を検討したほうが良さそうです。
他のプロセス間通信
TouchIN-OUT
以外にも、プロセス間通信を実現する方法はNDI
, OSC
, Spout
, Syphon
などがあります。特に音声、映像以外の数値やテキストのやり取りであればOSC
、映像であればSpout
, Syphon
(同一PC内)やNDI
などがあり、TouchDesigner以外のアプリケーションや開発環境においてもサポートされているので、それらを組み合わせることで、刻みTDの中にUnity
やP5
,独立のPython
処理などを添える、といったシステムを構成することができます。
刻みTDを複数マシンで処理分散
刻みTDによってプロセスを分けることで、同一PC内で刻むだけではなく、複数PC間に刻んだTDを分散させることが出来ます。複数PCをネットワーク(有線LAN)で接続したローカルネットワークを構成した上で、先述のIP指定でlocalhost
の代わりにそれぞれのPCでのIPアドレスを指定することで、複数マシンへ容易に処理分散を行うことができます。図の例は、1台目のPCで信号処理などをしたうえで、2台目のPCでフレームレートを犠牲にせずに映像を表示したい場合などの構成例です。
一方で、複数マシン間にする場合には途中経由のネットワーク機器の性能や、各PCのネットワーク設定(Windows Firewallに注意)によって遅延が発生する必要があります。特に、TouchIN/OUT
のParameter設定で、Queue
を極端に小さくしてしまうと値の取りこぼしが発生する経験がありました。複数マシンで刻む場合には、機材状況やQueue
の設定を注意深く検証することをおすすめいたします。
刻みTD開発
背景:開発フェーズと最適化フェーズ
刻みTDの必要性がでるような複数のモジュールを用いるシステム開発の場合には、それぞれのモジュールの機能開発やデバックをする開発フェーズと、全てのモジュールを繋ぎシステム全体のパフォーマンスをチューニングする最適化フェーズが存在すると思います。それぞれのフェーズでは異なる要件が発生します。
開発フェーズ
- 個別のモジュールをそれぞれの担当者が並行的に開発を行いたい
- 個別のモジュールのみでデバックを行いたい
- 物理的な装置を動作させる代わりに、シミュレーションや記録データを用いて開発をしたい
- 並行開発でコンフリクトをできるだけ避けたい
- 全体のシステムを動かしながら、個別のモジュールを入れ替えて開発検証したい。
最適化フェーズ
- システム遅延を最小化したい
- フレームレートを安定させたい
- システム起動を含めた運用安定性を上げたい
刻みTDと繋ぎTD
刻みTDによるプロセス分割によって、処理負荷分散や並行開発を行ったのちに、刻んだTDのプロセス間通信で発生する遅延を解消し、システムを最適化したいフェーズへ移行する場合も想定されます。そこで、刻みTDに加えて繋ぎTD:モジュール分割化させたtoeを再度統合したtoeにする。ことで、開発フェーズと最適化フェーズを必要に応じて柔軟に進行することを可能にします。
- ここでは、上述の
A.toe
,B.toe
,C.toe
andD.toe
のように刻んだTDを事例にします。ここでは、下記のような要件を想定します。- A:可変フレームレートシステムで、別プロセスとして動かしたい。
- B-C : 処理不可は高くないが間で発生するプロセス間遅延を最小化したい。
- D:外部機器制御上、可能な限りシステムを安定に、60FPSを担保したい。
この要件に基づき、B-Cのモジュールを再度TouchDesignerの標準のリンクでシステムを繋ぐとします。しかし**同時に、BとCのモジュール自体も並列・個別に開発検証を行いたい。**とします。
tox化
そこで、B.toe
の中にある、BモジュールコンポーネントとC.toe
の中にあるCモジュールコンポーネントをそれぞれ、B.tox
, C.tox
として、外部モジュールファイル化します。tox化は例えば、コンポーネントを右クリックメニューでSave Component tox.
をすることで、別toxファイルとして保存できます。
例として、A.toe
, B.toe
, C.toe
and D.toe
すべてをtox化した場合には、図のような関係になります。
tox化の際のTips
tox化する際に、TouchIN/OUT
の別プロセスのためのオペレーターを、コンポーネントにInオペレーターの第2インレットに接続することで、TouchIN/OUT
でも、実際のリンクでも両方使えるtoxにすることができます。
Inオペレーターの第2インレットは、「コンポーネントの上の階層でインレットへの入力がない場合には、第2インレットの入力を用いる」という挙動をします。つまり、コンポーネントを実結線すればそのリンクの情報を用いる。もしコンポーネントへのリンクがなければ代わりに、TouchIN/OUT
の情報を用いる。という事ができるのです。
再繋ぎTD
それぞれのコンポーネントがtox化された後、B-Cモジュール統合のためのtoeをBC.toe
として用意し、そこにB.tox
, C.tox
を配置します。ここでは、A.toe
とD.toe
はそのままにしておきます。
このようにすることで、A, Dモジュールとは分離しつつも、BとCモジュールを再び通常のリンク結線に戻し、刻んだ事によって発生してた遅延を解消することが出来ます。
また、全てをリンクによって結線する。完全に繋ぎTDに戻す、ということも可能です。ネットワーク図としては、最初にコンポーネントで分けた状態と同じに見えますが、それぞれのコンポーネントがExternal toxになっていることに注意してください。ここでの、ファイル構成は図のようになります。
刻みTD開発
-
開発をすすめる上で、BモジュールとCモジュールをそれぞれ更新していく場合、
B.toe
、C.toe
、さらに、BC.toe
でそれぞれB.tox
,C.tox
に該当するコンポーネントを編集することは出来ますが、あくまでもそれぞれのtoeの中での更新されているだけで、モジュール外部ファイル(tox)は古くなっていってしまいます。これらは、手動でtoxを更新することで、同期を確保することが出来ます。 -
しかし手動では、忘れやすい人間の特性上望ましくないので、これらを継続的に開発しながら、最新の状態に保つために、下記のようなtoe, toxの取り扱いを設定しておきます。
-
B.toe
、C.toe
、BC.toe
において、該当のコンポーネントをB.tox
,C.tox
を読み込むexternal tox
とすることで、起動時に必ず最新のB.tox
,C.tox
をファイルから読み込まれるようになります。 - Higaさんの
external tox saver
を用いることで、toe内に配置されている、external toxコンポーネントをtoeでの編集内容をそれぞれにtoxに保存されるように指定できます。https://satoruhiga.gumroad.com/l/ExternalToxSaver - これを行うことで、
B.toe
、C.toe
、BC.toe
に配置されているB.tox
,C.tox
のexternal ojectは、どのtoeから編集をしていても更新されるようにしておくことが出来ます。
-
-
以上の手順によって、
A.toe→BC.toe→D.toe
のように刻んだTDを一部繋ぎ直す事ができました。なお、前述のBモジュールコンポーネント、Cモジュールコンポーネント (B.tox
,C.tox
)では、それぞれTouchIN/OUT
も残っているので、個別のB.toe
,C.toe
を個別起動したとしても一連のシステムは処理されます。
このように、開発フェーズと最適化フェーズを行き来できるのと、システム全体を複数人で開発している際に、開発モジュールの担当さえ明示しておけばよきせぬコンフリクトを避ける事ができます。
Case Study
最後に刻みTDで開発をしたいくつかのプロジェクトを紹介します。
- こちらのプロジェクトでは、カメラトラッキングと三角測量によるボール3次元トラッキング、弾道予測、ロボットアームの動作計画、ロボットアームへの動きの司令、Virtual RealityHMDへの映像のレンダリングを2台のPCと7個のtoeに刻むことで、システムを安定化させています。特に、ボールトラッキングは状態に応じて、70FPS-120FPSの可変フレームレートであるのに対して、ロボットアームへの制御信号や、Virtual Reality HMDへの映像レンダリングはFPSを可能な限り固定で保つ必要がありました。また、開発途中では、実際の環境を使わずに、レコーディングデータや物理シミュレーションを用いて開発するなど、刻むことで実データとシミュレーションデータを切り替えて開発できるような構成を作っています。
- また、こちらのプロジェクトでは、一部の映像合成にpython側での処理を行っており、その際に著しいフレームドロップが発生するため、その部分を刻んで外部化して
TouchIN/OUT TOP
で接続しています。詳しくは、こちらの技術紹介にて構成を紹介しております。
トラブルシューティング
- なお
TouchIN-OUT
では、TCP/IP
(もしくはUDP
)通信を用います。Windowsではネットワーク設定上通信がうまくいかない場合があります。おかしいとおもったら、Windows Firewall
を無効化してしてみてください。 -
Windows Firewall
の恐ろしい点として、完全に接続できなくのではなく、若干遅い、時と場合によっては繋がる、のような挙動で問題の切り分けに時間を要したケースがありました。怪しいときには、Windows Firewall
を疑ってください。
まとめ
この度は、TouchDesignerで複数モジュールを複数人で同時開発する際にわりと調子がよかった構成として刻みTDを紹介させていただきました。今後、TouchDesignerをお使いの皆様が各所で「ここの部分刻んどいて!」と言ったときのリファレンスになれば幸いです。
いつか誰かの役に立ちますように。