ブログトップ 記事一覧 ログイン 無料ブログ開設

ゲームの花園 このページをアンテナに追加 RSSフィード

2012-03-11

スクリプト処理速度比較「VBS・JS・Python・C++」

先日Softimageのスクリプトの事で調べ物をしていたら、Softimageのスクリプト言語での処理速度を比較するという面白い記事を見つけました。(myaraさんのサイト、他のスクリプト記事も濃くて面白いです^^)

今までスクリプトの処理速度は気にした事が無かったので「VBS、意外と速いんやなぁ〜」と興味深く読んでました。ただこの2年間くらいはPython縛りでプラグイン作成を統一していた自分にとっては、Pythonの速度比較が気になるところです。という訳で、今回は上記記事を参考にSoftimageのスクリプト言語での速度比較をしてみました。

はじめに

題材にしたのは、上記記事にあったXSIBaseのスクリプト。処理の内容はというと、

・選択しているポリゴンオブジェクトを取得

ポリゴンオブジェクトのエッジを取得

・全てのエッジを検証。エッジに隣接しているポリゴン(neighbor polygon)が2つ以上あるか判定

・2つ以上あれば、各ポリゴンの法線ベクトルを取得

・2つのポリゴンの法線ベクトルの差が、指定した値以上であればエッジを選択

というような感じです。今回の速度計測で使用したオブジェクトは、恒例のスタンフォードドラゴンをリダクションしたものを利用しています。(そのままだと処理時間がかかりすぎたので…。)

f:id:Aqu:20120312011922p:image:w360

まずはこれをmyaraさんの記事に基づいて最適化したものをベースで利用しています。最適化の概要は「option explicitを利用した宣言の徹底」と「特定のエッジを発見した時に、その都度選択を行う処理を止め、一旦配列に保存して最後に一括選択」が大きなところです。このスクリプトで、処理時間的には下記の通りとなりました。

f:id:Aqu:20120312083941p:image:w360

スクリプト処理時間(秒)
VBScript593.6172
VBScript(最適化)7.1118

確かに速くなりました。しかもかなり!書き方でこんなに変わるものなんですね。


スクリプト毎の比較

さて、上記で最適化したVBスクリプトを他の言語にも移植していきます。今回はJスクリプトPython、あとC++dll化したものも用意してみました。どれも処理内容は同じものです。で、結果はこちら。

f:id:Aqu:20120312011924p:image:w360

スクリプト処理時間(秒)
VBScript7.1118
JScript8.7450
Python100.1579
C++1.8930

Python遅いっ!圧倒的に処理時間がかかっています。これはどういうことなんでしょう…。処理の流れは同じはずなんですが…。

そういえばC++で作ったdllプラグイン形式で、他の言語はスクリプトの直接実行なので、その辺りが影響しているのかなと思い、他の言語もプラグイン化してみました。

そして結果はこちら。

f:id:Aqu:20120312083037p:image:w360

スクリプト処理時間(秒)
VBScript7.1118 (秒)
VBScript(Plugin化)6.8593 (秒)
JScript8.7450 (秒)
JScript(Plugin化)8.5820 (秒)
Python100.1579 (秒)
Python(Plugin化)99.3639 (秒)
C++1.8930 (秒)

うぅん速くなっているようですが、体感速度的には誤差程度の差しか無かったですね・・・。(マクロ的な使い方をしていれば、体感的に速くなる印象があるので、今回みたいなエッジをforでループと言う処理内容では結果が出にくいのかもしれません。)


まとめ

というわけで、今回の比較ではPythonが遅くて、VBスクリプトが速いという結果になりました。

最近は時流に乗ってプラグイン制作では全てPythonで統一を考えていましたが、VBスクリプトを見直しました。よくよく考えるとSoftimage自体に入っているプラグイン自体の大半がVBスクリプトで書かれているので、そこで気づくべきでしたね。

Pythonの構文はシンプルで行数も少なく、アーティストには優しい言語だと思っているので、今後も使用を継続していくと思いますが、処理速度を求めるところはVBスクリプトで書くという選択肢は考えた方が良いかもですね。

あと最後に、今回使ったスクリプトC++のソースはダウンロードできる形にしています。もし「Pythonはこう書いたら速くなるよ〜。」とかヒントがあれば、ぜひコメントいただければと思います。自分もその方が助かるので…。

VBS_JS_PY_CPP.zip 直

では!

msmhrtmsmhrt 2012/03/12 17:57 time.time()の罠に引っかかったのかもしれませんね。

