我已经实施了我的第一个Gridgain应用程序,并且没有得到我预期的绩效改进。可悲的是,这很慢。我希望提供一些帮助,以改善我的实现,以便更快。

我的应用程序的要旨是,我正在对数百万个可能的参数进行蛮力优化,这些参数对每个函数评估都占一秒钟。我通过将数百万次迭代分为几个组来实施,每个组都被执行为一项作业。

相关的代码如下。范围x中每个值的函数maxappliedrange调用函数foo foo 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)
  }

我的代码可以在一台计算机上的多线程执行之间选择,也可以使用上面的代码使用多个Gridgain节点。当我运行Gridgain版本时,它开始时的速度会更快,但是总是会发生一些事情:

  • 其中一个节点(在另一台机器上)错过了心跳,导致我的主计算机上的节点放弃该节点,并开始第二次执行该作业。
  • 错过心跳的节点继续做同样的工作。现在我有两个节点做同样的事情。
  • 最终,所有工作都在我的主机上执行,但是由于某些工作开始后来,所有工作都需要更长的时间才能完成所有工作。
  • 有时,由于节点定时且整个任务失败,因此Gridgain会引发异常。
  • 我很生气。

我尝试将其设置为有很多工作,因此,如果一个人失败了,那将不会那么大,但是当我这样做时,我最终会在每个节点上执行许多作业。这给每台机器的负担增加了很多,使节点更有可能错过心跳,从而使一切都更快地下降。如果我每个CPU有一项工作,则如果一个作业失败,则必须从一开始就必须重新开始。无论哪种方式,我都无法获胜。

我认为最好的是,如果我能做两件事:

  • 增加心跳的超时
  • 节流每个节点,因此一次只能完成一项工作。

如果我能做到这一点,我可以将任务分为许多工作。每个节点一次都会做一份工作,没有任何机器会使它失去心跳。如果工作失败,那么几乎没有工作就会丢失,并且恢复会很快。

谁能告诉我该怎么做?我应该在这里做什么?

有帮助吗?

解决方案 2

现在我可以正常工作。在我的应用程序的情况下,我在一台计算机上的多线程应用程序中获得了约50%的速度,但这不是我能做的最好的。要做更多的工作。

要使用GridGain,似乎配置文件对于使所有内容都起作用至关重要。这是设置节点行为的地方,必须符合您的应用程序的需求。

我在XML配置文件中需要的一件事是:

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

这设置了在认为丢失节点之前可能会错过的最大心跳。我将其设置为高价值,因为我一直存在淋巴结问题,并在几秒钟后回来。另外,使用多播我可以使用配置文件中的其他属性来修复机器的IPS的IPS。我没有这样做,但是如果您一遍又一遍地使用相同的机器,可能会更可靠。

我做的另一件事是:

    <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进行比较,以了解所有不同选项,以使其更快地运行。

其他提示

我想到了。

首先,有一个XML配置文件,该文件控制网格节点如何运行的详细信息。默认配置文件在gridgain_home/config/default-spring.xml中。我可以将其编辑或复制它,然后将新文件传递给GGSTART.SH,当我启动网格节点时。我需要添加的两件事是:

    <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>

前两个构造函数参数是要启动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语句,它将启动一个带有所有默认选项的网格节点,而不是带有上述编辑的配置文件,这是我想要的。

现在它完全按照我的需求工作。我可以将任务分为小块,即使是我最弱,最慢的计算机也可以为这项工作做出贡献。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top