パーティクル フロー[スクリプト オペレータ](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)
これは、次と同じです。
しかし、処理時間は 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 を使用してテーブル検索を高速化する