Houdini 17.5 TOPsを使ってプロシージャルディペンデンシーグラフ(PDG)を構築する方法

TOPの紹介

TOPネットワークの背後にある基本的な概念とTOPネットワークでできる事について説明しています。

On this page

概要

TOPネットワークは、コンピュータに処理させたいワークアイテム(作業項目)を生成するための"レシピ"を作り、単一マシン上もしくはレンダーファーム上のプロセス内で効率的にワークアイテムを走らせたり、 できるだけ並列でたくさんのワークアイテムを実行できるように依存関係を解決します。 作られる"レシピ"の正体は、処理したいワークアイテムとその依存関係を示したPDG(Procedural Dependency Graph)です。

街を生成するワークフローを例にすると、地形の生成、道路のレイアウト、多種多様なビルのアセットの配置、樹木の配置、標識やベンチといった街頭設置物の配置などが必要になります。 これらの工程のいくつかは並列で処理することができ、他の工程は特定の工程が完了するまで処理を開始することができません。

手動で記述したスクリプトを使って街の生成を自動化しようとした場合、おそらく、それらの工程を別々の"パス"(地形の生成、道路のレイアウト、ビルの配置など)に分けることになるでしょう。 この方法だと、ほぼ間違いなくパス内およびパス間で並列で実行できる機会を見逃してしまうので、本当はまったくといって非効率です。 例えば、地形の特定のタイルの処理が終われば、他のタイルの処理が完了するのを待つことなくそのタイルに対して道路のレイアウトや樹木の配置を始めることができるはずです。

最終出力を生成するのに必要なすべての作業間で依存関係のネットワークを構築することで、TOPsはもっと効率の良い方法を探して街のレシピを"クック"することができます。 何かしらの変更があった時でも、TOPsはその変更のあった情報に依存している部分を把握しているので、その街の"再クック"に必要となるワークを最小限で実行することができます。

Houdiniの一部として、TOPsは特にシミュレーション、レンダリング、コンポジットなどのエフェクト作業を遂行できるように重きを置いていますが、 依存関係を持たせた状態で個々のワークアイテムに分解可能な作業でも役立ちます。

TOPノードのネットワークを構築することによって、処理させたいワークを指定し、その結果を制御する方法を指定します。 TOPノードは、ワークを実行するワークアイテムを生成したり、アトリビュートに情報を格納します。 TOPノードは主に2つのタイプがあります: プロセッサは新しいワークアイテムを生成し、パーティションはそのパーティション内のすべてのワークアイテムが完了するまで待機できるようにワークアイテム間に依存関係を生成します。

ワークアイテム

  • TOPネットワーク内の各プロセッサノードは、特定の数だけ ワークアイテム を生成します。このノードから生成されたワークアイテムは、TOPネットワーク内のノードボディ内部で表現されています(詳細は、以下のネットワークインターフェースを参照してください)。

  • ほとんどのワークアイテムは"ジョブ"を意味しています。つまり、単一コンピュータまたはレンダーファームのどちらかのプロセスで実行させるスクリプトまたは実行ファイルを指します。しかし、一部のワークアイテムは単にアトリビュートを保持するためだけに存在していて、実際には何のワークも処理しません。

    例えば、HDA Processorノードが生成したワークアイテムは、ワークを表現します: これらのワークアイテムは入力ファイルに対してHoudiniアセットをクックします。 しかし、File Patternノードが生成したワークアイテムは、単にマッチした各ファイルパスのホルダーにすぎません。 そこから下流にあるプロセッサノードのワークアイテムによって、それらのファイル名を使って何かを処理する必要があります。

アトリビュート

ワークアイテムは、HoudiniジオメトリのPointアトリビュートと同様に何かしらの情報を含んだ アトリビュート を持っています。 ワークにそのアトリビュートを読み込ませることで、そのワークの処理を制御することができます。 アトリビュートは、"親"ワークアイテムから生成されたワークアイテムに渡されるので、このアトリビュートを使用することで、ワークアイテムの結果を子ワークアイテムの処理に影響を与えたり、 ワークアイテムをまとめてグループ化したり、ネットワークを通じて情報を渡すことができます。

