gpt4 book ai didi

c - 多线程和 CPU 缓存

转载 作者:太空狗 更新时间:2023-10-29 16:29:39 26 4
gpt4 key购买 nike

我正在使用多线程在 C 中实现图像过滤操作,并使其尽可能优化。不过我有一个问题:如果一个内存被线程 0 访问,同时如果同一内存被线程 1 访问,它会从缓存中获取它吗?这个问题源于这两个线程可能运行在 CPU 的两个不同核心中的可能性。所以另一种表达方式是:所有内核是否共享相同的公共(public)高速缓存?

假设我有如下的内存布局

整数输出[100];

假设有 2 个 CPU 核心,因此我生成了两个线程来同时工作。一种方案可能是将内存分成两个 block ,0-49 和 50-99,让每个线程在每个 block 上工作。另一种方法是让 thread-0 在偶数索引上工作,如 0 2 4 等等......而另一个线程在奇数索引上工作,如 1 3 5 ....后一种技术更容易实现(特别是对于 3D数据),但我不确定我是否可以通过这种方式有效地使用缓存。

最佳答案

这个问题的答案在很大程度上取决于架构和缓存级别,以及线程实际运行的位置。

例如,最近的 Intel 多核 CPU 有一个针对每个内核的 L1 缓存,以及一个在同一 CPU 封装中的内核之间共享的 L2 缓存;然而,不同的 CPU 包将有自己的二级缓存。

即使您的线程在同一个包中的两个内核上运行,如果两个线程都访问同一缓存行中的数据,您也会让该缓存行在两个 L1 缓存之间跳动。这效率非常低,您应该设计算法来避免这种情况。


一些评论询问了如何避免这个问题。

从本质上讲,它真的不是特别复杂 - 您只是想避免两个线程同时尝试访问位于同一缓存行上的数据,其中至少有一个线程正在写入数据。 (只要所有线程都只读取数据,就没有问题 - 在大多数架构上,只读数据可以存在于多个缓存中)。

为此,您需要知道缓存行大小 - 这因架构而异,但目前大多数 x86 和 x86-64 系列芯片使用 64 字节缓存行(有关其他架构,请参阅您的架构手册)。您还需要知道数据结构的大小。

如果您要求您的编译器将感兴趣的共享数据结构与 64 字节边界对齐(例如,您的数组 output),那么您知道它将从缓存的开头开始行,你还可以计算后续缓存行边界在哪里。如果您的 int 是 4 个字节,那么每个缓存行将恰好包含 8 个 int 值。只要数组从缓存行边界开始,output[0]output[7] 就会在一个缓存行上,而 output[8] 通过 output[15] 进行下一步。在这种情况下,您可以设计自己的算法,使每个线程都处理相邻 int 值 block ,该值是 8 的倍数。

如果您要存储复杂的struct 类型而不是普通的int,则pahole实用程序将是有用的。它将分析编译二进制文件中的 struct 类型,并向您显示布局(包括填充)和总大小。然后,您可以使用此输出调整您的 struct - 例如,您可能想要手动添加一些填充,以便您的 struct 是缓存行大小的倍数。

在 POSIX 系统上,posix_memalign() 函数可用于分配具有指定对齐方式的内存块。

关于c - 多线程和 CPU 缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4802565/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com