Pregunta

No veo ninguna diferencia en el código de gcc para los punteros de restricción.

archivo1

void test (int *a, int *b, int *c)
{
  while (*a)
  {
    *c++ = *a++ + *b++; 
  }
}

archivo2

void test (int *restrict a, int *restrict b, int *restrict c)
{
  while (*a)
  {
    *c++ = *a++ + *b++;
  }
}

compilar con

  gcc -S -std=c99 -masm=intel file1.c
  gcc -S -std=c99 -masm=intel file2.c

archivo1.s y archivo2.s ambos son iguales, excepto el .file línea, que indica el nombre del archivo:

    .file   "file1.c"
    .text
    .globl  test
    .type   test, @function
test:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    movq    %rsi, -16(%rbp)
    movq    %rdx, -24(%rbp)
    jmp .L2
.L3:
    movq    -8(%rbp), %rax
    movl    (%rax), %edx
    movq    -16(%rbp), %rax
    movl    (%rax), %eax
    addl    %eax, %edx
    movq    -24(%rbp), %rax
    movl    %edx, (%rax)
    addq    $4, -24(%rbp)
    addq    $4, -8(%rbp)
    addq    $4, -16(%rbp)
.L2:
    movq    -8(%rbp), %rax
    movl    (%rax), %eax
    testl   %eax, %eax
    jne .L3
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   test, .-test
    .ident  "GCC: (GNU) 4.6.3 20120306 (Red Hat 4.6.3-2)"
    .section    .note.GNU-stack,"",@progbits

Ambos códigos se leen de la memoria y luego asignan la ubicación de la memoria señalada por a a b.donde esperaba el restrict La versión no volverá a leer las direcciones de a y b, y las direcciones de a y b se incrementará en el registro y al final se escribirá en la memoria.

¿Hay algo malo que estoy haciendo?¿O está bien la selección del ejemplo?

Lo he probado con diferentes interruptores. -O0, -O1, -O2, -O3, -Ofast, y -fstrict-aliasing con los mismos resultados idénticos para ambos archivos.

Nota: gcc --version = gcc (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2)

EDITAR Código cambiado.

¿Fue útil?

Solución

El caso es que la siguiente expresión:

    *c++ = *a++ + *b++;

De todos modos, prácticamente necesita eliminar la referencia a todos los punteros en cada iteración del bucle, ya que los punteros cambian en cada iteración.No hay ningún beneficio al usar restrict.

Intente cambiar la línea dentro del bucle a:

    *c++ = *a++ + *b;

(Es posible que también deba habilitar optimizaciones como -O2).

Verás eso en el restrict caso se carga *b en un registro una vez, mientras que en el caso sin restricciones necesita cargarse a través del puntero en cada iteración del bucle porque no sabe si o no c alguna vez alias b.

Otros consejos

Sólo estás leyendo uno de los consejos, por lo que restrict no importa.

Ver este ejemplo donde sí importa porque los punteros pueden alias los mismos datos, y los datos se escriben y leen a través de ambos punteros.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top