首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >理解VS2010 C#并行分析结果

理解VS2010 C#并行分析结果
EN

Stack Overflow用户
提问于 2010-05-25 08:10:09
回答 1查看 1.3K关注 0票数 15

我有一个有很多独立计算的程序,所以我决定把它并行化。

我使用Par等位基因。

结果表明,在大多数情况下,双核机- CPU利用率约为80%-90%。然而,使用双Xeon机器(即8核),我的CPU利用率仅为30%-40%,尽管程序在并行部分上花费了相当长的时间(有时超过10秒),而且我看到与串行部分相比,它在这些部分中使用了大约20-30个线程。每个线程需要超过1秒才能完成,因此我认为它们没有理由不并行工作--除非存在同步问题。

我使用了内置的VS2010分析器,结果很奇怪。即使我只在一个地方使用锁,分析器报告说,大约85%的程序时间用于同步(也是5-7%的睡眠,5-7%的执行,低于1% IO)。

锁定的代码只是缓存(字典) get/add:

代码语言:javascript
运行
复制
bool esn_found;
lock (lock_load_esn)
    esn_found = cache.TryGetValue(st, out esn);
if(!esn_found)
{
    esn = pData.esa_inv_idx.esa[term_idx];
    esn.populate(pData.esa_inv_idx.datafile);
    lock (lock_load_esn)
    {
        if (!cache.ContainsKey(st))
            cache.Add(st, esn);
    }
}

lock_load_esn是类型对象类的静态成员。

esn.populate对每个线程使用单独的StreamReader从文件中读取。

但是,当我按下同步按钮查看是什么导致了最大的延迟时,我看到分析器报告的行是函数入口行,而不是报告锁定的部分本身。

它甚至没有报告包含上述代码的函数(提醒-程序中的唯一锁)作为阻塞配置文件的一部分,噪音级别为2%。在噪音水平为0%的情况下,它报告了程序的所有功能,但我不明白为什么它们被计算为阻塞同步。

所以我的问题是-这是怎么回事?

为什么85%的时间花在同步上?

如何找出我的程序的平行部分的真正问题是什么?

谢谢。

Update:在深入到线程中(使用非常有用的可视化工具)之后,我发现大部分同步时间都花在等待GC线程完成内存分配上,并且由于通用数据结构调整了大小操作,所以需要频繁的分配。

我必须了解如何初始化数据结构,以便它们在初始化时分配足够的内存,从而可能避免GC线程的争用。

今天晚些时候我会报告结果。

更新:内存分配似乎确实是造成问题的原因。当我对并行执行类中的所有字典和列表使用初始容量时,同步问题就更小了。我现在只有大约80%的同步时间,CPU利用率达到70% (以前的峰值只有40%)。

我对每个线程进行了更深入的钻研,发现现在对GC分配的许多调用都用于分配小对象,而这些对象不是大型字典的一部分。

我通过为每个线程提供一个预先分配的对象池来解决这个问题,而不是调用“新”函数。

因此,我基本上为每个线程实现了一个单独的内存池,但是以一种非常粗糙的方式,这是非常耗时的,而且实际上也不是很好--我仍然需要使用许多新的方法来初始化这些对象,直到现在我才在全局范围内执行了一次,而且GC线程上的争用减少了,即使必须增加池的大小。

但这绝对不是我喜欢的解决方案,因为它不容易泛化,我也不想写我自己的内存管理器。

是否有一种方法可以告诉.NET为每个线程分配预定义的内存量,然后从本地池获取所有内存分配?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-05-25 16:20:08

你能少分配一点吗?

我有过几次类似的经历,看看糟糕的特权,发现问题的核心是GC。然而,在每一种情况下,我都发现自己在某个内部循环中意外地失掉了记忆,分配了大量不必要的临时对象。我会仔细查看代码,看看是否存在可以删除的分配。我认为程序“需要”在内部循环中大量分配是很少见的。

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

https://stackoverflow.com/questions/2902984

复制
相关文章

相似问题

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