カスタムコードにアトリビュートを読み込ませることでワークアイテムの生成を制御することができますが、 アトリビュートを最もよく使うのは、 TOPノードのパラメータ、もしくは、TOPネットワークが参照するHoudiniのネットワークとノードのパラメータからそのアトリビュートを参照する 時です。

  • 例えば、異なるレンダー品質を試行錯誤したいとしましょう。Wedge TOPを使用してpixelsamplesアトリビュートに異なる値を設定したワークアイテムを生成することができます。すると、ROP Mantra Render TOPの Pixel Samples パラメータでそのアトリビュートを参照できるように@pixelsamplesを設定することができます。

  • 他にも、TOPネットワークからコールされた外部のアセット/ネットワークのワークアイテムアトリビュートを参照することができます。例えば、HDA Processorはワークアイテム毎にHoudiniアセットをクックすることができます。そのアセットのパラメータに@attribute参照を使用することで、そのワークアイテムから値を引き出すことができます。

@attribute.componentを使ってベクトルのコンポーネントを参照することができます。componentは0から始まる数値またはx, y, z(それぞれ0, 1, 2に該当)です。例えば、@pos.xまたは@pdg_output.0です。

ノードとカスタムコードは任意でアトリビュートを追加することができますが、ワークアイテムにも常にアクセス可能なビルトインのアトリビュートがいくつか用意されています。

詳細は、アトリビュートの使い方を参照してください。

プロセッサ、パーティション、マッパー

プロセッサ

プロセッサは新しくワークアイテムを生成します。 既存のワークアイテムに基づいて複数の新しいワークアイテムを生成("fan-out:分散")することができます。

プロセッサノードは、ノードのパラメータに基づいてゼロから新しいワークアイテムを生成することができます。 また、入力ノードのワークアイテムから新しくワークアイテムを生成することができます。 ほとんどのノードはどちらの方法でも動作することができます。 Wedgeノードに何も入力がなければ、そのパラメータで指定されたWedgeの数だけワークアイテムが生成されます。 入力があれば、その入力のワークアイテムの数とWedgeの数を乗算した数だけ新しくワークアイテムが生成されます。

プロセッサノードは、"親"ワークアイテムに基づいて新しく"子"ワークアイテムを生成する際に、そのワークアイテムの結果を下流に渡すことができるように、その親の アトリビュート を子に継承します。

パーティション

パーティションノードは、色々な基準に基づいて入力のワークアイテムをまとめます。 これこそ、PDGが今後の処理用に複数のワークを単一ワークにまとめる("fan-in:結合")方法になります。 パーティションノード別に異なる方法で上流のワークアイテムをまとめることができます。

パーティション化には2つの効果があります:

  • パーティションは、グループ化したワークアイテム間に依存関係を生成するので、そのグループ内のすべてのワークアイテムが完了するまでは処理を継続しません。

  • (オプションで)パーティションは、グループ化したワークアイテムのアトリビュート値を結合します。例えば、パーティションから生成されたワークアイテムは、グループ化したワークアイテムから集まったoutputファイルパスのリストをinputアトリビュートとして受け取ることになります。

一番よく使用するパーティションノードはWait for Allです。 このノードは入力のワークアイテム すべて を単一パーティションにグループ化するので、上流のワークアイテムすべてが完了するのを待ってから、そのパーティションを継続させることができます。

アトリビュートに基づいてワークアイテムをパーティション化(例えば、同じフレームで動作させたワークアイテムすべてをグループ化)したり、他にもカスタム関数を使ってパーティション化したり、空間的にパーティション化することもできます。 例えば、地形上に樹木を配置する場合、地形を格子状に分割し、その特定のタイル内でジオメトリを生成するワークアイテムすべてをグループ化することができます。

パーティション化しただけでは、そのパーティション内のワークアイテムは何のワークも実行しません。 これはただ単にグループ化したワークアイテムから結合した情報が保持されているだけです。 それ以降のワークアイテムは、その結合した情報に対して動作することができます。

