2010-10-03 13 views
15

¿Cuál es el equivalente a __builtin_popcount que se encuentra en GCC y Clang, para MSVC-10?MSVC equivalente a __builtin_popcount?

+1

Enlace: http://stackoverflow.com/questions/109023/best-algorithm-to-count-the-number-of-set-bits-in-a-32-bit-integer –

+0

Eche un vistazo a [ estos] (http://msdn.microsoft.com/en-us/library/bb385231 (v = vs.90) .aspx) intrínsecos (o la [versión SSE4] (http://msdn.microsoft.com/en -us/library/bb531475% 28v = VS.90% 29.aspx)), de lo contrario siempre puede usar algo de [aquí] (http://chessprogramming.wikispaces.com/Population+Count) – Necrolis

Respuesta

10

Usando las observaciones presentadas:

+0

Tenga cuidado con esto; no funcionará con CPU ARM o CPU x86 que no admitan el conjunto de instrucciones ABM. – nemequ

8

Con este fragmento de código se obtiene la orden interna del CCG en la construcción con MSVC:

#ifdef _MSC_VER 
# include <intrin.h> 
# define __builtin_popcount __popcnt 
#endif 

(obras de Visual Studio 2008).

+1

Es '_MSC_VER' no '__MSC_VER' – lz96

1

Los incluso todas las CPU x86 __popcount intrínseca mencionados anteriormente no funciona en ARM, o (requiere el conjunto de instrucciones ABM). No deberías usarlo directamente; en cambio, si está en x86/amd64, debe usar el intrínseco __cpuid para determinar en tiempo de ejecución si el procesador admite popcnt.

Tenga en cuenta que probablemente no desee emitir un cpuid para cada llamada popcnt; querrás almacenar el resultado en alguna parte. Si su código siempre va a ser de subproceso único, esto es trivial, pero si tiene que ser seguro para subprocesos, tendrá que usar algo como un One-Time Initialization. Sin embargo, eso solo funcionará con Windows ≥ Vista; si necesita trabajar con versiones anteriores, tendrá que hacer las suyas propias (o usar algo de un tercero).

Para máquinas sin ABM (o si la detección del tiempo de ejecución no lo vale), hay varias versiones portátiles en Bit Twiddling Hacks (busque "Contar bits establecidos"). Mi versión favorita funciona para cualquier tipo T hasta 128 bits:

v = v - ((v >> 1) & (T)~(T)0/3);       // temp 
v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3);  // temp 
v = (v + (v >> 4)) & (T)~(T)0/255*15;      // temp 
c = (T)(v * ((T)~(T)0/255)) >> (sizeof(T) - 1) * CHAR_BIT; // count 

Si desea una versión drop-in puede utilizar the builtin module in portable-snippets (información completa: portátil de fragmentos es uno de mis proyectos), que debe trabajar prácticamente en cualquier lugar.

+0

No es necesario ser elegante con la detección de CPU. Hazlo antes de comenzar cualquier subproceso, p. con 'static const cpuid_result = cpuid();' para que se ejecute al inicio del programa. –

+0

Interesante versión genérica del bithack popcount. (Consulte https://stackoverflow.com/a/109025/224132 para las preguntas y respuestas canónicas). –