2009-05-13 11 views
6

Según the gcc docs, memcmp no es una función intrínseca de GCC. Si quisiera acelerar el memcmp de glibc bajo gcc, necesitaría usar las características intrínsecas de nivel inferior definidas en los documentos. Sin embargo, al buscar en Internet, parece que mucha gente tiene la impresión de que memcmp es una función integrada. ¿Es para algunos compiladores y no para otros?memcmp intrínseco

+2

Echa un vistazo a memcmp desde glibc también. La relación entre GCC y glibc es bastante complicada, ya que proporciona versiones diferentes de las mismas funciones y, a veces, lucha contra ella en archivos de cabecera cuya definición se utilizará de hecho en los programas de usuario. –

Respuesta

5

Su enlace parece ser para las funciones integradas específicas de la arquitectura x86, de acuerdo con this memcmp se implementa como una arquitectura independiente integrada por gcc.

Editar:

Compilar el código siguiente con Cygwin versión gcc 3.3.1 para i686, -O2:

#include <stdlib.h> 

struct foo { 
    int a; 
    int b; 
} ; 

int func(struct foo *x, struct foo *y) 
{ 
    return memcmp(x, y, sizeof (struct foo)); 
} 

produce la siguiente salida (tenga en cuenta que la llamada a memcmp() se convierte en un 8 bytes "REPZ CMPSB"):

0: 55      push %ebp 
    1: b9 08 00 00 00   mov $0x8,%ecx 
    6: 89 e5     mov %esp,%ebp 
    8: fc      cld  
    9: 83 ec 08    sub $0x8,%esp 
    c: 89 34 24    mov %esi,(%esp) 
    f: 8b 75 08    mov 0x8(%ebp),%esi 
    12: 89 7c 24 04    mov %edi,0x4(%esp) 
    16: 8b 7d 0c    mov 0xc(%ebp),%edi 
    19: f3 a6     repz cmpsb %es:(%edi),%ds:(%esi) 
    1b: 0f 92 c0    setb %al 
    1e: 8b 34 24    mov (%esp),%esi 
    21: 8b 7c 24 04    mov 0x4(%esp),%edi 
    25: 0f 97 c2    seta %dl 
    28: 89 ec     mov %ebp,%esp 
    2a: 5d      pop %ebp 
    2b: 28 c2     sub %al,%dl 
    2d: 0f be c2    movsbl %dl,%eax 
    30: c3      ret  
    31: 90      nop  
+0

Interesante. ¿Alguna idea de si estos están optimizados en formas específicas de arquitectura? – Justin

+0

sí, lo son. Existe un conjunto intrínseco SIMD específico para hacerlo (en SSE4.2 si recuerdo correctamente). –

+3

¿Por qué no un 'repz cmpsl' de 2 palabras? O mejor aún, simplemente 'if (x-> a == y-> a && x-> b == y-> b)'? gcc es una mierda ... –

8

Tenga en cuenta que la rutina REPZ CMPSB podría no ser más rápido que memcmp de glibc. En mis pruebas, de hecho, es nunca más rápido, incluso cuando se comparan unos pocos bytes.

Ver http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43052

+1

+1 para un gran enlace! Solo estaba buscando una respuesta sobre por qué el Memcmp de libc() realizó órdenes de magnitud más rápido que un simple 'repz cmpsb'. Supuse que tenía algo que ver con la alineación, ahora sé :) – Unsigned

+0

Verdaderamente, en 4.8 'memcmp' se compila en un' jmp memcmp' con '-O3', no en ensamblaje directo. ¿Alguien puede resumir cómo puede el glibc ser más rápido? ¿Algo que ver con la alineación? –

+1

@CiroSantilli Un típico "rápido' memcmp' "compara byte por byte hasta que se alcanza un límite de alineación, luego compara palabra por palabra (típicamente el tamaño de palabra nativo, 64-bit en x86 -64), luego, si quedan bytes que no sean del tamaño de una palabra, se los compara byte por byte hasta que finalicen. Código de caso especial para verificar rápidamente tamaños pequeños también son comunes. Ver la fuente 'glibc': https://sourceware.org/git/?p=glibc.git;a=blob;f=string/memcmp.c –

0

Ahora en 2017, GCC y Clang parece tener algunas optimizaciones para tampones de tamaños 1, 2, 4, 8 y algunos otros, por ejemplo 3, 5 y múltiplo de 8.

Cuestiones relacionadas