マッパー

マッパーは、グラフ内の関連性のないワークアイテム間で依存関係を構築します。 普段の使用では、あまり必要になることはありません。 例えば、異なる2本のノードチェーン内でワークを生成する場合に、システム側に片方のノードチェーンのワークが実際にはもう片方のノードチェーンの何かが完了するのに依存していることを伝えたい時に必要になります。

スケジューラ

スケジューラノードは、実際にはワークアイテム内の実行ファイルを走らせます。

  • スケジューラのタイプが異なれば、実行ファイルを走らせる方法も異なります。例えば、Local Schedulerはローカルマシン上のプロセスプールを使って実行ファイルを走らせるのに対して、HQueue SchedulerはHQueueレンダーファーム上に実行ファイルを配置します。

  • TOPネットワーク内に複数のスケジューラノードを配置することができるので、環境に応じた異なる方法でクックされるネットワークをセットアップすることができます(例えば、ローカルでクックすると同時に変更テストを試験段階のプロセスの一部としてファーム上でのみクックさせたい場合です)。TOP Networkノード Default TOP Scheduler パラメータは、そのTOPネットワークのクックに使用するスケジューラを制御します。

簡単な例

右側の単純化した図は、異なる品質レベルでアニメーションの5フレームをレンダリングし、異なる品質で同じフレームからモザイク(タイル画像)を作成する基本的なネットワークを表わしています。品質設定が最終画像にどのように影響を与えているのか理解できるかと思います。

  1. Wedgeノードは、Wedgeによるバリエーション(例えば、Mantraの Pixel Samples パラメータに異なる値を設定)を含んだ4個の"ダミー"のワークアイテムを生成します。

  2. ROP Mantra Renderノードを追加して、フレーム範囲を1-5に設定します。これによって、"親"ワークアイテム毎に5個の新しいワークアイテムが生成されます。Wedgeさせたアトリビュートは、その新しいワークアイテムに継承されます。

  3. Partition by Frameノードは、同じフレーム番号のワークアイテムに対して、依存関係を持った新しい"パーティション"アイテムを生成します。これによって、同じフレームのバリエーションすべての処理が完了するまでパーティションが待機し、それが完了したら次の工程に進みます。

  4. ImageMagickノードは、各フレームのレンダリングバリエーションを受け取り、それらのフレームを一枚のモザイク(タイル画像)に結合する新しいワークアイテムを生成します。

    もちろん、画像の上にテキストを重ねて、どの設定がモザイク画像内のサブ画像に該当するのかを示すといった処理もできます。

  5. 最後のWait for Allノードは、すべてのワークが完了するのを待機するパーティションアイテムを生成します。

    これによって、"メイン"のワークすべてが完了した後にのみ実行したいワークアイテムをその"Wait for All"の後に追加することができます。 "Wait for All"の後には、例えば、Post-Renderスクリプトを実行するワークアイテム、または、ワークが完了したことをユーザに通知するワークアイテムを配置します。

詳細は、使用頻度の高いTOPノードを参照してください。

静的ワークアイテム vs. 動的ワークアイテム

Static(静的)

TOPネットワークの実行を開始する前でも、単にノードパラメータに基づいた一部のワークアイテムが必要になることはご理解できるかと思います。 このようなワークアイテムのことを Static(静的) ワークアイテムと呼びます。

例えば、何も入力を持たないROP Mantra TOPは、レンダリングするフレーム毎にワークアイテムを生成し、そのレンダリングするフレーム数はノードパラメータで設定するわけなので、そのワークアイテムの数は事前にわかります。 もし、次のノードが入力のワークアイテム毎に新しいワークアイテムを生成するだけなのであれば、それらのワークアイテムも"静的"だと言えます。

映画のワークフローはフレームベースであることが多く、レンダリングするフレーム数が事前にわかっていることから、そのワークフロー自体が結果として静的ワークアイテムを生成することになります。

Dynamic(動的)

