Houdini 19.5 PDG/TOPsを使ってタスクを実行する方法

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

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

On this page

概要

パーティショナー系ノードは、PDGグラフが複数の上流ワークアイテムをグループ化する際に使用する仕組みです。 このノードで生成されたワークアイテムのグループのことを パーティション と呼びます。 このパーティション自体がそのパーティション内のワークアイテムに直接依存する特別なタイプのワークアイテムになっています。 パーティションは、その中のワークアイテムからアトリビュートも出力ファイルリストも継承します。 各パーティショナー系ノードのAdvancedタブには、上流アトリビュートをパーティションにコピーする方法を制御するためのパラメータがあります。

PDGには、アトリビュート値、インデックス、フレーム、ノードトポロジーなどのプロパティでワークアイテムをグループ化するために使用可能なビルトインのパーティショナー系ノードがたくさん含まれています。 Partition by Expressionノードや Python Partitionerノードを使用することで、同梱されているノードでは制御できないような場合のために独自のパーティションロジックを組むことができます。 他にも、スタンドアローンのPythonスクリプトとして独自のパーティショナー系ノードを組むこともできます。

プロセッサ系ノードと同様に、パーティショナーは静的または動的のどちらにも対応しています。 静的パーティショナーは、静的クックプリパス時にグループ化ロジックを実行します。 静的パーティショナーの入力は、すべての入力コネクションからのすべての静的ワークアイテムのリストになります。 静的パーティショナーに動的な入力ノードが含まれていても、そのノードがスキップされ、静的ワークアイテムのノードが見つかるまで上流を走査します。 動的パーティショナーは、すべての入力ノードがワークアイテムを生成した後でグループ化ロジックを評価します。 したがって、動的パーティショナーは、2レベル上のすべてのノードがクックされるまで待機した後で入力ワークアイテムをパーティション化しなければならないことになります。

独自のプロセッサ系ノードの登録で使用するものと同じPythonメソッドを使って、独自のパーティショナーノードを登録することができます。

アトリビュートによる分割

パーティショナーが入力ワークアイテムに対してonPartitionコールバックを実行する前に、PDGには、アトリビュート値に基づいてそれらのワークアイテムを分割するかどうかのオプションがあります。 パーティショナーに対して Split by Attribute パラメータが 有効 な時、PDGは、分割アトリビュートの固有な値毎に1回だけonPartitionメソッドをコールします。 このメソッドは、特定のアトリビュート値を持った入力ワークアイテムのリストを使ってコールされます。 PDGは、分割アトリビュートの値が異なるワークアイテムが同じパーティションに入らないように、これらのコールで生成されたパーティションが別個のインデックスを持つことを保証します。

その分割アトリビュートが見つからないワークアイテムは、どのパーティションにも追加しないようにしたり、または、すべてのパーティションに追加するようにすることができます。 この機能は、デフォルトでどのノードでも利用可能で、ノード作成者による余計な作業は不要です。 Python Partitionerまたはカスタムノードの Missing Attribute パラメータに対して適切なオプションを選択することで、あなた自身のコード内でそのアトリビュートが見つからなかった場合の処理を制御することもできます。 ワークアイテムを分割するための基本となるAPI関数は、Pythonからでも利用可能です。

アトリビュート分割オプションを 有効 にすると、onPartitionコールバックに渡されたpdg.PartitionHolder上でいくつかの追加プロパティを利用することができます。 例えば、ホルダーは分割アトリビュートの名前と現行値を用意することができます。 詳細は、そのクラスのAPIドキュメントを参照してください。

パーティショナーノードは、入力ワークアイテムのリストを1度ループして、アトリビュートで分割する際、または、そのアトリビュートが見つからないワークアイテムを検知する際に使用されるデータ構造を構築します。 これは、複数のTOPノードを使って同じ挙動を実装するよりも非常に効率的です。 しかも、固有な値の数がワークアイテムの総数よりも少ない場合は、このアトリビュート分割の機能がもっと上手く実行されます。 固有な値毎に別々にonPartitionコールバックが呼び出されるので、そのコールバック内で膨大な数のワークを処理するほどパフォーマンスコストが良くなります。 例えば、100,000個のワークアイテムと80,000個の固有なアトリビュート値があったと仮定すると、Partition Partitionerノードを使用して独自のロジックを記述するよりもパフォーマンスが良いです。

パーティション系アトリビュート

現在のところ、パーティショナー系ノードは、カスタムアトリビュートをパーティション上に追加することが できません 。 パーティションは、ノードの Advanced タブにあるパラメータに基づいて、そのパーティション内のワークアイテムからアトリビュートと出力ファイルを継承します。 Merge Input Attributes パラメータを 無効 にした場合、パーティションは何もアトリビュートを 継承しなくなります 。 しかし、そのパーティション内のワークアイテムからすべての出力ファイルはそのパーティション自身の出力リストにコピーされます。 このパラメータを 有効 にした場合、そのパーティション内のワークアイテムからアトリビュートがそのパーティションのアトリビュートにマージされます。 各パーティショナー系ノード(例えば、Python Partitioner)のドキュメントには、各パラメータの用途に関する詳細が載っています。

