Function Template Alias

I created a processor manager that compiles the same functions with different compilation options into different object files. In order for my code to have access to the same functions in different object files, I need to give the functions in each object file a different name.

In C (or C ++), I would do something similar in the header file for function declarations.

typedef float MyFuncType(float a); MyFuncType myfunc_SSE2, myfunc_SSE41, myfunc_AVX, myfunc_AVX2, myfunc_AVX512 

But now I need function templates for declarations. My real code is now more like this

 //kernel.h template <typename TYPE, unsigned N, typename VALUES> void foo_SSE2(int32_t *buffer, VALUES & v); template <typename TYPE, unsigned N, typename VALUES> void foo_SSE41(int32_t *buffer, VALUES & v); ... template <typename TYPE, unsigned N, typename VALUES> void foo_AVX512(int32_t *buffer, VALUES & v); #if INSTRSET == 2 // SSE2 #define FUNCNAME foo_SSE2 #elif INSTRSET == 5 // SSE4.1 #define FUNCNAME foo_SSE41 ... #if INSTRSET == 9 // AVX512 #define FUNCNAME foo_AVX512 #endif 

These are only ads in the header file. Function definitions are in a separate source file, which is compiled into another object file for each function name. The definitions look something like this.

 //kernel.cpp #include "kernel.h" template<typename TYPE, unsigned N, typename VALUES> void FUNCNAME(int32_t *buffer, VALUES & v) { //code } 

Then i will compile this

 gcc -c -O3 -msse2 kernel.cpp -o kernel_sse2.o gcc -c -O3 -msse4.1 kernel.cpp -o kernel_sse41.o ... gcc -c -O3 -mavx512f kernel.cpp -o kernel_avx512.o gcc -O3 main.cpp kernel_sse2.o kernel_sse41.o ... kernel_avx512.o 

The main.cpp file is another source file that must know function declarations so that the linker can associate them with definitions in other object files. Looks like this

 void dispatch(void) { int iset = instrset_detect(); if (iset >= 9) { fp_float1 = &foo_AVX512<float,1>; } else if (iset >= 8) { fp_float1 = &foo_AVX2<float,1>; } ... else if (iset >= 2) { fp_float1 = &foo_SSE2<float,1>; } } int main(void) { dispatch(); fp_float1(buffer, values); } 

But in my kernel.h file, it is annoying (and error prone) to repeat this for every change to the function name. I want something like the following (which, as I know, does not work).

 template <typename TYPE, unsigned N, typename VALUES> typedef void foo(int32_t *buffer, VALUES & v); foo foo_SSE2, foo_SSE41, foo_SSE_AVX, foo_AVX2, foo_AVX512 

Is there an ideal way to do this that separates declarations and definitions and allows me to simply rename identical declarations of template functions?

+2
source share
1 answer

This is similar to a preprocessor application:

 #define EMIT_FUNCTION_PROTOTYPE(func_name, func_suffix) \ template<typename TYPE, unsigned N, typename VALUES> \ void func_name ## func_suffix (int32_t *buffer, VALUES & v) #define EMIT_FUNCTION_PROTOTYPES(func_name) \ EMIT_FUNCTION_PROTOTYPE(func_name, _SSE2); \ EMIT_FUNCTION_PROTOTYPE(func_name, _SSE41); \ EMIT_FUNCTION_PROTOTYPE(func_name, _AVX); \ EMIT_FUNCTION_PROTOTYPE(func_name, _AVX2); \ EMIT_FUNCTION_PROTOTYPE(func_name, _AVX512) 

Then it is just single-line to generate all prototypes in your header file:

 EMIT_FUNCTION_PROTOTYPES(foo); // expands to: // template <typename TYPE, unsigned N, typename VALUES> // void foo_SSE2(int32_t *buffer, VALUES & v); // // template <typename TYPE, unsigned N, typename VALUES> // void foo_SSE41(int32_t *buffer, VALUES & v); // // template <typename TYPE, unsigned N, typename VALUES> // void foo_AVX(int32_t *buffer, VALUES & v); // // template <typename TYPE, unsigned N, typename VALUES> // void foo_AVX2(int32_t *buffer, VALUES & v); // // template <typename TYPE, unsigned N, typename VALUES> // void foo_AVX512(int32_t *buffer, VALUES & v); 

I do not think that this is a huge benefit, but it should give you what you want.

+1
source

Source: https://habr.com/ru/post/988095/


All Articles