首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >比一台机器上的多线程应用程序慢的GridGain应用程序

比一台机器上的多线程应用程序慢的GridGain应用程序
EN

Stack Overflow用户
提问于 2010-12-19 04:51:29
回答 2查看 1K关注 0票数 3

我已经实现了我的第一个GridGain应用程序,并且没有得到我期望的性能改进。遗憾的是,它的速度较慢。我想要一些帮助,以改善我的实现,以便它可以更快。

我的应用程序的要点是,我正在用数百万个可能的参数进行蛮力优化,每个函数的评估都需要一小部分秒。我通过将数百万次迭代分成几个组来实现这一点,每个组作为一个任务执行。

相关代码如下所示。函数maxAppliedRange对范围x中的每个值调用函数foo,并返回最大值,结果将成为每个作业找到的所有最大值的最大值。

代码语言:javascript
运行
复制
  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节点。当我运行grid增益版本时,它的启动速度似乎会更快,但接下来总会发生一些事情:

  • (在另一台计算机上)中的一个节点错过了心跳,导致我的主计算机上的节点放弃了该节点,并开始第二次执行任务。丢失心跳的节点
  • 继续执行相同的任务。现在我有两个节点在我的主机上执行相同的thing.
  • Eventually,--所有的作业都是在我的主机上执行的,但是由于有些作业是后来开始的,所以finish.
  • Sometimes需要花费更长的时间-- GridGain会抛出异常,因为一个节点超时了,整个任务都失败了。
  • I很生气。

我试着把它设置成有很多作业,所以如果一个作业失败了,那就没什么大不了的了,但是当我这样做的时候,我最终会在每个节点上执行许多作业。这就给每台机器增加了更大的负担,使得节点更有可能失去心跳,从而使每件事情都更快地下坡。如果我每个CPU有一个作业,那么如果一个作业失败,另一个节点必须从一开始就重新开始。不管怎样我都赢不了。

我认为最好的办法是我能做两件事:

heartbeats

  • Throttle每个节点的
  • 都会增加超时时间,以便它一次只执行一个任务。

如果我能做到这一点,我就可以把我的任务分成许多工作。每个节点一次只做一次工作,没有一台机器负担过重,以致错过一次心跳。如果一份工作失败了,那么就不会有什么工作损失,恢复也会很快。

有人能告诉我怎么做吗?我应该在这里做什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-12-19 19:01:18

现在我让它正常工作了。在我的应用程序中,我比一台机器上的多线程应用程序快了大约50%,但这不是我所能做到的最好的。还有更多的工作要做。

要使用gridgain,配置文件似乎对所有工作都很重要。这是设置节点行为的地方,必须与应用程序的需要相匹配。

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

代码语言:javascript
运行
复制
    <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,而不是使用多播。我没有这么做,但是如果你一遍又一遍地使用同一台机器,它可能会更可靠。

我做的另一件事是:

代码语言:javascript
运行
复制
    <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值告诉节点它可以同时运行多少个作业。这是一种比更改executor服务中线程数更好的节流方法。此外,它还实现了一些负载平衡,空闲节点可以“窃取”其他节点的工作,以便更快地完成所有工作。

也有更好的方法来做到这一点。显然,Grid增益可以根据每个节点的测量性能来调整任务的大小,这将提高总体性能,特别是在网格中有快速和慢的计算机时。

今后,我将研究配置文件,并将其与javadocs进行比较,以了解所有不同的选项,从而使其运行得更快。

票数 2
EN

Stack Overflow用户

发布于 2010-12-19 07:51:33

我想通了。

首先,有一个xml配置文件控制网格节点的操作细节。默认配置文件在GRIDGAIN_HOME/config/ default -spring.xml中。在启动网格节点时,我可以编辑它或复制它并将新文件传递给ggstart.sh。我需要补充的两件事是:

代码语言:javascript
运行
复制
    <property name="networkTimeout" value="25000"/>

将网络消息的超时设置为25秒,并且

代码语言:javascript
运行
复制
   <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。执行器服务控制执行网格作业的线程池。缺省值是100,这就是为什么我的应用程序被淹没,心跳被超时的原因。

我必须对代码进行的另一个更改是:

代码语言:javascript
运行
复制
  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语句,它将启动一个具有所有默认选项的网格节点,而不是具有上述编辑的配置文件,这正是我想要的。

现在它就像我需要的那样工作。我可以把任务分成几个小块,即使是我最弱和最慢的计算机也能为这一努力做出贡献。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4481645

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档