メインコンテンツまでスキップ

Out-Of-Processの基本を理解する(1)

前回、 で In-Process での使用方法を書きましたが
今回は Out-Of-Process を使用した場合についてを調べていきます。
Out-Of-Process は、WorkItem や Scheduler などにも大きく関係する+ Houdini の処理の作り方も
In-Process とは違い注意しなければいけないポイントがそこそこそあるので
それぞれの要素を順に確認していきます。

Out-Of-Process とは

そもそも Out-Of-Process はどういうものかというと、
その名の通り 実行する処理を、Houdini のプロセス外で実行することを言います。 完全に別プロセスになるので、Out-Of-Process で実行した場合は
実行している処理から現在開いている HIP のシーンの値は取れないし、実行もできません。

まず、シンプルな例として PythonScript を Out-Of-Process で実行してみます。

PythonScript ノードを作り、

EvaluateScriptDuring を「 Cook (Out-of-Process)」に変更します。
そして、Python Executable で、実行する Python の実行ファイルを指定します。
今回の例の場合、 py コマンドを使用して指定バージョン(Python310)を実行できるようにします。

Python Code に書いた内容を実行するのですが、この PythonCode は
Houdini の世界ではなく、Python310 の世界で実行されるコードです。
なので、

import hou
print(hou.pwd())

このように、現在のノードを hou.pwd で取得しようとしても

そもそも通常の Python なので、hou モジュールのインポートもできませんので
現在の Houdini のノードにアクセスはできません。

WorkItem

この Python を実行するときには、

WorkItem は使用することができますが、よくみると pdgjson.WorkItem となっていることがわかります。

In-Process の場合は、 pdg.WorkItem となっていて、オブジェクトのモジュールも
違っていることがわかります。

https://www.sidefx.com/ja/docs/houdini/tops/jobapi.html

この Out-of-Process で使用できる WorkItem は、JobAPI と呼ばれる、InProcess などで使用する
hou モジュールとは独立したライブラリになっています。

このライブラリは、TempDir に保存された、WorkItem の実行に必要な情報をまとめた JSON から
WorkItem オブジェクトを作成し、それらにアクセスする機能を提供してくれます。

例えば、AttributeCreate で

WorkItem に対してアトリビュートを追加します。

print(work_item.attrib("sample").value())

Out-of-Process な Python で、WorkItem の値を受け取るにはこのようにします。
通常の pdg.WorkItem と同じように扱うことができました。

TempDir

Out-of-Process は Houdini 外での実行になっているわけですが
外部で処理を実行するときに、どのようにして WorkItem の情報や それ以外の必要なデータを
実行するプロセスに対して受け渡す必要があります。

この、外部プロセスに対して必要な各種情報やデータなどを一時的に保存しておく場所が
この TempDir です。

この TempDir は、デフォルトの場合は LocalScheduler に設定する項目があります。 デフォルトは HoudiniTemp になっているので、これを任意のディレクトリに変更しておきます。

TempDirectory を変更した状態で、ジョブを実行すると、以下のように指定ディレクトリに数字フォルダが作られ
その下に data logs scripts というサブフォルダが作成されます。
これらのディレクトリは、PDG のスケジューラー(次回詳しく説明します)がデフォルトで定義している
共通のディレクトリで、それぞれ意味を持っています。

log はその名の通り、各プロセスのログを保存するディレクトリです。

scripts ディレクトリは、

PDG のノード次第で若干構成は変わりますが、WorkItem を実行するのに必要なスクリプトが
WorkItem のジョブが実行される前に、このフォルダ以下にすべてコピーされ
このフォルダに PATH が通った状態になってから PythonScript を実行します。

data ディレクトリは、

WorkItem を JSON にダンプしたファイルが置いてあります。
このファイル 1 つが、WorkItem 1つと一致していて、WorkItem のアトリビュートや
PythonScript で実行するスクリプトなど、ジョブを実行するのに必要な情報が
まとめられています。

import sys
sys.path.append('D:/pdgtemp/11828/scripts')

from pdgjson import WorkItem

work_item = WorkItem.fromFile("D:/pdgtemp/11828/data/pythonscript1_3.json.gz")

print(work_item.command)
print(work_item.attribValues())

試しに、Sript に PATH を通し、JSON をロードしてみます。
Hython ではなく素の Python であっても、実行できていることがわかります。

import base64

script = base64.b64decode(work_item.customData)
print(script.decode("utf-8"))

# 実行
exec(script)

PythonScript ノードに書かれたコード本体も、JSON に含まれているので
customData からスクリプトを取得することができます。

まとめ

長くなってきたので、いったんここまでを整理します。

Out-of-Process は、PDG の処理を現在起動している Houdini 外で実行すること。
外部プロセスなので、HIP の情報などは参照することができず、WorkItem を経由して
必要な情報は受け渡します。
それらのジョブを実行するのに必要な WorkItem の情報や、各種ライブラリなどは
TempDirectory で指定したフォルダ以下に、指定の構造で保存されます。

この辺りを抑えつつ、次回から各要素をもうすこし深堀しながらまとめていきます。