Organizando múltiples implementaciones (para SIMD)
Este es claramente una pregunta abierta y subjetiva, pero estoy buscando diferentes ideas sobre cómo “organizar” múltiples implementaciones alternativas de las mismas funciones.
Tengo un conjunto de varias funciones que tienen implementaciones específicas para plataformas. Específicamente, cada una tiene una implementación diferente para un tipo de SIMD en particular: NEON (64 bits), NEON (128 bits), SSE3, AVX2, etc. (y una implementación sin SIMD).
Todas las funciones tienen una implementación sin SIMD. No todas las funciones están especializadas para cada tipo de SIMD.
Actualmente, tengo un archivo monolítico que utiliza muchas directivas #ifdef para implementar las especializaciones específicas de SIMD. Funcionaba cuando solo estábamos especializando algunas de las funciones para uno o dos tipos de SIMD. Ahora, se ha vuelto difícil de manejar.
Básicamente, necesito algo que funcione como una función virtual o una función sobrescrita. Las implementaciones sin SIMD están implementadas en una clase base y las especializaciones SIMD (si las hay) las sobrescribirían. Pero no quiero polimorfismo en tiempo de ejecución real. Este código es crítico en cuanto al rendimiento y muchas de las funciones pueden (y deben) ser en línea.
Algo como esto lograría lo que necesito (que sigue siendo un lío de #ifdefs).
// functions.h
void function1();
void function2();
#ifdef _ARM_NEON
#include "functions_neon64.h"
#elif SSE3
#include "functions_sse3.h"
#endif
#include "functions_unoptimized.h"
// functions_neon64.h
#ifndef FUNCTION1_IMPL
#define FUNCTION1_IMPL
void function1() {
// Implementación NEON64
}
#endif
// functions_sse3.h
#ifndef FUNCTION2_IMPL
#define FUNCTION2_IMPL
void function2() {
// Implementación SSE3
}
#endif
// functions_unoptimized.h
#ifndef FUNCTION1_IMPL
#define FUNCTION1_IMPL
void function1() {
// Implementación sin SIMD
}
#endif
#ifndef FUNCTION2_IMPL
#define FUNCTION2_IMPL
void function2() {
// Implementación sin SIMD
}
#endif
¿Alguien tiene ideas mejores?
davy.ai
Un enfoque alternativo sería utilizar la especialización de plantillas para proporcionar las diferentes implementaciones. Esto eliminaría la necesidad de #ifdefs y mejoraría la legibilidad del código.
Primero, define una función de plantilla con una implementación predeterminada/no SIMD:
“`c++
template
void funcion1() {
// Implementación no SIMD
}
Finalmente, utiliza la función de plantilla en tu código especificando el tipo SIMD deseado:
c++
funcion1<neon64>(); // llama a la especialización neon64
funcion1<sse3>(); // llama a la especialización SSE3
funcion1<int>(); // llama a la implementación predeterminada/no SIMD
Este enfoque facilita la adición de nuevas implementaciones SIMD en el futuro sin tener que modificar el código existente. También elimina la necesidad de #ifdefs y mejora la legibilidad del código.