我有一个使用TPL并行化的for循环的实现。我正在使用一个4GB内存和i3核心处理器的戴尔笔记本电脑。我有多个parallel.foreach,它们使用Parallel.invoke调用。该程序是Enterprise的一个附加程序,用于在EA中创建模型图和对象。
代码是这样的:
Parallel.invoke(()=>parent1Creation(),()=>parent2Creation(),...);其中每个父创建都是一个Parallel.foreach。
Parallel.foreach(parents, (parent) => {
//create parent
//create children
for(child in parent.children) {
childecreation();
}
for(child2 in parent.children) {
childecreation();
}
//can be any type and number of children
} 我有一个问题,当我的循环大小增加,即大约1500到2000次迭代时,Enterprise停止工作。
这是因为我的膝上型电脑配置或者我使用并行循环的方式还是与Enterprise有关的问题。
我该怎么解决这个问题。
发布于 2016-09-12 05:19:03
我不建议你这么做。同时运行大量Parallel.ForEach循环并不一定有助于您的性能(请参阅后面的文章中的警告),特别是如果每个Parallel.ForEach循环都要处理大量的迭代。在某种程度上,使用额外的线程将不再有益于您的性能,只会增加开销。
这里要注意的是,Parallel.ForEach在为特定foreach循环选择最优线程数方面通常是很好的(但不是完美的)。对于一个特定foreach循环将使用多少个线程(甚至是它将并行运行),没有明确的保证,因此可以想象,多个Parallel.ForEach循环实际上会提高性能。最好的检查方法是使用调试器来查看它在任何给定点上实际使用了多少线程。如果不是您所期望的那样,您可能会在Parallel.ForEach循环中检查代码的实现(例如);您可以在此时采取其他步骤来提高性能(例如,为IO绑定和其他非CPU绑定操作提供良好的异步/等待实现,以便线程能够完成更多的工作-请参见下文)。
简单的例子:假设您有一个系统,其中您有4个线程和4个核心,而4个线程是系统上唯一运行的东西。(很明显,这种情况永远不会发生)。从调度的角度来看,明智的做法是让每个核心句柄每个线程一个。假设每个线程一直都很忙(也就是说,它从来不等待),那么添加额外的线程如何可以提高您的性能呢?例如,如果您开始运行6个线程,那么显然至少有一个核心现在必须运行至少2个线程,这会增加额外的开销,而没有明显的好处。这里的简化(也可能是不真实的)假设是,您的任务是100%的CPU绑定,并且线程实际上运行在不同的核心上。如果这些假设中有一个是不正确的,那么这显然是一个增强的机会。例如,如果线程花费大量时间等待IO绑定操作的结果,CPU上的多个线程实际上可以提高性能。您还可以考虑使用异步/等待实现来提高性能。
要点是,在某个时候添加额外的线程不会给您带来任何性能上的好处,只是增加了开销(特别是如果所涉及的任务主要是CPU绑定的,而不是大部分的IO绑定)。这个事实是无法回避的。
非CPU绑定操作(例如,对服务器的调用等IO绑定任务),其中主延迟等待来自CPU/内存外部的结果是不同的并行化。事实上,异步/等待并不一定会创建新线程;它的主要行为之一是将控制返回到有关方法的调用方,并在可能的情况下“尝试”在同一线程上执行其他工作。
重复我最喜欢的比喻,假设你是10个人中的一员出去吃饭。当服务生过来点菜时,服务员要求点菜的第一个人还没准备好,但其他九个人已经准备好了。侍者要做的正确的事情是,不要等到第一个人准备好点菜,而是让其他9个人先点菜,然后如果他准备好了,就让第一个人点菜。他绝对不会请第二个侍者来等一个人准备好;在这种情况下,第二个侍者可能实际上不会减少完成点菜所需的总时间。这基本上就是异步/等待所要完成的;例如,如果一个操作所做的都是等待来自服务器的结果,那么理想情况下,您将能够在等待时执行其他事情。
另一方面,为了扩大类比,绝对不是服务生自己做的。在这种情况下,增加更多的人(类推,线程)将真正加快速度。
为了进一步推广这一类比,如果厨房只有一个四烧炉,那么在厨房工作人员遇到炉子大小的硬性限制之前,你可以增加多少人,这是一个很难的限制。一旦你达到了这个极限,更多的厨房工作人员实际上会放慢速度,因为他们只会妨碍对方,因为实际上可以同时烹饪的东西的数量有一个严格的限制。不管你的厨房工作人员有多大,你不可能一次在炉子上煮超过4件东西。在这种情况下,您拥有的核心数量就像厨房大小一样;一旦您到达某个点,增加更多的厨房工作人员(线程)将降低您的性能(而不是提高性能)。
发布于 2016-09-12 21:20:47
如果使用RDBMS支持的模型,则最好针对模型执行一些SQL,以快速完成任务,而不是使用EA的API。
https://leanpub.com/InsideEA有很多关于这个结构的细节。
例如,使用SQLServer,与遍历EA对象相比,使用原始插入要快得多,更不用说连接来快速获取数据了。
与使用API相比,我的脚本具有接近100 x+的性能w/ SQL。
不确定EA COM对象是否能够按需要调用。如果是的话,为了使Object_IDs得到正确的分配,模型更新仍然必须按某种顺序进行。这可能解释了为什么您会在某种锁定限制下运行。
https://stackoverflow.com/questions/39443578
复制相似问题