Мое предложение будет составлять отдельный блок для каждого набора команд (например, Xnosse.o Xsse3.o Xsse4.o и т. Д.) И использовать для этого автоматический диспетчер. Пользователь должен получить максимальную производительность для своего ПК и не заботиться о внутренней детализации.
С момента написания кода в библиотеке вы можете автоматически принять решение о загрузке с помощью функции init, которая будет вызываться при загрузке библиотеки. Вы также можете принять это решение только в первый раз, когда функция фактически вызвана, это для ленивой привязки.
Вот пример кода (только gcc!)
единиц компиляции:
//Xnosse.c
void do_some_math_stuff_no_sse(int x, int y)
{
...do some sophisticated math stuff with no sse support
}
void do_some_other_math_stuff_no_sse(int x, int y)
{
...do some other sophisticated math stuff with no sse support
}
//Xsse3.c
void do_some_math_stuff_sse3(int x, int y)
{
...do some sophisticated math stuff with sse3 support
}
void do_some_other_math_stuff_sse3(int x, int y)
{
...do some other sophisticated math stuff with sse3 support
}
//Xsse4.c
void do_some_math_stuff_sse4(int x, int y)
{
...do some sophisticated math stuff with sse4 support
}
void do_some_other_math_stuff_sse4(int x, int y)
{
...do some other sophisticated math stuff with sse4 support
}
Сейчас в библиотеке:
//my_math.h
/* Following definitions are in my_math.c */
extern void (*do_some_math_stuff)(int x, int, y);
extern void (*do_some_other_math_stuff)(int x, int y);
//my_math.c
void not_set(int x, int y)
{
// If you don't want to use the constructor for any reason,
// say you want lazy binding, this will do the trick as our
// functions do_math_stuff and do_other_math_stuff are initialized
// to this one
setup();
}
void (*do_some_math_stuff)(int x, int, y) = not_set;
void (*do_some_other_math_stuff)(int x, int y) = not_set;
int detect_sse()
{
..Do runtime detection of sse version
}
/* The following function will be called when your library loads */
void __attribute__ ((constructor)) setup(void)
{
if (detect_sse() == 0)
{
do_some_math_stuff = do_some_math_stuff_no_sse;
do_some_other_math_stuff = do_some_other_math_stuff_no_sse;
}
else if (detect_sse() == 3)
{
do_some_math_stuff = do_some_math_stuff_sse3;
do_some_other_math_stuff = do_some_other_math_stuff_sse3;
}
else if (detect_sse() == 4)
{
do_some_math_stuff = do_some_math_stuff_sse4;
do_some_other_math_stuff = do_some_other_math_stuff_sse4;
}
}
Если вы хотите ленивым связывание, удалите конструктор decorater из установки и компиляции с:
gcc -Wall -shared -fPIC -o libmy_math.so my_math.c Xnosse.c Xsse3.c Xsse4.c
Если вы хотите, чтобы динамический диспетчер работал, когда загрузка библиотеки использует следующие дополнительные параметры для g cc:
gcc -Wall -shared -Wl,-init,setup -fPIC -o libmy_math.so my_math.c Xnosse.c Xsse3.c Xsse4.c
3 просто неприемлемо, нет ifs или buts здесь. –
@ н.м. Я раньше не работал с указателями функций, поэтому все трое казались довольно неэлегантными. Следовательно, вопрос. –