>デフォルトのタイマ関数はプラットフォーム依存です。Windows の場合、 time.clock() はマイクロ秒の精度がありますが、 time.time() は 1/60 秒の精度しかありません。(引用元: http://www.python.jp/doc/2.7/library/timeit.html )

AquAqu 2012/03/12 22:35 > msmhrtmsmhrtさん

コメント有難うございます!
timeがプラットフォーム依存だとは初めて知りました。

ただ、今回の様にSoftimage上でPythonを利用した場合は、time.clock() も、time.time() も"from time import time"した上でのtime()も結果は変わりませんでした。

あと念には念をで、リアルストップウォッチで処理時間を計測してみても、上記とほぼ同じ計測値でした。処理時間の差としては、他の言語と比較するとやはり大きいようです。

anamorphobiaanamorphobia 2012/03/15 01:36 Softimage+pythonの場合オブジェクトモデルのプロパティからなんとかCollection取ってきて、ループで回すなどとやると遅くなる傾向がありますね。この場合なら getFacetNormal 内のNormal取ってくるところを facet.Nodes.NormalArray で拾ってくれば高速化できるとおもいます。それ以外にも、ループ内で oCol.AddItems してるところをただのpythonの配列に入れてループ外で連結、oCol.SetAsText にすると多少早くなると思います。検証してないのでちょっとあやふやですが…
言語間の比較とはちょっとずれましたが参考になれば幸いです。

AquAqu 2012/03/15 07:38 > anamorphobiaさん

コメント有難うございます。
上記ポイント、早速今夜にでも試してみますので、少々お待ちくださいー!

AquAqu 2012/03/17 00:34 > anamorphobiaさん

すいません、検証が遅くなりました。

結果から言いますと、facet.Nodes.NormalArrayにするとめっちゃ速くなりました。時間は100秒かかってたものが、40.021(秒)だったので、60秒短縮できたかたちになります!

ただ、oColをPythonのリスト(配列)への変更をあわせてしてみたのですが、こちらは速度的には、100秒 > 99秒くらいのだったので、上記の時間短縮はほぼ、facet.Nodes.NormalArrayが貢献しているようです。

処理の仕方だけで、こんなに変わるもんなんですね^^;

myaramyara 2012/03/23 01:55 リンクして頂きありがとうございます。

Pythonのループとコレクションは遅いと知っていたけど、そこまでとは驚きました。Pythonについてはまだ触り始めたばかりでとても勉強になる記事です。

やっぱりコンポーネントループが多いスクリプトはJSにした方が良さそう。

AquAqu 2012/03/23 02:25 > myaraさん

はじめまして!
最近ブログ発見して、定期的に読ませてもらっています^^
スクリプトの考え方とか、処理速度の事とか、悩みが近いので勉強になっています。


> Pythonのループとコレクションは遅いと知っていたけど、そこまでとは驚きました

そうですね、一度上記のスクリプトを改良して、For内でやってる処理は全てコメントアウトしてみたのですが、結局30秒かかってるので、単にループするだけでも遅いんだなとわかりました…。

Softimageでは、速度を求める処理はPython以外を選択するというのが、正しいかもしれませんね^^
(Pythonを使わないのが正解という見方も…。)

garugaru 2012/04/05 19:16 なんか知らない間に、こんな記事があったなんてー。
お久しぶりです。

そして、Python遅いですね…。これはかなりの弱点ですねー。
書きやすいのに。残念。

こちらでも、最適化を試みてみました。

なるべくCollectionを使わないようにと、変数を使いまわすというのを試みました結果、少しは、vbsの足元にまでたどり着けたかなという感じですが、vbsよりは速くはなりませんでした…。

こちらが最適化後のものです。
http://bit.ly/Hvu5KH

今回で書き方を変えないとなーとしみじみ思いました。

どうもありがとう!!!

AquAqu 2012/04/07 01:06 garuさん


お久しぶりです!
garuさんが最適化されたスクリプト実行してみました。

元が100秒前後だったのに対し、garuさんのやつが32秒前後。

他の言語にはかなわないとはいえ、素晴らしい結果です!3倍以上速くなりました^^;

中身も見せてもらいましたが、SetFacetNormal内のベクトルの扱い方と、str(l)の書き方に眼から鱗です(T-T

ありがとうございますー!

fmt0808fmt0808 2012/04/24 20:47 チョット気になったのでコードを落としてテストしてみました。

たしかにforの部分でも差は出てますが、もっと差を広げる部分がNeighborPolygonsメソッドでした。

実際にアップされているスクリプトの中身のfor内をPython,VBSそれぞれNeighborPolygonsの処理以外をコメントして実行してみたのとNeighborPolygonsを含めてコメントして実行してみたのとでの差が大きすぎました。
このことから現状だと。

SoftimageのPythonのNeighborPolygonsメソッドは遅い。
という点もかなり影響してきそうです。

既知かもしれないですが、報告まで…。

AquAqu 2012/04/26 23:41 > fmt0808さん

コメントをいただけるとは、ありがたいです^^

NeighborPolygonsメソッドのコメントアウトを試してみました。コメントアウトしたのは下記の7行です。

-----------------------
oPolys = oEdge.NeighborPolygons()
if oPolys.Count == 2:
angle = GetFacetAngle(oPolys(0), oPolys(1))

if angle >= hardEdgeLimit:
edgeName = selObjFullName + "." + oEdge.FullName + "[" + str(oEdge.Index) + "]"
oCol.AddItems(edgeName)
-----------------------

こちらで試した感じですと、

--------------------
VBS : 7.234秒
VBS : 0.125秒 ※NeighborPolygonsメソッド以下をコメントアウト
→約57倍処理時間が変化

Python : 98.414秒
Python : 2.521秒 ※NeighborPolygonsメソッド以下をコメントアウト
→約39倍処理時間が変化
--------------------

になり、処理時間は大きく変化しました。

ただ、それぞれのスクリプトでのNeighborPolygonsメソッドの速度が大きく違うようには、あまり感じられませんでした。(やはりPythonの実行速度が遅いのかなという印象です・・・。)

この辺りの受け取り方、fmt0808さんとずれていますでしょうか?また、こちらでコメントアウトした範囲が間違っているなどあれば、コメントいただけるとありがたいです。

よろしくお願いします!

投稿したコメントは管理者が承認するまで公開されません。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/Aqu/20120311/1331509290
リンク元