PyMel

使われてるコードを見ていて気付いたこと。

 とりあえず、名前を変えるような操作を伴う場合にいちいち関連するノード(基本的には、shapeとその親のtransform)の名称の変化を気にしたコーディングの必要がなさそう。
 一旦PyMel Objectを取得すると、Objectがノードを示す一意のデータになるので、名称の変化を気にしないでよかった。

 これはたぶんOpenMayaでもPyMelと同じなんだろう。(試してないけど、オブジェクトを作って、それでノードを操作するものなので。)
 しかし、Python+Maya.cmdsで書いていると名前ベースになってしまうので、renameすると途端にデータを見失いまくる…この辺は非常にめんどくさいと思った。

 こんな感じに書くと、シェイプのリネームに失敗することになる。

 OpenMayaのようにノードをオブジェクト管理している環境の方が、リネーム絡みの処理は楽かと。 (OpenMayaの手続きに慣れる必要はあるけど。)

時間をおいて眺めたら、なんでmaya.cmdsでわざわざrenameしているのか。いや、そもそもなんでshapeを先に取得しているのか…とか疑問のわくコードではある。
単に、元がmaya.cmdsベースのコードにOpenMayaを付け足してたり、途中の処理をバッサリ削除してメモとして仕立てたせいなんだけど…どっちにしろ名前ベースで処理中にrenameしたらいろいろ不味いことが起こる。
OpenMayaだと、ざっくりこんな感じ?(完全にサンプル実装だけど…)

DirectX12のマルチGPU

 OpenCLとかRadeonのCrossFireばかり気にしていたけど、DirectX12のマルチGPUの機能が思ったより凄いかも。
 RX580で2万くらいの出物があったので、手元のRyzen2700X+RX570とセットでTimeSpy(futuremarkのベンチマーク)を試してみた。

 スコアはTotal:7726, Graphic: 7600(Test1:51.58, Test2:42.11), CPU:8534だった。
 ググってみると Ryzen1600X+RX580でTotal:4156というのを見つけたので、どうやらマルチGPUでそこそこ性能が出るというのは嘘じゃなかった。

 しかもDirectX12のEMAという機能は異機種混合を可能にするらしくて、単なるモデル違いだけでなくメーカー違いもサポートする模様。またGTX970x2ではSLI接続より効果が上がったという結果も見つけたので、そもそも技術的にかなり最近のGPUのレンダリング パイプラインを効率化する方法を導き出したということのような気がする。

 …のだが、そんなに凄いという噂を目にしなかったのは、単にそちら方面にアンテナ伸ばしてなかったからなのか、それともじつはそこまでの効果が出ることが稀なだけなのか。

 実のところ、そこら辺がよく判らないでいる。

その後

 DiRT Rallyを動かしてみたら、RX570単体が平均で60fps前後 ⇒ RX580+570では100fps超になっていた。1.6~1.7倍ほど処理が増大した。そもそも、RX570⇒RX580で12,13%早くなってるというのもあるけど、かなり上乗せされてる感じがする。
 DX11のゲームなので、DX12ネイティブなゲームだともっと上乗せされるのかしら。

で、結局OpenCLとは何か?

 それには、「“GPGPU”についてググりなさい。」というのが答えかもしれない。終わり。

 …。
 大雑把には、ベクトル演算ユニットの活用手段のひとつであり応用技術。そのライブラリ。
 名前からも推測できるが、OpenGLを踏襲した仕様体系。手続き的な部分が似ているので、OpenGLを使ったことがあれば、なんとなく使い方が見える感じ。