場合によっては、一度ワークが完了した後にワークアイテムを生成したいことがあります。 このようなワークアイテムのことを Dynamic(動的) ワークアイテムと呼びます。

ゲームやエフェクトのワークフローは動的であることが多いです。 例えば、群衆をエージェント数に基づいてタイル別に分けて、そのタイル毎に群衆エージェントのセカンダリシミュレーションを実行したいです。 これは、群衆シミュレーションを生成してそれらのファイルが読み込まれた後で 動的に セカンダリシミュレーションを行なうことができます。

  • 一般的な経験則 として、 動的ワークアイテムよりも静的ワークアイテムの方が好まれます: ワークアイテムの数がわかっているので、どれだけのワークが処理されるのかが感覚的にわかり、Houdiniによる完了パーセンテージの評価の精度がもっと良くなります。

  • とはいうものの、 ワークフローによっては、動的ワークアイテムは避けて通れません 。実際にほとんどの ネットワーク全体 が動的です。ゲームのワークフローを例にすると、レイアウトカーブからレベルを生成する時、カーブと他のカーブが交差、カーブとタイルが交差、カーブと他の何かと交差するまでそのワークの量がわかりません。

  • Houdiniがそのワークが静的なのかどうかを判断できなくて、ワークアイテムを静的または動的のどちらで生成するのか選択する場合があります。そのような場合だと、TOPネットワークは実行中に常にどのワークアイテムが必要なのかを解明することができることから、常にワークアイテムを動的とマークした方が 安全 です。しかし、ワークアイテムが静的であることを既に 知っている のであれば、そのノードを静的とマークすることで、その静的ワークアイテムの恩恵を受けることができます。

    (Wait for Allノードは、動的な数のワークアイテムを静的な数(1)に変換することができます。他のパーティションノードでも動的な数を静的な数に変換することができます。このような場合は、手動でノード設定を変更する必要がなくて、Automatic設定で制御することができます。)

    • 一部のプロセッサノードには、 Work Item Generation メニューがあります。ここからStatic, Dynamic, Automaticを選択することができます(Automaticは"このノードが静的ワークアイテムを生成することができる、または、何も入力がない場合に静的ワークアイテムを生成する"ことを意味します)。動的にしか動作しない、または、静的にしか動作しないようなプロセッサには、このようなオプションはありません。

    • 一部のパーティションノードには、 Use Dynamic Partitioning パラメータがあります。パーティション化が動的に生成された情報に依存している場合には、これを有効にしてください。パーティション化が直近の上流の静的ワークアイテム内の"既知"の情報にのみ依存している場合には、これを無効にしてください。その場合、グループ化も静的に計算することができます(一部のパーティションノードには、そのノードが動的または静的なパーティション化のどちらで動作させるのかを指定するためのオプションが備わっていません)。

Tip

TOPネットワークに何もキャッシュ化した結果が存在しない(どのノードにもワークアイテムが存在しない)場合、ネットワークエディタで Tasks ▸ Generate Static Work Items を選択することで、既知の静的なワークアイテムすべてを生成することができます。 これは、そのネットワークで必要となるワークの量を把握するのに役立つことが多いです。

TOPノードネットワークインターフェース

詳細は、TOPネットワークユーザーインターフェースを参照してください。

TOPsを使ってプロシージャルディペンデンシーグラフ(PDG)を構築する方法

基本

次のステップ

リファレンス

  • すべてのTOPsノード

    TOPノードは、データをネットワークに送り込んで"ワークアイテム"に変換し、色々なノードでそれを制御するワークフローを定義します。たいていのノードは、ローカルマシンまたはサーバーファーム上で実行可能な外部プロセスを表現しています。

  • プロセッサ系ノードのコールバック

    プロセッサ系ノードは、スケジューラで実行可能なワークアイテムを生成します。

  • パーティショナー系ノードのコールバック

    パーティショナー系ノードは、複数の上流ワークアイテムを単一パーティションにグループ化します。

  • Python API

    ディペンデンシーグラフを扱うためのPython PDGパッケージのクラスと関数。