こちらは、以前(2021/01/10)に別サービスで展開した内容を Qiita に移行したものです。
はじめに
PyTorch を使った Houdini ノードの作成方法に関しては試したことがなかったので、それをテストしたので、そのまとめを書いておく。
開発環境
Windows 10
Houdini 18.5.460
PyTorch 1.7.1 CUDA 11
Visual Studio 2017
サンプルコード
準備
LibTorch をダウンロード
Houdini のノードとして C++ での実装をするにあたって、LibTorch(PyTorch C++ Distribution) を使用する。
PyTorch のサイトにて、適切なバージョンをダウンロード。
そして任意のディレクトリに展開して配置しておく。
ここで注意すべきなのが、LibTorch は Rlease/Debug ビルド用のライブラリがそれぞれ別々になっている(NOT ABI-compatible)。なので、ビルドソリューションによって切り替える事。
CMake
基本的な CMake は次のファイルで行う。
cmake_minimum_required( VERSION 3.6 )
project( PyTorchTest )
# CMAKE_PREFIX_PATH は、Houdiniインストールパスの
# toolkit/cmakeのサブディレクトリパスを含める。
# 詳しくは、HDKドキュメントの"Compiling with CMake"セクションを参照。
list( APPEND CMAKE_PREFIX_PATH "$ENV{HFS}/toolkit/cmake" )
# HoudiniライブラリとLibTorchライブラリのヘッダーファイルがある場所を指定。
# そして、インポートしたライブラリをHoudiniとTorchとしてターゲットを命名。
find_package( Houdini REQUIRED )
find_package( Torch REQUIRED )
set( library_name SOP_PyTorchTest )
# LibTorch用にフラッグを受け取れる様に追記。
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}" )
# 埋め込み型DSファイルをSOP_PyTorchTest.Cの中に生成.
# この関数は、HoudiniConifg.cmake内に定義。
houdini_generate_proto_headers( FILES SOP_PyTorchTest.C )
# ソースファイルを追加。
add_library( ${library_name} SHARED
SOP_PyTorchTest.C
SOP_PyTorchTest.h
)
# HoudiniライブラリとLibTorchへのライブラリをライブラリネームとしてリンク。
# また、必要インクルードディレクトリとコンパイル定義を追加。
target_link_libraries( ${library_name} Houdini "${TORCH_LIBRARIES}")
set_property(TARGET ${library_name} PROPERTY CXX_STANDARD 14)
# Include ${CMAKE_CURRENT_BINARY_DIR} for the generated header.
target_include_directories( ${library_name} PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
)
# ライブラリの出力ディレクトリ(デフォルトでは、
# `C:\Users\<username>\Documents\houdini<version>\dso`)など、
# いくつかの共通ターゲットプロパティを設定。
# この関数は、HoudiniConifg.cmake内に定義。
houdini_configure_target( ${library_name} )
# Visual Studioでのビルドの場合に有効
# ポストビルドコマンドとして、リンクされたファイルを
# ビルドターゲットディレクトリにコピーする。
# コピー前にはbinディレクトリを追加し、LibTorch関連はそちらにコピー
if (MSVC)
set(binary_dir $<TARGET_FILE_DIR:${library_name}>/../bin)
add_custom_command(TARGET ${library_name}
COMMAND ${CMAKE_COMMAND} -E make_directory
${binary_dir})
file(GLOB TORCH_DLLS "${TORCH_INSTALL_PREFIX}/lib/*.dll")
add_custom_command(TARGET ${library_name}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${TORCH_DLLS}
${binary_dir})
endif (MSVC)
テスト用のコード編集
今回は、SOP_Star のサンプルソースをもとにテストした。
テストするにあたって、次の項目を書き換えた。
#include <torch/torch.h>
// ~ 省略 ~
// ノードがクックされた際の処理
void
SOP_PyTorchTestVerb::cook(const SOP_NodeVerb::CookParms &cookparms) const
{
// ~ 省略 ~
torch::Tensor tensor = torch::rand({2, 3});
std::cout << tensor << std::endl;
// ~ 省略 ~
}
ビルド
Command Line Tools を起動して、作業ディレクトリに移動する。
Command Line Tools を用いなくてもいいが、各種環境設定などなどが面倒なので、おとなしくそれを使った方が吉。
mkdir build
cd build
cmake .. -G "Visual Studio 15 2017 Win64" -DCMAKE_PREFIX_PATH=\path\to\torchlib
そしてビルド。
cmake --buld . --config Release
この時点でエラーが出る場合、以下のトラブルシュートの欄を参照。
場合によっては、Visual Studio を起動してから、各種問題を解決してからビルドすると良い。
Houdini上でテスト
始めに bin ディレクトリに対し、set PATH=\path\to\bin
(デフォルトでは、C:\Users\<username>\Documents\houdini18.5
以下)と環境変数をセットする。
Houdini を起動し、/obj/geo1 と作成し、ノードを作成してみる。
次の様に出力されればビルド成功。
トラブルシュート
以下、ビルドしていた際に起きたトラブルで対処したもの。
C2061: Syntax Error: identifier 'IValue'
原因
libtorch\include\ATen/core/ivalue.hの中のIValue
の前の行にある Doxygen 用の部分がうまく機能しておらず、それがVisual Studio のコンパイラに引っかかっている。
解決方法
エラーが起きてる以下の箇所を削除。
使う側としては、Doxygen でドキュメント化するわけでもないので、削除対応を選択した。
/// \cond DOXYGEN_CANNOT_HANDLE_CONSTRUCTORS_WITH_MACROS_SO_EXCLUDE_THIS_LINE_FROM_DOXYGEN
C10_DEPRECATED_MESSAGE("IValues based on std::unordered_map<K, V> are slow and deprecated. Please use c10::Dict<K, V> instead.")
/// \endcond
LINK : fatal error LNK1104: cannot open file 'torch-NOTFOUND.obj'
原因
ビルドソリューション用のライブラリを選択ミスしている。
このエラーの場合は、Release ビルド用のライブラリをダウンロードしてきて参照しているが、この torch-NOTFOUND.obj ファイルが含まれるのは Debug ビルド用のもの。
解決方法
適切(Release ビルド用ライブラリ)なビルド用ライブラリをダウンロードしてきて使用する。
C2872: "std":ambiguous symbol エラー (Release)
原因
Conformance mode
が Yes
になっている。
Visual Studio 2017 以降で追加されたもので、非標準の C++ 構文は認めないというものとのこと。LibTorch 側がこれに引っかかるので、ここはどうしようもないので切り替える事で対応。強制的に No
にする方法ない…??
解決方法
Conformance mode
を No
に設定する。
C2872: "std":ambiguous symbol エラー (Debug)
Debug でビルドしようとすると、上記解決策を試してみても修正されずにエラーが出続ける状態が続いく。
原因
各コード中の std が指定ビルドバージョンの構文に会っていないため。
解決方法
std
となっているところをすべて ::std
と書き換える。
LibTorchのdllが、Houdiniのバージョン認識にひっかかる
デフォルトの起動だとエラーも何も出力されず、ノードを Tab 検索しても出てこなかったりして、この問題に気づかないことが多い。そういった原因がわからない場合、とりあえず、set HOUIDNI_DSO_ERROR=1
と環境変数をセットして、DSO 関連のエラーをすべて表示するようにする。
具体的には次のエラーが起きていた。
原因
dso ディレクトリ以下には、Houdini が Houdini のプラグインとして認識するもののみを置くべきで、そこにサードパーティのものがあるがゆえに、Houdini のバージョン識別の処理が走った際に、その情報が取得できずに弾かれるという問題。
解決方法
サードパーティの dll 等は dso ディレクトリ以下に置かず、bin などをのディレクトリを別途つくってそこに配置。set PATH=\path\to\bin
として設定することで解決できる。
こちらは、CMake 側で、ディレクトリを作成。そちらに LibTorch 関連のバイナリをコピーする仕組みにすることで対応。
bin ディレクトリが作成できない
LibTorch 関連のファイルを独自の bin ディレクトリにコピーしたいが、bin ディレクトリが存在しないとエラーで止まる。
原因
存在しないディレクトリにコピー処理をしようとしても、ディレクトリ自体を作る機能がコピーコマンドに存在しないので、予め作る必要がある。
解決方法
ビルド時のコピー前にフォルダを作る処理を入れる。
if (MSVC)
set(binary_dir $<TARGET_FILE_DIR:${library_name}>/../bin)
add_custom_command(TARGET ${library_name}
COMMAND ${CMAKE_COMMAND} -E make_directory
${binary_dir})
file(GLOB TORCH_DLLS "${TORCH_INSTALL_PREFIX}/lib/*.dll")
add_custom_command(TARGET ${library_name}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${TORCH_DLLS}
${binary_dir})
endif (MSVC)
最後に
こうして、とりあえず外部ライブラリの LibTorch を取り込むことができるので、これをベースに色々 Houdini の PyTorch を使った機械学習ノードを作っていけると思う。