Multithreading 如何为给定的多核体系结构优化算法

Multithreading 如何为给定的多核体系结构优化算法,multithreading,caching,optimization,multicore,computer-architecture,Multithreading,Caching,Optimization,Multicore,Computer Architecture,我想知道我应该使用什么技术来为给定的体系结构优化给定的算法。如何使用更好的缓存提高性能。如何降低缓存一致性,或者在算法/程序中应避免哪些访问模式,以便缓存一致性不会影响性能 我了解在一级缓存中使用最近缓存的数据的一些标准技术,但如何有效地在多核上使用共享缓存(如二级缓存)中的数据,从而避免更昂贵的主存访问 基本上,我感兴趣的是为了更好地映射到给定的体系结构,应该尝试利用或避免哪些数据访问模式。我可以使用什么样的数据结构,在什么样的场景中使用什么样的体系结构(具有不同级别的私有缓存和共享缓存)来提

我想知道我应该使用什么技术来为给定的体系结构优化给定的算法。如何使用更好的缓存提高性能。如何降低缓存一致性,或者在算法/程序中应避免哪些访问模式,以便缓存一致性不会影响性能

我了解在一级缓存中使用最近缓存的数据的一些标准技术,但如何有效地在多核上使用共享缓存(如二级缓存)中的数据,从而避免更昂贵的主存访问


基本上,我感兴趣的是为了更好地映射到给定的体系结构,应该尝试利用或避免哪些数据访问模式。我可以使用什么样的数据结构,在什么样的场景中使用什么样的体系结构(具有不同级别的私有缓存和共享缓存)来提高性能。谢谢。

对于给定的体系结构,我应该使用哪些技术来优化给定的算法?

微体系结构各不相同,因此了解特定处理器的详细信息。英特尔在其产品中提供了良好的文档。如果您使用的是英特尔处理器,请阅读第8.3节和第8.6节:

8.3优化指南 本节总结了调优多线程应用程序的优化准则。列出了五个方面(按重要性排序):

  • 线程同步
  • 公共汽车利用率
  • 内存优化
  • 前端优化
  • 执行资源优化
本节列出了与每个领域相关的实践。每个领域的指导原则将在后面的章节中进行更深入的讨论。大多数编码建议提高了处理器内核的性能伸缩性;由于高温热处理技术而产生的结垢。注意仅适用于一种环境的技术

8.6内存优化

缓存的高效运行是内存优化的一个关键方面。缓存的高效运行需要解决以下问题:

  • 缓存阻塞
  • 共享内存优化
  • 消除64kbyte别名数据访问
  • 防止一级缓存中的过度逐出
为了更好地映射到给定的体系结构,我应该尝试利用或避免哪些数据访问模式?

利用

当缓存已满且缓存中的访问未命中时,缓存必须收回某些内容以为新数据/代码腾出空间,收回的内容通常基于最近使用最少(LRU)的近似值。如果可能的话,您的代码应该具有强大的:

  • 尝试打包算法中时间相近的数据,使其空间(地址)相近
  • 严格打包数据,例如,当使用32位整数时,不要使用64位整数
  • 有时,“对象”(相关数据)相对于缓存线的对齐很重要。例如,如果存在一个每个64字节的对象数组,并且这些对象是随机访问的,那么在64字节边界对齐将通过不引入未使用的数据来提高缓存效率。如果对象未对齐,则每个接触的对象都会引入两条缓存线,但只需要64字节,因此传输的数据中有50%不会被使用(假设缓存线为64字节)
  • 正如@PaulA.Clayton在评论中指出的,预取数据非常重要,因为它隐藏了部分或全部内存延迟。“此外,利用基于步幅的硬件预取也非常有益。(软件预取在某些情况下也很有用。)尽早获取指针有助于提高内存级别的并行性。”
  • 为了方便硬件预取并提高缓存中数据的利用率,请仔细注意矩阵和其他大型结构的存储和访问方式。。。看
避免

  • 不经常使用的数据不应与经常使用的数据接近
  • 避免。如果两个或多个线程访问同一缓存线,但在缓存线内不共享相同的数据,并且其中至少有一个线程是写入程序,则共享错误。。。这将带来不必要的负担和延迟影响
  • 在处理旧数据之前,尽量不要使用新数据
测量

正如Andrei Alexandrescu所说,在性能调优方面,唯一正确的直觉是“我应该对此进行测量”。请熟悉缓存性能监视工具,例如:


关键原则是局部性:当您有选择时,首先处理附近的数据(避免稀疏访问),并尽快执行数据重用(对相同数据重新分组连续的过程)

对于多线程程序,原则是独立的局部性:确保线程在不相交的数据集上工作(需要/可能使用不同的副本)


除非您有很好的理由这样做,否则请远离硬件的特性。

应该提到的是,代码也是以与数据相同的方式缓存的。具有大量内联和少量跳转/调用的小而密集的代码将减少L1C缓存的压力,并最终减少L2、L3和RAM的压力,因为它们会与数据获取发生冲突


如果您使用的是超线程,则有证据表明,一个内核中两个超线程的较低优化级别(O1)将比单个高度优化(O2和更高)线程完成更多的工作。

如果内存/缓存接口首先支持关键块,将第一个使用的数据放在缓存线的开头并不具有优势。即使没有这些,优势也很小。目标是在缓存线中使用尽可能多的时间局部性数据,这