Приложение работает быстрее, если не привязано к ядру - PullRequest
3 голосов
/ 02 сентября 2011

У меня есть приложение с 4 потоками, которое я запускаю на 8-ядерном процессоре Intel с CentOS.Когда я запускаю два экземпляра, оба экземпляра работают быстрее, чем 1 экземпляр.Более того, в двух случаях они работают быстрее, когда я не связываю каждый поток с другим ядром и оставляю планирование планировщику.

Если придерживаться этой логики, возможно, один экземпляр также работает медленно, поскольку планировщик закрепил все 4 потока на 4 отдельных ядрах.Когда я закрепляю каждый поток по 2 экземплярам, ​​то есть по 8 потоков, привязанных к 8 ядрам, объединение двух экземпляров также занимает примерно то же время, что и один экземпляр.

Приложение интенсивно блокируется, поскольку частодоступ к общей памяти.Также обратите внимание, что загрузка ЦП остается 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]

Ответы [ 4 ]

3 голосов
/ 03 сентября 2011

Одним из объяснений является архитектура кеша и памяти; и местонахождение данных.

В соответствии с поиском спецификаций Intel, для вашего процессора X5550 имеется 4 ядра (и 8 логических процессоров) на физический чип. Если у вас 16 логических процессоров, то у вас 2 физических чипа (что вполне возможно для этого Xeon). Дополнительные исследования показывают, что каждое ядро ​​имеет свои собственные кэши L1 и L2, которые совместно используются обоими логическими процессорами в этом ядре; и каждый физический чип имеет 8 МБ кэш-памяти L3, которая используется всеми 4 ядрами (8 логическими процессорами) на этом чипе.

Если логические ЦП 0 и 1 совместно используют кэш L2, а логические ЦП 2 и 3 - отдельный кэш L2, тогда 2 потока, модифицирующих одну и ту же память, могут работать лучше на логических ЦП 0 и 1 (а не на логических ЦП 0 и 2) потому что данные остаются в «исключительном» состоянии в одном кеше (и не пересекаются между разными кэшами L2).

Таким же образом, если первые восемь логических процессоров совместно используют кэш L3, а другая группа из восьми логических процессоров совместно использует кэш L3, тогда 8 потоков, модифицирующих ту же самую память, могут работать лучше, если ограничены одной группой логических процессоров ( и не распространяется на отдельные физические чипы с отдельными кэшами L3).

Другое дело, что с парой процессоров "Xeon X550" очень вероятно, что ваш компьютер ccNUMA. Два отдельных банка памяти, где один банк памяти напрямую подключен к первому физическому ЦП, а другой банк памяти напрямую подключен ко второму физическому ЦП. В этом случае, когда ЦП пытается получить доступ к ОЗУ, которое напрямую не связано с этим ЦП, ему необходимо попросить другой ЦП (к которому подключено ОЗУ) извлечь его (а не получить его самостоятельно), и это снижает производительность (примерно на 15% медленнее).

Linux имеет специальную поддержку систем ccNUMA. Он будет пытаться ограничить каждый процесс (и все его потоки) определенной группой процессоров и выделить память, которая напрямую связана с этими процессорами; в попытке избежать такого «примерно на 15% более медленного» снижения производительности.

Если вы объедините все это, процесс с 8 потоками, которые связаны с ЦП и постоянно борется за одни и те же блокировки (изменяя строки кэша там, где эти блокировки), вероятно, будет работать лучше на первых 8 логических ЦП или на последних 8 логические процессоры; и будет возникать относительно высокая проблема производительности (может быть такая же плохая, как «на 30% медленнее», когда вы объедините штраф NUMA и проблему отказов кэша), если вы попытаетесь равномерно распределить потоки процесса по логическим процессорам (например, процессорам 0, 2). , 4, 6, 8, 10 и т. Д.).

3 голосов
/ 02 сентября 2011

Включена ли ваша CPU Hyper-Threading?

Попробуйте привязать процессы к четным ядрам: CPU0, CPU2, CPU6, CPU8, как это было предложено Агнером Фоксом (цитата в Linux: узнайте, что Hyper-Threading Core ID )

Если вы связали 4 потока с CPU0-CPU3, вы свяжете их с 2 физическими ядрами, и возникнет конфликт за ресурсы (HT-поток не так быстр, как физический поток, ЕСЛИ есть другой HT-поток наодин и тот же процессор).

В Linux ядра HT нумеруются попарно: таким образом, CPU0-CPU1 - это две половины HT первого физического ядра, CPU2-CPU3 - второго и т. д.

Если вы получаете замедление от использования только четных процессоров, я заключаю, что у вас много синхронизации между потоками.HT-потоки могут быть синхронизированы быстрее, чем потоки разных физических ядер.

0 голосов
/ 30 августа 2012

Вы, вероятно, страдаете от комбинации трех эффектов:

  1. Ваш пиннинг фактически связывает руки планировщика.Вы сказали, что ваша программа слишком тяжелая.Когда поток не может получить блокировку, он переходит в спящий режим, освобождая процессор для обработки другого потока.Но если вы закрепили свои потоки, то планировщик не может переместить ни один из потоков, которые должны работать, в свободный процессор!Таким образом, закрепление вашей нити может фактически снизить производительность.

  2. Ложное совместное использование .Когда вы запускаете несколько экземпляров, так что каждый из них является своим собственным процессом, ОС собирается предоставить каждому процессу разные страницы физической памяти (в отличие от двух потоков в одном и том же процессе).Это означает, что процессы не могут случайно совместно использовать строки кэша.Убедитесь, что любые глобальные данные, к которым обращаются из нескольких потоков, доступны только для чтения или в отдельной строке кэша (см. Posix_memalign).

  3. Если у вас много блокировок, ваша программа может простослишком однопоточный.Каждый раз, когда вы используете блокировки для предотвращения одновременной работы двух потоков, вы, по сути, говорите: «сделайте эту часть моей программы однопоточной».Слишком много примеров этого, и в итоге вы получите однопоточную программу с дополнительными накладными расходами блокировок.Несколько экземпляров означают отсутствие конфликта блокировок, поэтому вы приближаетесь к своей первоначальной однопоточной производительности.

0 голосов
/ 02 сентября 2011

Одно из возможных объяснений состоит в том, что они могут использовать одно и то же ядро ​​(одно переходит в спящий режим, другое просыпается), поэтому они могут использовать один и тот же кэш, что сокращает потери в кеше и, следовательно, значительно повышает производительность только этого. Процессор, тратящий 100% своего количества, не будет загружать процессор полностью. Добавление другого потока приведет к тому, что другой поток запустится, пока первый спит с любым действием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...