【问题标题】:Application runs faster when not pegged to cores应用程序在不与核心挂钩时运行得更快
【发布时间】:2011-09-02 18:04:07
【问题描述】:

我有一个具有 4 个线程的应用程序,我在带有 CentOS 的 8 核 Intel 进程上运行。当我运行它的两个实例时,这两个实例的组合运行速度比 1 个实例快。此外,对于两个实例,当我不将每个线程绑定到不同的内核并将调度留给调度程序时,它们运行得更快。

按照这种逻辑,也许一个实例也运行缓慢,因为调度程序已将所有 4 个线程固定到 4 个单独的内核。当我固定 2 个实例的每个线程时,即 8 个线程固定到 8 个内核时,这两个实例加起来的时间也与一个实例的时间大致相同。

应用程序是锁密集型的,因为有频繁的共享内存访问。另请注意,否则 CPU 开销保持 0%,因此几乎没有其他进程消耗周期。

现在我的问题是这里发生了什么?我想到的一种解释是,当线程被固定到不同的内核时,它们几乎同时尝试获取互斥锁,结果发生了高争用,但是当它们被调度程序调度时,它们可能会尝试在稍微不同的时间获取互斥锁,从而减少争用。

任何意见!这真的很奇怪,因为留给调度程序,一个实例的运行速度比两个实例加起来要慢。如何编译我的基准测试结果。不会相信我的!

/proc/cpuinfo 给出的处理器信息如下。

processor   : 0
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 1
siblings    : 8
core id     : 0
cpu cores   : 4
apicid      : 16
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.15
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 1
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 0
siblings    : 8
core id     : 0
cpu cores   : 4
apicid      : 0
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5319.96
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 2
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 1
siblings    : 8
core id     : 1
cpu cores   : 4
apicid      : 18
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.04
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 3
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 0
siblings    : 8
core id     : 1
cpu cores   : 4
apicid      : 2
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.05
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 4
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 1
siblings    : 8
core id     : 2
cpu cores   : 4
apicid      : 20
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.04
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 5
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 0
siblings    : 8
core id     : 2
cpu cores   : 4
apicid      : 4
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.05
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 6
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 1
siblings    : 8
core id     : 3
cpu cores   : 4
apicid      : 22
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.03
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 7
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 0
siblings    : 8
core id     : 3
cpu cores   : 4
apicid      : 6
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.07
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 8
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 1
siblings    : 8
core id     : 0
cpu cores   : 4
apicid      : 17
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.01
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 9
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 0
siblings    : 8
core id     : 0
cpu cores   : 4
apicid      : 1
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.07
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 10
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 1
siblings    : 8
core id     : 1
cpu cores   : 4
apicid      : 19
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.04
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 11
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 0
siblings    : 8
core id     : 1
cpu cores   : 4
apicid      : 3
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.00
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 12
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 1
siblings    : 8
core id     : 2
cpu cores   : 4
apicid      : 21
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.03
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 13
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 0
siblings    : 8
core id     : 2
cpu cores   : 4
apicid      : 5
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.05
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 14
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 1
siblings    : 8
core id     : 3
cpu cores   : 4
apicid      : 23
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.02
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

processor   : 15
vendor_id   : GenuineIntel
cpu family  : 6
model       : 26
model name  : Intel(R) Xeon(R) CPU           X5550  @ 2.67GHz
stepping    : 5
cpu MHz     : 2660.076
cache size  : 8192 KB
physical id : 0
siblings    : 8
core id     : 3
cpu cores   : 4
apicid      : 7
fpu     : yes
fpu_exception   : yes
cpuid level : 11
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm
bogomips    : 5320.04
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: [8]

【问题讨论】:

  • 推测,固定线程花费的时间比它们从额外内核中获得的锁要多。运行在同一个内核上的两个线程竞争一个锁是否比运行在不同内核上的两个线程竞争同一个锁便宜,有人知道吗?还要考虑是否存在虚假共享,同一个内核上的两个线程多次访问同一个缓存行比不同内核上的两个线程多次访问同一个缓存行要便宜。
  • 您的 CPU 超线程是否已启用?尝试将进程绑定到偶数核:CPU0、CPU2、CPU6、CPU8
  • 是的 osgx,它的超线程。我会试试的。很好的建议。
  • 这个 8 核 Intel 是不是像“4 核,每个都有超线程”那样?
  • 啊,现在当我执行 /proc/interrupts 时,我还看到 16 个 CPU。超线程在这里工作:-)!

标签: c linux multithreading


【解决方案1】:

一种解释是缓存和内存架构;和数据局部性。

根据英特尔的规格查找器,对于您的 X5550 CPU,每个物理芯片有 4 个内核(和 8 个逻辑 CPU)。如果你有 16 个逻辑 CPU,那么你就有 2 个物理芯片(这对于这个 Xeon 来说是完全可能的)。更多研究表明,每个内核都有自己的 L1 和 L2 缓存,由该内核中的两个逻辑 CPU 共享。每个物理芯片都有 8 MiB 的 L3 缓存,由该芯片上的所有 4 个内核(8 个逻辑 CPU)共享。

如果逻辑 CPU 0 和 1 共享 L2 高速缓存,而逻辑 CPU 2 和 3 共享单独的 L2 高速缓存,则修改同一内存的 2 个线程可能在逻辑 CPU 0 和 1 上运行得更好(而不是逻辑 CPU 0 和 2)因为数据在一个缓存上保持“独占”状态(并且不会在不同的 L2 缓存之间反弹)。

