Как включить поддержку инструкции POPCNT/internal на моем компьютере?

Я попытался запустить следующую программу на своем компьютере (Fedora 17 32bit). Как включить в моей системе поддержку инструкции popcnt для быстрого подсчета населения?

#include <stdio.h>
#include <nmmintrin.h>

int main(void)
{
    int pop = _mm_popcnt_u32(0xf0f0f0f0ULL);
    printf("pop = %d\n", pop);
    return 0;
}

Я скомпилировал программу и запустил ее, но получил следующее исключение:

[xiliu@xiliu tmp]$ gcc -Wall -march=corei7 -m32 -msse4.2 popcnt.c -o popcnt
[xiliu@xiliu tmp]$ ./popcnt 
Illegal instruction (core dumped)

Ниже приведена информация о моем процессоре:

[xiliu@xiliu tmp]$ cat /proc/cpuinfo 
processor   : 0
vendor_id   : GenuineIntel
cpu family  : 6
model       : 15
model name  : Intel(R) Pentium(R) Dual  CPU  T2370  @ 1.73GHz
stepping    : 13
microcode   : 0xa4
cpu MHz     : 800.000
cache size  : 1024 KB
physical id : 0
siblings    : 2
core id     : 0
cpu cores   : 2
apicid      : 0
initial apicid  : 0
fdiv_bug    : no
hlt_bug     : no
f00f_bug    : no
coma_bug    : no
fpu     : yes
fpu_exception   : yes
cpuid level : 10
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 pbe nx lm constant_tsc arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl est tm2 ssse3 cx16 xtpr pdcm lahf_lm dtherm
bogomips    : 3458.20
clflush size    : 64
cache_alignment : 64
address sizes   : 36 bits physical, 48 bits virtual
power management:

[... repeated for 2nd core ...]

person afancy    schedule 11.11.2012    source источник
comment
Это довольно ужасный пример; если вы скомпилируете с помощью gcc с включенной оптимизацией, в двоичном файле не будет инструкции popcnt, потому что распространение констант превратит ее в mov esi, 16 (godbolt.org/z/h5ObTj). Однако MSVC терпит неудачу и по-прежнему выдает инструкцию popcnt.   -  person Peter Cordes    schedule 15.10.2018


Ответы (3)


Вместо этого используйте __builtin_popcount(). не зависит от платформы.

person Hasturkun    schedule 11.11.2012

Первым процессором, поддерживающим инструкцию POPCNT, был Intel Nehalem. Похоже, у вас из линейки Core, которая старше. Предложение Хастуркуна будет работать в вашей системе, но будет реализовано с использованием нескольких инструкций вместо одной.

Если вам нужно портативное решение, а не решение для GCC, ознакомьтесь с превосходным Шона Эрона Андерсона. Bit Twiddling Hacks, на которой для этого есть хорошо оптимизированный код.

person Cory Nelson    schedule 11.11.2012
comment
Верно. Другими словами, popcnt был добавлен как часть SSE4 (а T2370 OP поддерживает только дополнительный SSE3). - person Pascal Cuoq; 11.11.2012
comment
POPCNT был представлен одновременно с SSE4.2, но не является его частью. У него есть собственный CPUID бит. - person Cory Nelson; 13.11.2012
comment
Несмотря на опасность показаться старой школой, IBM POWER5 уже имеет POPCNT. www-01. ibm.com/support/knowledgecenter/ssw_aix_71/ - person jupp0r; 13.10.2014
comment
@ jupp0r: Несмотря на опасность появления ДРЕВНЕЙ школы, мейнфреймы Control Data, такие как CDC 7300, которые я использовал для программирования в 1970-х, имели инструкцию popcount. Он работал с 60-битными словами и занимал в несколько раз больше времени, чем простые инструкции вроде ADD. - person Brendan McKay; 12.01.2016
comment
@BrendanMcKay, ты меня достал :) Cray-1 также мог делать popcnt (1975) - person jupp0r; 12.01.2016

Ваш процессор не поддерживает POPCNT. (см. https://en.wikipedia.org/wiki/SSE4) Но вы можете использовать этот бесплатный инструмент с открытым исходным кодом, чтобы определить, поддерживается ли он: https://github.com/mgorny/cpuid2cpuflags< /а>

Он возвращается, например, для Intel Core i7-3770.

CPU_FLAGS_X86: aes avx f16c mmx mmxext pclmul popcnt sse sse2 sse3 sse4_1 sse4_2 ssse3
person Jonas Stein    schedule 06.12.2017