GPGPUって?

 知るには、まずここからかも。
 「GPGPU(General-purpose computing on graphics processing units; GPUによる汎用計算)とは、GPUの演算資源を画像処理以外の目的に応用する技術のことである」wikiより。
 要するに、最新グラボに搭載されている3DCG系の演算ユニットを汎用的な計算に活用する為の技術体系が、GPGPUと呼ばれている。
 用語的には、ベクトル演算ユニットとGPU(グラボに乗っている計算機)は別物で、コンピュータに直で乗っているのがベクトル演算ユニットで、GPUはそれとは別物。という扱いだけど、これは単純にグラボが専用のメモリを積んでいて、GPUはグラボに積んだメモリしか直接アクセスできない。というのが理由。コンピュータに乗ったメモリにはグラボからはアクセスできないので、グラボはコンピュータにデータを送って貰わないと何も計算できない。また計算結果もコンピュータに読み取って貰わないといけないので、ひと手間掛かる。
 その代わり、GPUはグラボ内のメモリに高速かつ(GPU搭載の複数の計算機による)大量のアクセスができるので、単純な計算を超高速に実行できる。
 単位時間当たりの計算速度はCPUを遥かに超えてきているので、そこに価値ができている。

 ただし、GPUにはいくつかの点でCPUに劣る面があり、計算可能な範囲がCPUに比べると制限を受ける傾向がある。

 長所:メモリにシーケンシャルにアクセスし、かつ条件分岐の無い計算(演算密度の高い処理)に強い。
 短所:条件分岐だらけ、メモリにランダムアクセスが発生する計算は大の苦手。

 また、GPUにより単精度浮動小数点しか対応していなかったり、メモリもCPUほど大きなサイズを持っていない点も短所に挙げられる。

で、結局OpenCLって?

 専用の記述式で計算処理(Kernel:カーネル)を書き、専用の初期化・実行処理で計算処理を実行させる為の環境がOpenCL。
 OpenCLドライバが用意されたGPUと対応するSDKを用意すれば、あとはプログラムを書くだけ。

 (参考)C++でOpenCL(使ってみよう編)

 CPUのような汎用的な処理は苦手だけど、計算処理を一気に処理することに特化した性能を持っているので、画像処理や3次元計算にはとても有用。

