Цифровые раскопки: SIMD, x86-код и указатели на функции ======================================================== .. post:: 20, June 2022 :tags: gps-sdr, SIMD, x86, указатели на функции :category: digital-excavation :author: engineer Когда я пытался запускать свежеоткомпилированные исходники gps-sdr, то одной из первых проблем был нерабочий код SSE-функций. Вообще-то это странно! Кажется, тогда, давным-давно такой проблемы не было. А тут вызов этих функций (функций с префиксом 'sse\_') приводил к Segfault. Ещё предстоит разобраться в причинах этого. Впрочем ad hoc решением было использование аналогичных функций, написанных на чистом C++ (без каких-либо ассемблерных вставок) и имеющих префик 'x86\_'. На скорую руку и так сошло. Но во время исследований исходников gps-sdr была найдена интересная функция void Init_SIMD() в файле cpuid.cpp. .. code-block:: C :linenos: void Init_SIMD() { // if(CPU_SSE3()) // { // simd_add = &sse_add; // simd_sub = &sse_sub; // simd_mul = &sse_mul; // simd_dot = &sse_dot; // // simd_conj = &sse_conj; // simd_cacc = &sse_cacc; // simd_cmul = &sse_cmul; // simd_cmuls = &sse_cmuls; // simd_cmulsc = &sse_cmulsc; // } // else // { // simd_add = &x86_add; // simd_sub = &x86_sub; // simd_mul = &x86_mul; // simd_dot = &x86_dot; // // simd_conj = &x86_conj; // simd_cacc = &x86_cacc; // simd_cmul = &x86_cmul; // simd_cmuls = &x86_cmuls; // simd_cmulsc = &x86_cmulsc; // // } // // simd_cmag = &x86_cmag; // simd_max = &x86_max; } Задумка - хорошая! Но почему-то код закомментирован. Что ж почему бы не реализовать эту задумку?! Указатели на функции - штука полезная, хотя и не самая тривиальная (по крайней мере для меня). Разбираясь, как реализовать задумку автора, нашёл на stackoverflow (ну а где ж ещё-то?) полезный `пример `_. Итак требуется: 1. Выполнить объявление функции (указателя на функцию) в *.h-файле. 2. Выполнить описание функции (указателя на функцию) в *.cpp-файле значением по умолчанию. 3. В функции Init_SIMD() выполнить переназначение указателя на функцию (при необходимости). Для простоты сокращу пример до использования одной функции. В файле simd.h выполняется объявление указателя на функцию по имени simd_add. Этот указатель в зависимости от потребностей будет указывать либо на функцию void sse_add(int16 *A, int16 *B, int32 cnt), либо на функцию void x86_add(int16 *A, int16 *B, int32 cnt). .. code-block:: C :linenos: extern void (*simd_add)(int16 *A, int16 *B, int32 cnt); В файле cpuid.cpp выполняется определение указателя на функцию и при необходимости его переопределение в функции Init_SIMD(). Изначальное определение требуется, чтобы указатель на функцию сразу же был бы проинициализирован значением по умолчанию. .. code-block:: C :linenos: void (*simd_add)(int16 *A, int16 *B, int32 cnt) = &x86_add; void Init_SIMD() { if (0) ///if(CPU_SSE3()) { void (*simd_add)(int16 *A, int16 *B, int32 cnt) = &sse_add; //simd_add = &sse_add; } else { void (*simd_add)(int16 *A, int16 *B, int32 cnt) = &x86_add; //simd_add = &x86_add; } } Ну а так как в причинах неработоспособности SSE-функций ещё только предстоит разобраться, то вместо условия if(CPU_SSE3()) - стоит просто if (0). P.S. Надо бы ещё исследовать код, который генерирует gcc с соответствующими опциями. Есть предположение, что сам компилятор умеет в SIMD-инструкции раскладывать неплохо (уж всяко лучше меня ;) ).