マージは、まず最初にパーティショナー系ノードのソート関連のパラメータに基づいてワークアイテムをソートすることから始まります。 次に、PDGは、そのソートされたワークアイテムをループさせて、各ワークアイテムからアトリビュート値をそのパーティションにコピーします。 そのパーティション上に既にそのアトリビュートが存在した場合は、そのアトリビュートは無視されます。 例えば、すべてのワークアイテムに同じアトリビュート名セットがあった場合、ソートされたリスト内の1番目のワークアイテムのアトリビュート値のみがそのパーティションにコピーされます。 ソートされたリスト内の2番目のワークアイテムのアトリビュートが1番目のワークアイテムになかった場合、そのアトリビュートもパーティションにコピーされます。 このマージ工程におけるソート順は、そのパーティション上の出力ファイルの順番も決めます。

ノードコールバック

パーティショナー系ノードには、上流ワークアイテムのリストを入力として受け取るコールバック関数の1つしかありません。 このコールバック関数では、パーティションオペレーションのステータスを示したpdg.result値を返す必要があります。

onPartition(self, partition_holder, work_items)pdg.result

このコールバックは、PDGグラフのクック中にパーティショナー毎に1回評価、または、( Split by Attribute有効 な場合)固有のアトリビュート値毎に1回評価されます。 パーティショナーが静的だった場合、このコールバックは静的プリパス時に実行されます。 動的だった場合、すべての入力ワークアイテムが生成された後にクック時に評価されます。 この関数のwork_items引数には、パーティションの対象となる上流ワークアイテムのリストを渡します。 partition_holder引数には、パーティションの作成で使用されるpdg.PartitionHolderクラスのインスタンスを渡します。

各パーティションは、onPartition関数から提供された固有の数値を使って定義されます。 ワークアイテムは、addItemToPartition関数にそのワークアイテム自身とパーティション番号を引数に渡すことでパーティションに追加されます:

# 各ワークアイテムを固有のパーティションに追加します。
partition_holder.addItemToPartition(work_items[0], 0)
partition_holder.addItemToPartition(work_items[1], 1)

# 両方のワークアイテムを3番目の共通パーティションに追加します。
partition_holder.addItemToPartition(work_items[0], 2)
partition_holder.addItemToPartition(work_items[1], 2)

ワークアイテムを複数のパーティションに追加したり、どのパーティションにも追加しないようにすることもできます。 場合によっては、作成されるパーティションの数がわかる前に、ワークアイテムをすべてのパーティションに追加したい事があります。 addItemToAllPartitionsメソッドは、そのワークアイテムがすべてのパーティション(そのコールの後で追加されたパーティションも含む)に属することをマークします。

他にも、ワークアイテムをそのパーティションで requirement(必須) としてマークすることもできます。 必須としてマークされたワークアイテムが削除されると、パーティション内にまだ他のワークアイテムが存在していても、そのパーティションもまるごと削除されます。 例えば、上流ワークアイテムのペアからパーティションを作成するPartition by Combinationがこの挙動に該当します。 ペアのどちらかのワークアイテムが削除されると、もはやペアではなくなるので、そのパーティションが無効になります。 以下のコードは、入力ワークアイテムの固有のペア毎にパーティションを形成するonPartition関数の実装例です:

partition_index=0

# ワークアイテムの外側ループ
for index1, item1 in enumerate(work_items):

    # ワークアイテムの内側ループ
    for index2, item2 in enumerate(work_items):

        # 順番はどうであれ、ワークアイテムのペア毎に1つだけパーティションを作成したいとします。
        # 以下のチェックがなかった場合、(a,b)と(b,a)の両方に対してパーティションが作成されてしまいます。
        if index2 <= index1:
            continue

        # 次で利用可能なパーティションに両方のワークアイテムを追加し、それらのワークアイテムをrequired(必須)としてフラグを立てます。
        partition_holder.addItemToPartition(item1, partition_index, True)
        partition_holder.addItemToPartition(item2, partition_index, True)

        partition_index += 1

PDG/TOPsを使ってタスクを実行する方法

基本

初心者向けチュートリアル

次のステップ

リファレンス

  • すべてのTOPsノード

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

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

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

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

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

  • スケジューラ系ノードコールバック

    スケジューラ系ノードはワークアイテムを実行します。

  • 独自のファイルタグとハンドラー

    PDGはファイルタグを使用して出力ファイルのタイプを決めます。

  • Python API

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

  • Job API

    ジョブスクリプトで使用するPython API

  • ユーティリティAPI

    Python pdgutilsパッケージのクラスと関数は、PDGノードでの使用だけでなく、スクリプトやプロセス外のジョブスクリプトでの使用も想定されています。