LoginSignup
1
0

More than 1 year has passed since last update.

PyTorchを使ったHoudiniノードを作る <C++/HDK>

Last updated at Posted at 2021-12-15

こちらは、以前(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)。なので、ビルドソリューションによって切り替える事。

xx97fd2j5i843sm9m2m09nr5hazq.png

CMake

基本的な CMake は次のファイルで行う。

CMakeLists.txt
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 のサンプルソースをもとにテストした。
テストするにあたって、次の項目を書き換えた。

SOP_PyTorchTest.C
#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 と作成し、ノードを作成してみる。
次の様に出力されればビルド成功。

tc3q03xsenpyz5aw0hyrq59aibqa.png

トラブルシュート

以下、ビルドしていた際に起きたトラブルで対処したもの。

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)

ovbdq2xhpkswj5562tjoctoiw0ec.png

原因

Conformance modeYes になっている。
Visual Studio 2017 以降で追加されたもので、非標準の C++ 構文は認めないというものとのこと。LibTorch 側がこれに引っかかるので、ここはどうしようもないので切り替える事で対応。強制的に No にする方法ない…??

解決方法

Conformance modeNo に設定する。

4pfnq9tqjwtzfj18k0nhhaxl9gzd.png


C2872: "std":ambiguous symbol エラー (Debug)

Debug でビルドしようとすると、上記解決策を試してみても修正されずにエラーが出続ける状態が続いく。

原因

各コード中の std が指定ビルドバージョンの構文に会っていないため。

解決方法

std となっているところをすべて ::std と書き換える。


LibTorchのdllが、Houdiniのバージョン認識にひっかかる

デフォルトの起動だとエラーも何も出力されず、ノードを Tab 検索しても出てこなかったりして、この問題に気づかないことが多い。そういった原因がわからない場合、とりあえず、`set HOUIDNI_DSO_ERROR=1` と環境変数をセットして、DSO 関連のエラーをすべて表示するようにする。

具体的には次のエラーが起きていた。

im8se45h15xg02sc9gv4figojzhy.png

原因

dso ディレクトリ以下には、Houdini が Houdini のプラグインとして認識するもののみを置くべきで、そこにサードパーティのものがあるがゆえに、Houdini のバージョン識別の処理が走った際に、その情報が取得できずに弾かれるという問題。

解決方法

サードパーティの dll 等は dso ディレクトリ以下に置かず、bin などをのディレクトリを別途つくってそこに配置。set PATH=\path\to\bin として設定することで解決できる。

こちらは、CMake 側で、ディレクトリを作成。そちらに LibTorch 関連のバイナリをコピーする仕組みにすることで対応。


bin ディレクトリが作成できない

LibTorch 関連のファイルを独自の bin ディレクトリにコピーしたいが、bin ディレクトリが存在しないとエラーで止まる。

原因

存在しないディレクトリにコピー処理をしようとしても、ディレクトリ自体を作る機能がコピーコマンドに存在しないので、予め作る必要がある。

解決方法

ビルド時のコピー前にフォルダを作る処理を入れる。

CMakeLists.txt
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 を使った機械学習ノードを作っていけると思う。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0