3

最初のGridGainアプリケーションを実装しましたが、期待したパフォーマンスの向上が得られません。悲しいことに、それは遅いです。より速くできるように、実装を改善するための助けが欲しいです。

私のアプリケーションの要点は、関数の評価ごとに数分の1秒かかる数百万の可能なパラメーターを使用して力ずくの最適化を行っていることです。私はこれを、数百万の反復をいくつかのグループに分割することによって実装しました。各グループは1つのジョブとして実行されます。

関連するコードは以下のとおりです。関数maxAppliedRangeは、範囲xのすべての値に対して関数fooを呼び出し、最大値を返します。結果は、各ジョブで検出されたすべての最大値の最大値になります。

  scalar {
    result = grid !*~
      (for (x <- (1 to threads).map(i => ((i - 1) * iterations / threads, i * iterations / threads)))
        yield () => maxAppliedRange(x, foo), (s: Seq[(Double, Long)]) => s.max)
  }

私のコードは、1台のマシンでマルチスレッド実行するか、上記のコードを使用して複数のGridGainノードを使用するかを選択できます。gridgainバージョンを実行すると、最初は高速になるように見えますが、その後は常にいくつかのことが起こります。

  • (別のマシン上の)ノードの1つがハートビートを逃し、メインコンピューター上のノードがそのノードをあきらめて、ジョブの実行を2回開始します。
  • ハートビートを逃したノードは、同じ仕事を続けます。これで、2つのノードが同じことを実行します。
  • 最終的には、すべてのジョブがメインマシンで実行されますが、一部のジョブは後で開始されるため、すべてが完了するまでに時間がかかります。
  • ノードがタイムアウトし、タスク全体が失敗したために、GridGainによって例外がスローされることがあります。
  • イライラします。

多くのジョブを持つように設定してみたので、1つが失敗してもそれほど大きな問題にはなりませんが、これを行うと、各ノードで多くのジョブが実行されることになります。これにより、各マシンに非常に大きな負担がかかり、ノードがハートビートを見逃す可能性が高くなり、すべてがより速く下り坂になります。CPUごとに1つのジョブがある場合、1つのジョブが失敗すると、別のノードを最初からやり直す必要があります。いずれにせよ、私は勝つことができません。

私が最もうまくいくと思うのは、2つのことができるかどうかです。

  • ハートビートのタイムアウトを増やす
  • 一度に1つのジョブのみを実行するように、各ノードをスロットルします。

これができれば、自分の仕事を多くの仕事に分割することができます。各ノードは一度に1つのジョブを実行し、マシンが過負荷になってハートビートを逃すことはありません。ジョブが失敗した場合、ほとんど作業が失われず、回復は迅速になります。

誰かがこれを行う方法を教えてもらえますか?私はここで何をすべきですか?

4

2 に答える 2

2

私はそれを考え出した。

まず、グリッドノードの動作の詳細を制御するxml構成ファイルがあります。デフォルトの設定ファイルはGRIDGAIN_HOME/config/default-spring.xmlにあります。これを編集するか、コピーして、グリッドノードを起動するときに新しいファイルをggstart.shに渡すことができます。追加する必要がある2つのものは次のとおりです。

    <property name="networkTimeout" value="25000"/>

これにより、ネットワークメッセージのタイムアウトが25秒に設定されます。

   <property name="executorService">
        <bean class="org.gridgain.grid.thread.GridThreadPoolExecutor">
            <constructor-arg type="int" value="1"/>
            <constructor-arg type="int" value="1"/>
            <constructor-arg type="long">
                <util:constant static-field="java.lang.Long.MAX_VALUE"/>
            </constructor-arg>
            <constructor-arg type="java.util.concurrent.BlockingQueue">
                <bean class="java.util.concurrent.LinkedBlockingQueue"/>
            </constructor-arg>
        </bean>
    </property>

最初の2つのコンストラクター引数は、開始する1つのスレッドと1の最大スレッドサイズに対するものです。エグゼキューターサービスは、gridgainジョブを実行するスレッドプールを制御します。デフォルトは100です。これが、私のアプリケーションが圧倒され、ハートビートがタイムアウトしていた理由です。

コードに加えなければならなかった他の変更は次のとおりです。

  scalar.apply("/path/to/gridgain home/config/custom-spring.xml") {
    result = grid !*~
      (for (x <- (1 to threads).map(i => ((i - 1) * iterations / threads, i * iterations / threads)))
        yield () => maxAppliedRange(x, kalmanBruteForceObj.performKalmanIteration), (s: Seq[(Double, Long)]) => s.max)
  }

.applyステートメントがないと、上記の編集を含む構成ファイルではなく、すべてのデフォルトオプションでグリッドノードが開始されるため、これが必要です。

今では必要なとおりに機能します。私はタスクを小さな部分に分割することができ、私の最も弱くて最も遅いコンピューターでさえ、この努力に貢献することができます。

于 2010-12-19T07:51:33.173 に答える
2

今、私はそれが正しく機能しています。私のアプリケーションの状況では、1台のマシンでマルチスレッドアプリケーションよりも約50%高速化されていますが、それは私ができる最善の方法ではありません。さらに作業を行う必要があります。

gridgainを使用するには、すべてを機能させるために構成ファイルが重要であるように思われます。これはノードの動作が設定される場所であり、アプリケーションのニーズに一致する必要があります。

xml構成ファイルで必要なものの1つは、次のとおりです。

    <property name="discoverySpi">
        <bean class="org.gridgain.grid.spi.discovery.multicast.GridMulticastDiscoverySpi">
            <property name="maxMissedHeartbeats" value="20"/>
            <property name="leaveAttempts" value="10"/>
        </bean>
    </property>

これにより、ノードが欠落していると見なされる前に欠落する可能性のある最大ハートビートが設定されます。数秒後にノードが出たり戻ったりする問題が続いたため、これを高い値に設定しました。または、マルチキャストを使用する代わりに、構成ファイル内の他のプロパティを使用して、実行中のノードを持つマシンのIPを修正することもできます。私はこれをしませんでしたが、同じマシンを何度も使用している場合は、おそらくより信頼性が高くなります。

私がした他のことは:

    <property name="collisionSpi">
        <bean class="org.gridgain.grid.spi.collision.jobstealing.GridJobStealingCollisionSpi">
            <property name="activeJobsThreshold" value="2"/>
            <property name="waitJobsThreshold" value="4"/>
            <property name="maximumStealingAttempts" value="10"/>
            <property name="stealingEnabled" value="true"/>
            <property name="messageExpireTime" value="1000"/>
        </bean>
    </property>

    <property name="failoverSpi">
        <bean class="org.gridgain.grid.spi.failover.jobstealing.GridJobStealingFailoverSpi">
            <property name="maximumFailoverAttempts" value="10"/>
        </bean>
    </property>

最初の値の場合、activeJobsThreshold値は、ノードが同時に実行できるジョブの数を示します。これは、エグゼキュータサービスのスレッド数を変更するよりも、スロットルを実行するためのより良い方法です。また、一部の負荷分散を実行し、アイドル状態のノードが他のノードから作業を「盗む」ことで、すべてをより高速に実行できます。

これを行うためのより良い方法もあります。Gridgainは、各ノードの測定されたパフォーマンスに基づいてジョブのサイズを決定できます。これにより、特にグリッド内に高速および低速のコンピューターがある場合、全体的なパフォーマンスが向上します。

将来的には、構成ファイルを調べてjavadocsと比較し、さまざまなオプションをすべて学習して、これをさらに高速に実行できるようにします。

于 2010-12-19T19:01:18.727 に答える