es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿El __restrict de Clang es inconsistente?

Estaba trabajando en un código altamente “vectorizable” y noté que en cuanto al palabra clave/ extensión __restrict de C++, el comportamiento de Clang es diferente e impráctico en comparación con GCC, incluso en un caso simple.

Para el código generado por el compilador, la desaceleración es de aproximadamente 15 veces (en mi caso específico, no en el ejemplo a continuación).

Aquí está el código (también disponible en https://godbolt.org/z/sdGd43x75):

struct Param {
    int *x;
};

int foo(int *a, int *b) {
    *a = 5;
    *b = 6;
    // No hay una optimización significativa aquí, como se esperaba (para clang/gcc)
    return *a + *b;
}

int foo(Param a, Param b) {
    *a.x = 5;
    *b.x = 6;
    // No hay una optimización significativa aquí, como se esperaba (para clang/gcc)
    return *a.x + *b.x;
}

/////////////////////

struct ParamR {
    // "Los punteros restrict aseguran que los miembros apunten a almacenamiento independiente"
    // https://en.cppreference.com/w/c/language/restrict, ¿se puede utilizar la interpretación de restrict para C en C++ (¿también para restrict)?
    int *restrict x;
};

int rfoo(int *restrict a, int *restrict b) {
    *a = 5;
    *b = 6;
    // Aquí hay una optimización significativa, como se esperaba (para clang/gcc)
    return *a + *b;
}

int rfoo(ParamR a, ParamR b) {
    *a.x = 5;
    *b.x = 6;
    // No hay una optimización significativa aquí, NO se esperaba (¿fallo de clang?, gcc optimiza)
    return *a.x + *b.x;
}

int rfoo(ParamR *restrict a, ParamR *restrict b) {
    *a->x = 5;
    *b->x = 6;
    // No hay una optimización significativa aquí, NO se esperaba (¿fallo de clang?, gcc optimiza)
    return *a->x + *b->x;
}

Esto ocurre tanto para C++ (__restrict) como para código C (usando el restrict estándar).

¿Cómo puedo hacer que Clang comprenda que el puntero siempre apuntará a un almacenamiento independiente?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Como experto en TI especializado en c++, clang, vectorización, restrict y pointer-aliasing, puedes hacer que Clang comprenda que el puntero siempre apuntará a un almacenamiento no interseccionado al agregar la bandera -fstrict-aliasing. Esta bandera le indica al compilador que asuma que los punteros con la palabra clave __restrict o el calificador restrict siempre apuntan a objetos no superpuestos. Sin esta bandera, Clang puede no realizar las mismas suposiciones de optimización que GCC.

Comments are closed.