パーティクル フロー[スクリプト オペレータ](script operator)の for ループを最適化して処理速度を上げる

MAXScript に関する質問と回答 > 処理速度を上げる方法 > パーティクル フロー[スクリプト オペレータ](script operator)の for ループを最適化して処理速度を上げる

On Proceed() ハンドラの内部にコードを使用した場合

for i in 1 to count do
(
pCont.particleIndex = i
colmult = 80
pspeed = pCont.particlespeed
pvel = sqrt (pspeed.x*pspeed.x+pspeed.y*pspeed.y+pspeed.z*pspeed.z)
pCont.particleAge = pvel*colmult
)

パフォーマンスに関するコメント

次の行を見てください。

pvel = sqrt (pspeed.x*pspeed.x+pspeed.y*pspeed.y+pspeed.z*pspeed.z)

これは、次と同じです。

pvel = length pspeed

しかし、処理時間は 4 倍長くなります。パーティクル フロー演算子の内部を計算する場合は、そのコードは各パーティクルについて数千回、場合によっては数百万回呼び出されるので、処理速度が最も速いメソッドを使用する必要があります。

最初のコード ブロックは、あるマシン上で実行した場合に、評価に 3360 ミリ秒かかりました。

(
st = timestamp()
pspeed = [10,2,3]
for i = 1 to 1000000 do
sqrt (pspeed.x*pspeed.x+pspeed.y*pspeed.y+pspeed.z*pspeed.z)
format "%\n" (timestamp()-st)
)

しかし、次のような length() メソッドを使用した同じコードを使用した場合は、

(
st = timestamp()
pspeed = [10,2,3]
for i = 1 to 1000000 do
length pspeed
format "%\n" (timestamp()-st)
)

同じマシン上でも評価は 813 ミリ秒しかかからず、処理速度は 4.13 倍も向上しています。

さらに、どちらの場合も、一時変数 pvel への割り当てによって 200 ミリ秒から 100 万回の呼び出しが追加されるので、元のコード ブロックを次のように書き直します。

(
for i = 1 to count do(
pCont.particleIndex = i
pCont.particleAge = length (pCont.particlespeed) * 80
)
)

length() メソッドを使用することによって処理速度が向上したうえに、中間的な変数を使用しないことによって 100 万回の呼び出しにつき 600 ミリ秒を短縮できます。

次に、もう 1 つ別のシミュレーションをしてみましょう。ループおよび初速の計算に 3 つの変数割り当てが含まれている場合です。

(
st = timestamp()
for i = 1 to 1000000 do (
pspeed = [10,2,3]
colmult = 80
pvel = sqrt (pspeed.x*pspeed.x+pspeed.y*pspeed.y+pspeed.z*pspeed.z)
pvel * colmult
)
format "%\n" (timestamp()-st)
)

このコードは最初のコードで行っていた処理と非常に似た処理を行っています (パーティクルの値を実際に読み書きしている点を除く)。この評価には 5750 ミリ秒かかりました。

一方、

(
st = timestamp()
for i = 1 to 1000000 do (
pspeed = [10,2,3]
colmult = 80
pvel = length pspeed
pvel * colmult
)
format "%\n" (timestamp()-st)
)

このコードは 3200 ミリ秒で実行できます。なぜなら、MAXScript コード内の 3 つの加算と 3 つの乗算を省略できるからです。length() は同じことを内部的に行いますが、C++ で実装されているためはるかに高速です。

中間変数を使用せずに同じ値を最後に計算しているインライン バージョンのテスト コードは、1400 ミリ秒しかかかりません。

(
st = timestamp()
for i = 1 to 1000000 do (
length [10,2,3] * 80
)
format "%\n" (timestamp()-st)
)

まとめると、最良のパフォーマンスを得るためには、PFlow スクリプトの内部でローカルの中間変数を使用することを避け、次のように組み込みメソッドを使用します。

(
for i = 1 to pCont,Numparticles() do (
pCont.particleIndex = i
pCont.particleAge = length (pCont.particlespeed) * 80
)
)

前のヒント

for ... collect と for ... do のパフォーマンスの比較

次のヒント

Bsearch を使用してテーブル検索を高速化する