パーティクル フロー Script オペレータの 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 を使用してテーブル検索を高速化する