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.

Compilador de C optimizado para forzar la operación de “load-prefetch”

¿Existe alguna forma ‘estándar’ de forzar al compilador de C a no omitir la operación de ‘carga falsa’ que fuerza la ‘carga anticipada’ en la caché de la CPU?

En el lenguaje ensamblador, es simplemente una operación de carga como
mov eax,[ebx]
y el ensamblador no puede omitir esta instrucción si los datos de eax no se utilizan de ninguna manera.

Sin embargo, el compilador de optimización de C puede omitir las operaciones de carga si ve que sus datos no se utilizan en los cálculos posteriores.

Por lo tanto, existen muchas soluciones antiestéticas para el compilador de C, como realizar operaciones innecesarias con datos precargados, como sumar y tratar de ‘comparar’ su resultado, pero no es agradable y carga la CPU con instrucciones innecesarias.
Ejemplo:

long long acumulador = 0;
char *p;
for(int i = 0; i < PREFETCH_SIZE; i += 64)
{
   acumulador += *(p + i);
}
if(acumulador < some_large_dummy_value)
{
   // hacer algo realmente útil
}

¿Puede existir una ‘pragma’ especial u otra forma de forzar al compilador de C a no omitir la ‘precarga garantizada de software’ como esta?

char *p;
for(int i = 0; i < PREFETCH_SIZE; i += 64)
{
   char b = *(p + i);
}

Sé sobre mm_prefetch(), pero es ‘menos garantizado’ en la precarga de datos reales en la caché, ya que puede ser omitido si causa una falta de TLB, puede estar limitado en la ‘sobrecarga de los búferes de operaciones de memoria’, etc., etc.

El manual de optimización de Intel está lleno de ejemplos de ‘precarga de software’, pero solo están en forma de lenguaje ensamblador.

Puede estar estrechamente relacionado con preguntas sobre ‘desactivar localmente las optimizaciones del compilador’ como https://stackoverflow.com/questions/2219829/how-to-prevent-gcc-optimizing-some-statements-in-c. Pero la mayoría de las soluciones dependen del compilador. La prometedora puede ser la especificación ‘volatile’. ¿Pero solo funcionará en operaciones de escritura en memoria? ¿O también en lectura?

EDITADO: Solución final funcional:

#define CACHE_LINE_SIZE 64
void my_SWprefetch(char *p, int iSize)
{
    for(int i=0; i < iSize; i += CACHE_LINE_SIZE)
    {
        (void)*(volatile char *)(p + i);
    }
}
Tags:  , ,

Answer

  1. Avatar for davy.ai

    Hasta donde yo sé, no hay una forma estándar de obligar al compilador de C a no omitir la operación de “carga ficticia” que fuerza la “carga de prefetch” en la memoria caché de la CPU. Sin embargo, hay algunas formas de lograr el comportamiento deseado. Una forma es usar la palabra clave volatile. Al agregar la palabra clave volatile a la operación de desreferencia del puntero, se informa al compilador que el valor apuntado debe cargarse cada vez que se acceda a él, incluso si parece que el valor no se utiliza.

    Otro enfoque es utilizar ensamblador en línea, donde se pueden escribir las instrucciones necesarias en lenguaje ensamblador, incluyendo las operaciones de carga, y el compilador no las optimizará. Sin embargo, este enfoque puede comprometer la portabilidad y mantenibilidad del código.

    En general, la mejor solución puede depender de la situación y requisitos específicos, y puede requerir algo de experimentación y perfilado para determinar el enfoque óptimo.

Comments are closed.