同理,如果前 8 个逻辑 CPU 共享一个 L3 缓存,而另一组 8 个逻辑 CPU 共享一个 L3 缓存,那么修改同一内存的 8 个线程在受限于一组逻辑 CPU 时可能会运行得更好(并且不分布在具有单独 L3 缓存的单独物理芯片上)。

另一件事是,使用一对“Xeon X550”CPU,您的计算机极有可能是 ccNUMA。两个独立的内存条,其中一个内存条直接连接到第一个物理 CPU,另一个内存条直接连接到第二个物理 CPU。在这种情况下,当一个 CPU 尝试访问没有直接连接到该 CPU 的 RAM 时,它需要请求另一个 CPU(RAM 连接的位置)来获取它(而不是能够自己获取它),并且这会降低性能(大约“慢 15%”)。

Linux 确实有特殊的支持 ccNUMA 系统。它将尝试将每个进程(及其所有线程)限制在一组特定的 CPU 上,并分配直接连接到这些 CPU 的内存;为了避免“大约慢 15%”的性能损失。

如果将所有这些结合起来,一个具有 8 个线程且受 CPU 限制并不断争夺相同锁(修改这些锁所在的缓存行)的进程可能会在前 8 个逻辑 CPU 或后 8 个逻辑 CPU 上运行得更好逻辑 CPU;如果您尝试将进程的线程均匀分布在逻辑 CPU(例如 CPU 0、2 、4、6、8、10 等)。

【讨论】:

  • 布伦丹,感谢您提供如此详细的信息。你能给我一个链接,让我可以看到这个平台的完整架构,即缓存、不同内存的延迟等......其次,我想知道放置共享数据的最佳位置在哪里。假设我有少量数据共享 b/w 两个进程在两个不同的处理器上运行,进程 1 在四核处理器 0 上运行,而进程 2 在四核处理器 1 上运行,哪里是放置我的最佳位置经常访问的共享数据。有什么线索吗?
【解决方案2】:

您的 CPU 是否启用了超线程?

按照 Agner fox 的建议,尝试将进程绑定到偶数核:CPU0、CPU2、CPU6、CPU8(Linux find out Hyper-threaded core id 中有引用)

如果你将 4 个线程绑定到 CPU0-CPU3,你会将它们绑定到 2 个物理内核,并且会出现资源争用(如果同一 CPU 上有另一个 HT 线程,则 HT 线程不如物理线程快) .

在 linux 中,HT 内核是成对编号的:因此 CPU0-CPU1 是第一个物理内核的两个 HT 半部,CPU2-CPU3 是第二个物理内核,依此类推。

如果您因仅使用偶数编号的 CPU 而变慢,我的结论是您在线程之间有很多同步。与不同物理内核的线程相比,HT 线程可以快速同步。

【讨论】:

  • 我已经尝试过了,但它以某种方式让它变得更慢。我不知道这里发生了什么。这个超线程的东西让基准测试成为一场噩梦:(!
  • 线程计算什么?使用什么算法?这里必须同步吗?
  • osgx,在我看来 CPU 0-7 是核心,而 8-15 是超线程,因为我有 /proc/interrupts,58: 4451 9151 787942 534 183421 393 77119 54 0 0 0 0 0 0 0 0 IO-APIC 级 ata_piix,注意最后 8 个零。
  • IO-APIC 可以分配给前 8 个核心,与 HT 物理映射没有任何关系。这是可能的,因为两个 HT 内核都复制了一些 APIC 硬件。并且在双插槽系统的第二个插槽上分配 IO APIC 会有限制。
【解决方案3】:

一种可能的解释是,它们可以使用相同的内核(一个进入睡眠状态,另一个唤醒),因此可以共享相同的缓存,这减少了缓存未命中,因此仅凭这一点就可以显着提高性能。 CPU 花费 100% 的量程不会完全占用 CPU。引入另一个线程将使另一个线程在第一个线程处于休眠状态时运行。

【讨论】:

    【解决方案4】:

    您可能会同时受到三种影响:

    1. 您的固定实际上是在捆绑调度程序。你说你的程序很重。当一个线程未能获得锁时,它会进入睡眠状态,从而释放 CPU 以处理不同的线程。但是如果你已经固定了你的线程,那么调度程序就不能将任何有工作要做的线程移动到空闲的 CPU 上!所以你的线程固定实际上会降低性能。

    2. False sharing。当您运行多个实例以使每个实例都是自己的进程时,操作系统将为每个进程提供不同的物理内存页面(与同一进程中的两个线程不同)。这意味着进程不会意外共享缓存行。确保从多个线程访问的任何全局数据要么是只读的,要么位于其自己的缓存行上(参见 posix_memalign)。

    3. 如果你有很多锁,你的程序可能太单线程了。任何时候你使用锁来防止两个线程同时行动,你实际上是在说,“让我的程序的这一部分成为单线程的。”这样的实例太多,您最终会得到一个带有额外锁开销的单线程程序。多个实例意味着没有锁争用,因此您更接近原来的单线程性能。

    【讨论】:

      猜你喜欢
      • 2012-04-11
      • 2022-11-17
      • 2023-01-20
      • 2018-05-14
      • 1970-01-01
      • 2021-12-30
      • 2019-04-17
      • 1970-01-01
      • 2022-01-26
      相关资源
      最近更新 更多