Auth0 試してみた。

 “Auth0”がなにか?というと「認証サービス」というもの。

 そもそも、一般に存在しているいろいろなサイトの中には認証処理が一般に公開された状態になっているものがある。Googleだったり開発系だとGithubだったり。
 そういうところにアカウントを持っている場合に、いちいち他のサイトで認証する時にサイトごとにユーザー名やパスワードを用意するのって億劫なわけです。
 なので、サイトによっては一般の認証システムを使って自サイトへのサインインを完了させる機能を用意していたりする。そういうサイトは、そのサイト用のユーザー名やパスワードを特別に作らなくても、Googleアカウントとかでサインインしてサイトのサービスを利用できるようになる。
 でもそういうサービスを提供するにも、認証システムを旨いこと実装してあげないといけないのでいろいろ大変です。

 単純に言えばAuth0はそういう認証処理を一元化して管理できる場(プラットフォーム)を用意しました~って感じのサービス。(このへん読むといろいろわかるかも⇒認証プラットフォーム Auth0 とは?

 WordPressのプラグインに“Auth0”って、そのまんまの名前のプラグインがあったので、利用してみた。

 基本的には、Auth0で自分のアカウント(テナントID)を作って、WordpressのプラグインにそのIDとあとアクセス用のTokenを作って渡してあげればいい感じ。
 Tokenは、Auth0のDashboardからAPI項目を選択。APIがなかったら作成(たぶん1つは作られてる?)して、その中のAPI Explorer項目を選択。そこにTokenが出てくる。(これも、なかったら作成。確かデフォルトでは作成されてない。)

 あと、Wordpress側のダッシュボード > 設定 > 一般 > メンバーシップ のチェックが入っていないと、初回サインイン時にユーザーが作成できない旨のエラーが出るので、はじめてAuth0でサインインする時は必ずチェックを入れておくこと。

[OpenCL] 少し動かしてみたけど、結構情報が当て嵌まらない

 なんだろう? AMD環境って、今OpenCLのメインストリームじゃないのかな?
 検索して出てくる情報は、Intel系…というかMacの情報が多くて、そもそもうちの環境だとCPUがデバイスとして列挙されないんだけど…どゆこと??って感じになっている。

 とりあえず、下記のサイトとかでサンプル拝借しながらdeviceinfoを集めるところからやっているけど、自分で何とかしていかないと試しに人に倣って試してみる、という訳にはいかないかなぁ。

 ちなみに、参考のサンプルはWindowsで動かすと足りないものがあったりするので、処理を省くか、なんとか処理を補完しないと動かせなかった。。

参考

Dakkers/OpenCL-examples
tzutalin/clDeviceQuery.cpp
OpenCLに対応するデバイスの列挙(C言語・Mathematica)

その後

C++からOpenCLをラクに使うためにライブラリを書いてみた

 これも、うちの環境と違う。
 どうやらうちの環境だと、ユニファイドメモリをサポートしてないっぽい…(この方が言うには、「サポートしていないハードがないので動作未確認」とな。そんなに珍しい環境なのかしら?)

ClPyって??

 ClPy(シーエルパイ)なるものを見つけたので、メモ。

 「CuPyをOpenCLで動かすフレームワーク」なんだそうで…CUDA諦めてOpenCL勉強しようとしたら、これだもんなぁ、、
 とりあえず、忘れないようにメモっておく。

 CuPyをOpenCLで動かすフレームワーク ClPy を先行リリースしました

AMD APP SDKが見当たらない…

めも。

 CUDAが環境的にナニだったので、OpenCL調べてみるか…と思ったのだが、調べていくとAMD APP SDKが必要…みたいな話になってきたので、AMDでSDKをDLしなきゃーって思ったのだが、何故だか見当たらない始末。

 理由は不明だが、2018.12.2現在公開されている気配がない。

 で、こんな書き込みを見つけた。
 OpenCL SDK

 どうもここからもらってくる感じになってるみたい。
 AMDのドライバ(Radeonドライバとか)にはそもそもランタイムとしてOpenCLが含まれているらしく、とりあえずそこに置いてある include, libファイルでビルドすれば動くっぽい。

 参考サイト①にあるデバイス確認のコードで、実際に動くことも確認できた。

参考

C++でOpenCL(環境構築編)
SDKなしでOpenCLを使ってみる -導入編-
Khronos OpenCL Registry(仕様策定をしている団体のページ)
公式のリファレンス

Maya2018に最近傍点探索モジュールを入れる

Python単体で近傍頂点探索(数万頂点規模)は、ちょっとキツかった。

めも。(入れたモジュールは、nmslib。最初CPythonでAnnoyを使ってみて、これでいいやと思った。しかしMaya2018へのpipインストールができそうになかったのでpipインストールが容易なこちらを選択。)

事前に、numpyとVisualC++ Build Tools(V14.0)のインストールが必要。(既にVisualStudio2015を入れているなら、VisualC++ Build Toolsは不要)

・get-pip.pyをダウンロードして、mayapy.exeと同じ場所に配置。
・コマンドプロンプトを管理者権限で起動。mayapy.exeの場所をカレントディレクトリにして、以下を実行。

・pipの配置場所をカレントディレクトリにして、以下を実行。

・VisualC++ Build Toolsをダウンロードしてインストールする。(CMake for Windowsを入れてなければ、そっちも。)
・VisualC++ Build Tools > Visual C++ 2015 x64 Native Build Tools Command Prompt を管理者権限で起動して、以下を実行。

という感じだった。

参考

近似最近傍探索ライブラリ比較
AutodeskMAYAにpip, numpy をインストールする方法
[GUIDE] How to install numpy+scipy in Maya Windows 64 bit?
【python】ライブラリインストール時に「error: Microsoft Visual C++ 14.0 is required.」エラーが発生

その後

 仕事では、結局Pythonのみでなんとかすべし。という指令が下り、頑張ってなんとか初期段階から50倍以上の高速化ができて、C++記述のプラグインと通常利用で遜色ないところまで早くなったとさ…(いろいろ問題は抱えてるんだけども、通常利用で噴出しないところに収められた感じなので、良しとした。)
 でもモジュール利用ができるなら、間違いなく実現までの工数をすっ飛ばせていたので、使えるものなら使えばいいんじゃないかと。(今回の仕事では使えなかっただけ)

プログラム言語習得に関して

 プログラム言語の習得に関しては、理数系・文系を問わず可能です。
 しかし、アプローチのスタンスが異なるので、特に文系思考(正しくは、論理的思考よりも感覚的な経験が基準になっている思考方法)の場合には習得に困難さを感じがちです。

 そもそもプログラム言語の取得に関しては、理数系の思考をする人の方が圧倒的に有利です。これは、プログラム言語が理数系の人の考え方を元に設計されたものである以上、仕方がないと言えます。逆に自然言語(日本語や英語など、会話に用いられる一般な言語)に関しては、論理的思考よりも感覚的な面が反映されやすいので、感覚的な経験を元にする文系思考の人のほうが馴染みが早いのです。
 従って、学習に有効なアプローチも異なります。

 もし理数系が得意という人は、一般に流通しているプログラム言語の入門書を読めば大体の理屈が飲み込めるので、そのままプログラム言語を書けるようになるでしょう。
 問題は、文系思考の場合です。基本文系でもある程度すんなり理数系を理解する論理的思考を持つ人であれば、純粋な理数系の人に準じて、それなりにプログラム言語を書けるようになります。しかし、純粋に文系思考で、経験的に物事を把握していくタイプの場合、捉え方が異なるので思うようにプログラム言語の習得が出来ない…という状況に陥ることは多く見受けられます。

 必要なのは、ひとえに経験になります。
 経験から状況に応じた方法を理解するタイプだと、どうしても解るまで続けるしか手段を持っていないので、理論が先行するような情報の解釈に時間が掛かるのです。なかなか腑に落ちない、と言い換えても良いかもしれません。
 ですので、習得の為には腑に落ちるまでプログラムを動かして、ひたすら挙動を知る。ということが、必要になります。

 理数系の人でも頭の中でやっている事はそんなに変わらないのですが、今までに習得した理屈と同じものを頭の引き出しから取り出して理解することを行うので、腑に落ちるのにそんなに時間が掛からないことが多いだけです。知らない分野ならむしろ理数系の人の方が時間が掛かったりします。ただし、一度学習が終わるとその後に必要な時間は圧倒的に短縮されますが。

 
 ただ「動かして覚える」場合、入門書に記述されているサンプルのパターンが少ないという問題に直面します。というのも、基本的な入門書の内容として「PCの動作を理解する」ということが語りたいことなので、動作の基本になるパターンを前提に書いています。実行時に問題が起こるパターンを網羅するようなものではなく、あくまでも一例として基本動作を挙げているだけです。
 文系思考の強い人の場合は、この点も敷居の高さを感じる部分かもしれません。応用しようにも、動作の切り分けが意識できていない場合には、ある機能がどういった機能で成り立っているのかまで詳細に理解出来ていない場合が多く、機能を1つのブラックボックスとして捉えたまま利用してしまうことからなかなか抜け出せない場合があります。
 理数系タイプの人だと、必要に応じて機能を細分化して捉え直すことを行いますが、これが出来るのは「PCの動作を理解する」のと同様に、それがどういった形で成り立っていうのか、構成もある程度理解して捉えようとする面があるからです。

 では、文系思考の強い人がプログラム言語習得を行うにはどうしたら良いのでしょうか?
 先にも書きましたが、経験を積む必要があります。
 理数系の人が行っているような「機能の構成を捉える」という部分についてです。

 つまり文系思考の人の勉強のステップとしては、とても大きくは2つのステップを意識的に行う必要があります。

 ・動くプログラムを用意して、「プログラムの動作を理解する」ステップ
 ・更にプログラムの利用する機能について、「PCの動作を理解する」ステップ

 実のところ、これは理数系の人も同じことをしています。理数系の人は、説明をするまでもなく自然にそれを行ってしまうだけです。そもそも、PCやソフトウェアの動作を知ることが好きだったり、作ることや動くのを楽しんでやっているだけなので、勉強しているという意識もなく自然に実践している…というのが実態だと思います。

 文系思考の場合は、なかなかそういうわけにもいかない部分があります。スタート時点での不利は否めませんが、判り始めるとその状況も変わってくるので、「何故プログラム言語を習得しようとしているのか」という初志を忘れないで取り組む事が必要になると思います。
 「自分だけのソフトを作りたい。」「もっと自分好みの機能が欲しい。」などの目的意識があるなら、学ぶのに必要な苦労とのトレードオフだと思います。

 ただ最初は勉強になるので、経験として身に付くまでなるべく間を開けずに継続的に取り組む必要があります。
 この手の技術というのは使わなくなると意外と簡単に忘れてしまうのですが、一度身に付けば再学習は前のように時間を取られることはなくなるので、まず一度身に付くまで継続するくらいの頑張りが大事です。

関連記事

 プログラミングは難しいか?
 プログラムを作れるようになるには
 プログラムは誰にでも書ける

Qt.py 便利だ…

 前の記事(PySideのノード描画ライブラリ)で Python3&PySide2対応させたけれども、やっぱりPython&PySide環境でも利用するには…と思い始めてしまったので、とりあえず気になっていたQt.pyを試してみた。

 感想としては、「やっぱり便利だ…。」という感じ。
 実質PySide2に書き換えたコードのimport文の指し先を、PySide2からQtに変えただけで特に問題なく動いてしまった。
 PySideで作られたコードの場合は、PySide2相当の記述に変えないといけないのかもしれないけど、一旦PySide2で作ったらimport文以外変更なしでいけそうな気配。

 PySide2になってちょこちょこ引数のとり方も変わってるので、まったくPySide2対応していない場合にそれを今更直すのは面倒だけど、新しく書いたコードを古い環境に適用させないといけない可能性が有るなら便利かと思う。(古い環境にもQt.pyがあれば、コード変更要らずなわけで。)

参考

Qt.pyでPySideとPySide2を共通コードで使う

PySideのノード描画ライブラリ

最近よく見掛けるようになった気のする、ノードグラフ表示。
どこかにライブラリが転がってないかな…と探していたら、PySideで描画してみたよ。っていうライブラリがあった。
描画させてみた。という感じの機能なので、ツール化しようとするといろいろ足りなくて大変だと思うけど、そのぶん小規模なのでノードを描画をさせる際の参考になりそう。

Python3 & PySide2には対応してないコードなので、そっちの環境で動かすには、まずバージョン差異で動かない部分を修正する必要もあり。

cb109/qtnodes

コードをちょっと手直しして、こんな感じに出してみた。(勉強ついでに、PySide2 & Python3で動くようにしてみたけど、やっぱノード名称のラベル(ノードの型名じゃないやつ)が欲しいですね)

その後ラベル付けたら、こんな感じになった。基本的に構造を表示させる目的のものなので、そういう機能はないんだけど…これで簡単なノードプログラミング環境を作ろうとすると、アトリビュートエディタみたいな値編集機能や、ノードの持つ値や接続を辿って取得する機能も必要ですね。考えるとちょっと楽しくなってきた。

他には、こんなのもあった。

>pyQt4 or pyQt5 or pySide or pySide2で動くというもの。こっちは先のものよりも随分と実用的な感じ。
LeGoffLoic/Nodz

>PySide2ベースのオサレUI
jchanvfx/NodeGraphQT

>Qt5ベース C++記述のもの。そこそこ良さそう。
paceholder/nodeeditor

>D言語で書いて、C++にしたもの。Qt5版と断っているのとそうでないものがあるので、断ってないのはQt4系かな?
QNodesEditor – Qt nodes/ports-based data processing flow editor

>Maya用のノードエディタ。ICE的な感じ?(PySide2専用っぽい)
Qt node editor 1.0.0 for Maya (maya script)
IlgarLunin/PyFlow

>実行ファイルやコードとか見当たらないけど、見た目重視にするとこんな感じなのかな、ちょっと凝り過ぎな気もするけど。
PyQt4 Node Editor

>C++14ベースのノードエディタ。「ブループリントのエディタみたいなやつ」と書かれているimgui系統。使い易さは判らないけど、これもオサレUI。
thedmd/imgui-node-editor

ちなみに、最近のMayaのノードエディタのノードのスタイルはめっちゃオーソドックスな感じ。

Yetiのストランドの置いてきぼりを検出

そういう事例があって、調べた結果のメモ。

 Groomノードはストランドの情報をノード内部に記録していて、ストランドの初期位置などは内部情報なのでそこを基準に検出するには対象meshに対してのストランドの追従計算方法が判らないと厳密に計算出来そうになかった。

 これはリーダーから助言戴いたことなので自分の調べた内容ではないが、Groomノードのバウンディングボックスを調べることで検出できそうなことが判った。
 というのが、一部のストランドが置いてきぼりになるということは、対象を動かすことでバウンディングボックスの大きさが明らかに変動する。
 なので、対象meshを動かす前後のバウンディングボックスの大きさの変化をみれば、結果的に置いてきぼりの有無を検出できる。

 実際にはストランドの位置関係で、追従したとしても必ずしも対象meshを動かす前後のバウンディングボックスが完全には一致しなかったので、「対象meshの移動量に対して変動が少ないものは問題ない」という判別を行う必要があった。

ちなみに

 Groomノードからストランドをカーブに変換するメソッドがあるので、対象mesh移動前・移動後でストランドをカーブに変換した上で両者のカーブについて移動がみられないものがあれば、それは「置いてきぼりになっている」ことになるので、厳密にはその方法が確実に検出できる。
 ただカーブすべてをチェックしないといけないのはコストが掛かる。前述のGroomノード単体のバウンディングボックスで基本的な判定をした上で、変化のあったものに対してのみ必要に応じて厳密なチェックを行うほうが処理的に適切だろう。

 カーブ単位で検出する利点は、問題のカーブがどこに存在するかを知ることが出来る点にある。

PythonでCUDA (…ならず)

CUDAをローレベルで書くとか言っても、ゴリゴリとコード書くほどではないので、なんだかな〜…と思っていたのだけどcupyとかpycudaとか見つけてしまった。

で、とりあえずcupyを入れるも、なにやらアーキテクチャが合わないみたいなエラーで止まってしまい動作確認できず。
pycudaはCUDA2.0〜対応しているというので、インストールしてみたのだが、これまた動かず。

どうやら、どちらもビデオカードに積んでいるCUDAのバージョンが古いので動かない…という結果に。

いやいや、待ってよ…
「pycudaはCUDA2.0〜対応」じゃないんかよ!って思ったんだけど、そもそもCUDAの動作環境としてインストールしている「CUDA toolkit」なる動作環境が間に噛んでおり、toolkitにもまた対応するCUDAのバージョンが…。

toolkit9.1の場合、それが3.0以降なので対応できぬ、という話だった。

現状linux機に積んでいるGPUはFermi世代(CUDA2.1, 具体的にはquadro600)なので、Kepler以降のもの(例えばquadroK600など)に変えないと駄目そう。
敢えてtoolkit9.0にダウングレードするという選択肢もあるみたいだけど、ソースからインストールするのではゴリゴリコード書く人と変わんなくないですか…ってことで、そのうちGPUを変えたら再度検証したい。
(Windows機に乗ってるGTX950でもKeplerの次のMaxwell世代なのでそっちなら動かせるんだけど、個人的にlinux活用週間なのでこっちで遊びたい…)

…考えてみるとpycudaではコードゴリゴリ書くのとあまり変わんないような気もするし、その際はnumpy準拠(?)のcupyで行きたい。

そもそもCUDAのローレベルのコードというのは

 どんなものか? という話もあるのか…

 CUDAの基本的な動作パターンは、大雑把には以下の通り。

 ・予めCPU側で計算する値の配列情報を用意
 ・用意した配列をGPU側に転送(メモリ確保&コピー)
 ・GPU側で実行する計算処理を指定してGPU側の計算を実行
 ・GPU側の計算が終わったら、GPU側からCPU側に結果を転送(メモリ確保&コピー)
 ・GPU側のメモリを開放

 pycudaの場合は、これを概ねそのままPythonで記述する感じ。
 cupyの方は、基本numpyと同じような記述で済む。

 どっちだって同じじゃね?と思うかもしれないが、例えば「GPU側で実行する計算処理」はPythonではなくて nvcc でコンパイルするものをそのまま書く感じなので、ここはC言語に準拠した記述になる。これをpycudaでは文字列で扱うし、他の要素に関してもあまりPythonぽい手続きには感じない。
 numpyはそもそもPython記述で処理を書き連ねる感じになっているので、Pythonコードを書くというその部分でストレスを感じずに済む。それだけで、numpy準拠であるcupyは意味がある。