草庐IT

c# - 了解 VS2010 C# 并行分析结果

coder 2024-05-22 原文

我有一个包含许多独立计算的程序,所以我决定将其并行化。

我使用 Parallel.For/Each。

双核机器的结果还不错 - 大多数时候 CPU 利用率约为 80%-90%。 然而,对于双 Xeon 机器(即 8 核),尽管程序在并行部分花费了相当多的时间(有时超过 10 秒),但我只获得了大约 30%-40% 的 CPU 利用率,而且我看到它采用与串行部分相比,这些部分中的线程多了大约 20-30 个。每个线程都需要超过 1 秒的时间才能完成,所以我认为它们没有理由不并行工作 - 除非存在同步问题。

我用了VS2010自带的profiler,结果很奇怪。 即使我只在一个地方使用锁,分析器报告说大约 85% 的程序时间花在了同步上(还有 5-7% 的 sleep ,5-7% 的执行,低于 1% 的 IO)。

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

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 是 Object 类的静态成员。
esn.populate 使用每个线程的单独 StreamReader 从文件读取。

但是,当我按下“同步”按钮查看导致最大延迟的原因时,我看到探查器报告的行是函数入口行,而没有报告锁定的部分本身。
它甚至不将包含上述代码的函数(提醒 - 程序中唯一的)报告为噪声级别为 2% 的阻塞配置文件的一部分。噪声级别为 0% 时,它会报告程序的所有功能,我不明白为什么它们算作阻塞同步。

所以我的问题是 - 这里发生了什么?
怎么85%的时间都花在了同步上?
我如何找出程序并行部分的真正问题所在?

谢谢。

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

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

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

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

我进一步深入每个线程,发现现在对 GC allocate 的许多调用都是为了分配不属于大型字典的小对象。

我通过为每个线程提供一个预先分配的此类对象池来解决这个问题,我使用它而不是调用"new"函数。

所以我基本上为每个线程实现了一个单独的内存池,但是以一种非常粗糙的方式,这非常耗时而且实际上不是很好 - 我仍然必须使用很多对于这些对象的初始化,我现在只在全局范围内进行一次,并且 GC 线程上的争用较少,即使必须增加池的大小也是如此。

但这绝对不是我喜欢的解决方案,因为它不容易泛化,而且我不想编写自己的内存管理器。
有没有办法告诉 .NET 为每个线程分配预定义的内存量,然后从本地池中获取所有内存分配?

最佳答案

能少分配点吗?

我有过几次类似的经历,查看糟糕的性能并发现问题的核心是 GC。但是,在每种情况下,我都发现我在某个内部循环中不小心造成了内存泄漏,不必要地分配了大量的临时对象。我会仔细查看代码,看看是否有可以删除的分配。我认为程序很少会“需要”在内部循环中进行大量分配。

关于c# - 了解 VS2010 C# 并行分析结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2902984/

有关c# - 了解 VS2010 C# 并行分析结果的更多相关文章

  1. ruby-on-rails - Railstutorial : db:populate vs. 工厂女孩 - 2

    在railstutorial中,作者为什么选择使用这个(代码list10.25):http://ruby.railstutorial.org/chapters/updating-showing-and-deleting-usersnamespace:dbdodesc"Filldatabasewithsampledata"task:populate=>:environmentdoRake::Task['db:reset'].invokeUser.create!(:name=>"ExampleUser",:email=>"example@railstutorial.org",:passwo

  2. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  3. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  4. 报告回顾丨模型进化狂飙,DetectGPT能否识别最新模型生成结果? - 2

    导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri

  5. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  6. ruby - 带括号和 splat 运算符的并行赋值 - 2

    我明白了:x,(y,z)=1,*[2,3]x#=>1y#=>2z#=>nil我想知道为什么z的值为nil。 最佳答案 x,(y,z)=1,*[2,3]右侧的splat*是内联扩展的,所以它等同于:x,(y,z)=1,2,3左边带括号的列表被视为嵌套赋值,所以它等价于:x=1y,z=23被丢弃,而z被分配给nil。 关于ruby-带括号和splat运算符的并行赋值,我们在StackOverflow上找到一个类似的问题: https://stackoverflow

  7. ruby - 使对象的行为类似于 ruby​​ 中并行分配的数组 - 2

    假设您在Ruby中执行此操作:ar=[1,2]x,y=ar然后,x==1和y==2。是否有一种方法可以在我自己的类中定义,从而产生相同的效果?例如rb=AllYourCode.newx,y=rb到目前为止,对于这样的赋值,我所能做的就是使x==rb和y=nil。Python有这样一个特性:>>>classFoo:...def__iter__(self):...returniter([1,2])...>>>x,y=Foo()>>>x1>>>y2 最佳答案 是的。定义#to_ary。这将使您的对象被视为要分配的数组。irb>o=Obje

  8. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  9. ruby - 了解在 Ruby 中与 lambda 一起使用的 inject 行为 - 2

    我经常将预配置的lambda插入可枚举的方法中,例如“map”、“select”等。但是“注入(inject)”的行为似乎有所不同。例如与mult4=lambda{|item|item*4}然后(5..10).map&mult4给我[20,24,28,32,36,40]但是,如果我制作一个2参数lambda用于像这样的注入(inject),multL=lambda{|product,n|product*n}我想说(5..10).inject(2)&multL因为“inject”有一个可选的单个初始值参数,但这给了我......irb(main):027:0>(5..10).inject

  10. ruby-on-rails - 如何测试自己对 Ruby/ROR 的了解? - 2

    是否有self验证的问题列表。看着那个,我可以确定我知道。我应该复习一下。在学习的过程中,我列了一个这样的list,但它只包含我在某处听说过的项目。我需要一段时间才能找到新的东西。 最佳答案 以下是针对ruby​​和Rails的一些测试列表。证书名称:RubyonRails谁提供:oDeskIncorporation认证费用:免费网站:https://www.odesk.com/tests/985?pos=0证书名称:RubyonRails提供者:Techgig.com(TimesBusinessSolutionsLimited(T

随机推荐