如何优化双,四和更高的多处理器?

时间:2011-12-26 04:42:20

标签: c# .net parallel-processing cpu

伙计们,我已经编写了20多年的高速软件,并且几乎了解了本书中的每一个技巧,从微型工作台制作合作,分析,用户模式多任务处理,尾部递归,您可以将其命名为非常高性能的东西Linux,Windows等。

问题在于,当CPU密集型工作的多个线程暴露给多核处理器时,我发现自己会感到困惑。

线程(在不同内核上)之间共享日期的各种方式的微观基准测试结果似乎不符合逻辑。

很明显,核心之间存在一些“隐藏的交互”,这与我自己的编程代码并不明显。我听说过L1缓存和其他问题,但那些对我来说是不透明的。

问题是:我在哪里可以学到这些东西?我正在寻找一本关于多核处理器如何工作,如何编程以利用其内存缓存或其他硬件架构的深度书,而不是受到它们的惩罚。

任何建议或优秀的网站或书籍?经过大量的谷歌搜索,我空洞。

此致 韦恩

6 个答案:

答案 0 :(得分:4)

这本书教会了我很多关于为什么不需要原始CPU功率的这类问题,这是唯一需要注意的问题。我几年前在研究生院里用它,但我认为所有的原则仍然适用:

http://www.amazon.com/Computer-Architecture-Quantitative-Approach-4th/dp/0123704901

基本上,多进程配置中的一个主要问题是同步对主内存的访问,如果你不这样做,它可能是性能的真正瓶颈。对于必须保持同步的缓存,它非常复杂。

答案 1 :(得分:4)

我自己的问题,回答,在stackoverflow的姐妹网站上:https://softwareengineering.stackexchange.com/questions/126986/where-can-i-find-an-overview-of-known-multithreading-design-patterns/126993#126993

我会复制答案以避免点击:

引用鲍里斯:

  

使用Microsoft .NET并行编程:设计模式   多核架构的分解和协调http://rads.stackoverflow.com/amzn/click/0735651590

     

这是一本书,我全心全意地推荐。

     

是:

     

新版 - 去年发布。意味着你没有阅读有点过时   实践。

     

简短 - 大约200多页,信息密集。这些   阅读时间过多,阅读1000多页的时间太少   图书。

     

易于阅读 - 不仅写得很好,而且它   以简单易懂的方式介绍难以掌握的概念。

     

打算教 - 每章都提供练习。我知道它是   总是有益于这些,但很少这样做。这本书很给出   令人信服的有趣任务。令人惊讶的是我做了大部分和   喜欢这样做。

另外,如果你想了解更多低级细节,这是我找到的最好的资源:“The Art of Multiprocessor Programming”它是用java作为代码示例编写的,它与我的C#背景很好地配合使用

PS:我有大约5年的“硬核”并行编程经验,(使用C#教唆)所以当我说“The Art of Multiprocessor Programming”摇滚时,希望你能相信我

答案 2 :(得分:2)

答案 3 :(得分:2)

并行化代码导致意外性差的一个特定原因是false sharing,如果你不知道那里发生了什么(你没有),你就不会看到它。这里有两篇文章讨论.Net的原因和补救措施:

http://msdn.microsoft.com/en-us/magazine/cc872851.aspx

http://www.codeproject.com/KB/threads/FalseSharing.aspx

Rgds GJ

答案 4 :(得分:1)

多线程有不同的方面需要不同的方法。

例如,在网络服务器上,广泛使用线程池,因为它被认为是“有利于”性能的。这样的池可能包含数百个等待投入工作的线程。使用那么多线程将导致调度程序超时工作,这对性能有害,但在Linux系统上是无法避免的。对于Windows,选择的方法是IOCP机制,它建议许多线程不大于安装的核心数。它导致应用程序成为(I / O完成)事件驱动,这意味着在轮询时不会浪费任何循环。涉及的少数线程将调度程序工作减少到最低限度。

如果对象要实现可扩展的功能(更多内核< =>更高性能),那么主要问题将是内存总线饱和。由于代码获取,数据读取和数据写入,将发生饱和。错误实现的代码将使用两个线程而不是一个线程运行得更慢。解决这个问题的唯一方法是积极减少内存总线的工作:

  • 将代码定制到最小的内存占用(=适合代码缓存),并且不调用其他函数或跳转到处。
  • 定制内存读取和写入的最小大小。
  • 通知预读机制即将进行的RAM读取。
  • 定制工作,使得核心自身缓存(L1和L2)内部工作的比例与其外部工作(L3和RAM)相比尽可能大。

以另一种方式表达:将适用的代码和数据块放入尽可能少的缓存行(每个64字节),因为最终这将决定可扩展性。如果缓存/内存系统能够每秒执行x缓存行操作,那么如果每个工作单元(=> x / 5)而不是十一(x / 11)或五十个 - 需要五个缓存行,则代码将运行得更快二(x / 52)。

实现这一目标并非易事,因为它每次都需要或多或少的独特解决方案。有些编译器可以很好地利用主机处理器的流水线操作进行指令排序。这并不一定意味着它将成为多核的良好排序。

可扩展代码的有效实现不一定非常好。推荐的编码技术和样式最终可能会妨碍代码的执行。

我的建议是通过在低级语言(例如C)中编写一个简单的多线程应用程序来测试其工作原理,该应用程序可以调整为在单线程或多线程模式下运行,然后分析代码不同的模式。您需要在指令级别分析代码。然后,您将尝试使用不同的(C)代码构造,数据组织等。您可能需要在框外思考并重新考虑算法,以使其更易于缓存。

第一次需要大量的工作。您将无法了解适用于所有多线程解决方案的内容,但您可能会了解在分析配置文件代码时不应该做什么以及需要注意什么。

答案 5 :(得分:0)

我发现此链接专门解释了问题 在影响我的CPU上的多核缓存处理 多线程程序。

http://www.multicoreinfo.com/research/intel/mem-issues.pdf

网站multicoreinfo.com一般都有很多好处 有关多核编程的信息和参考资料。