多线程时的内存考虑

3
我正在使用C/C++实现一个处理向量的算法,考虑到我正使用多核CPU,所以想将它并行化。我有一些GPGPU的经验,那里不良的内存访问会破坏整个性能,那么在CPU核之间是否需要考虑特殊的访问布局呢?
谢谢。

2
简短回答:是的。即使没有多线程,CPU也可能存在一些非常棘手的性能陷阱。例如:这个这个。多线程只会让事情更加复杂。 - Mysticial
如果你没有使用GPGPU进行算术密集型计算(这是它们的设计目的),那么你可能会遇到内存访问限制的问题。然而,关于多线程,你将更加关注上下文切换和同步(这通常是并发编程中最大的问题),而不是内存访问延迟。 - Kiril
@Lirik:这完全取决于工作涉及的规模。如果向量很短,且几乎没有工作上下文切换和同步问题,则可能存在问题。如果向量很长且工作量很大,则内存组织、缓存操作和代码调整都是至关重要的。 - Olof Forshell
2个回答

5

在多处理器设置中,可能会遇到一些与内存相关的问题,其中一些问题会使应用程序变得非常缓慢。

您需要大致了解盒子上的高速缓存行大小,并尝试做到以下两点:

  1. 限制单个线程在短时间内访问的数据缓存行数(特别是您写入的缓存行)。 即,避免“弄脏”比必须多的缓存行。
  2. 像瘟疫一样避免两个单独的线程“同时”访问同一个数据缓存行,其中任何一个线程都有写入操作。

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

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


@Hot_Licks,小调整:例如,避免比必要的更多地“触及”(读取)或“弄脏”(写入)缓存行。 - Krazy Glew
@KrazyGlew - “限制单个线程在紧密时间序列中访问的数据缓存行数(特别是写入的缓存行数)。” - Hot Licks

1

@Hot_Licks: 实际上,如果线程是在同一个核心上运行的两个超线程,则不管是读还是写,让不同的线程访问它们都没有问题。在同一台Intel CPU上,干净的缓存行可以在硬件线程之间免费共享。即使是脏缓存行也可以非常便宜地共享 - 尽管如果一个人正在读取数据,而另一个人正在写入数据,可能会出现争用。 (奇怪的是,如果两个这样的硬件/超线程同时写入,则没有惩罚。)

对于AMD唯一的“多线程”CPU Bulldozer,我认为共享写入成本甚至更低。

但是,这仅适用于在同一物理处理器上运行的硬件线程,例如Intel超线程或逻辑处理器。如果它们在不同的物理处理器上运行,则没有优势。由于大多数软件线程包会任意迁移线程,因此您的规则并不那么严格。

尽管如此,您仍然希望最小化(a)单个线程访问的行数和(b)多个线程访问的总行数,即使其他线程没有共享。因为缓存 - MLC,LLC - 是有限的资源。但是您是正确的 - 一旦缺少缓存...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接