【问题标题】:Memory considerations with multithreading多线程的内存注意事项
【发布时间】:2012-02-05 00:05:29
【问题描述】:

我正在 C/C++ 上实现 am 算法来处理一些向量,我认为让它并行可能是一个好主意,因为我正在使用多核 CPU。我有一些使用 GPGPU 的经验,糟糕的内存访问会破坏整个性能,我是否还需要考虑 CPU 上的内核之间的任何特殊访问布局?

谢谢

【问题讨论】:

  • 简短回答:是的。即使没有多线程,CPU 也会有一些非常讨厌的性能问题。示例:thisthis。多线程只会让事情变得更复杂。
  • 如果您没有将 GPGPU 用于算术密集型计算(这是它们的设计目的),那么您可能遇到了内存访问限制的问题。但是,就多线程而言,与内存访问延迟相比,您对上下文切换和同步(这通常是并发编程的最大问题)的关注要多得多。
  • @Lirik:这完全取决于所涉及工作的规模。如果向量很短并且工作量很小,则上下文切换和同步可能是一个问题。如果向量很长并且工作大量的内存组织,缓存操作和代码调整就是一切。

标签: c++ multithreading performance memory cpu


【解决方案1】:

在使用多处理器设置时,您可能会遇到许多与内存相关的问题,其中一些问题可能会减慢应用程序的爬行速度。

您需要大致了解您的盒子上的缓存行大小并尝试 2 件事:

  1. 限制单个线程以接近的时间顺序访问的数据缓存行(尤其是您写入的缓存行)的数量。即,避免“弄脏”更多的缓存行。
  2. 避免像瘟疫一样让两个单独的线程“同时”访问同一个数据缓存行,其中一个写入。

(如果您正在处理必须分页的大型数据结构,上述两条规则也适用于数据页。)

在可能的情况下,为每个线程设置单独的工作数据结构(尤其是堆),而不是共享数据。特别要注意所有线程都更新的公共计数器,并且(显然)避免锁定和信号量,除非在您绝对需要同步线程的关键时刻。

【讨论】:

  • @Hot_Licks,小调整:例如避免“触摸”(读取)或“弄脏”(写入)比您必须的更多的缓存行。
  • @KrazyGlew - “限制单个线程以接近的时间顺序访问的数据缓存行(尤其是您写入的缓存行)的数量。”
【解决方案2】:

@Hot_Licks:实际上,如果线程是运行在同一个内核上的两个超线程,那么让不同的线程访问它们是没有问题的,无论是读还是写。干净的线条在同一英特尔 CPU 上的硬件线程之间免费共享。即使是脏行也非常便宜地共享-尽管如果一个人在读取数据的同时另一个人正在写入数据,您可以获得 MOnukes。 (奇怪的是,如果两个这样的硬件/超线程同时写入,则不会受到惩罚。)

使用 AMD 唯一的“线程”CPU Bulldozer,我认为写入共享的成本更低。

但这仅适用于硬件线程,例如Intel 超线程或逻辑处理器,在相同的物理处理器上运行。如果它们在不同的物理处理器上运行,则没有胜利。由于大多数软件线程包都是随意迁移线程的,所以你的规则还不错。

尽管如此,您仍然希望最小化 (a) 单个线程访问的行数,以及 (b) 多个线程访问的总行数,即使不被其他线程共享。由于缓存——MLC、LLC——是一种有限的资源。但你是对的 - 一旦你错过了缓存......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    • 2011-02-19
    • 2010-11-12
    相关资源
    最近更新 更多