Создание DLL для использования в LabVIEW

Простейшие вопросы в области инженерной разработки
Аватара пользователя
IvanLis

Activity Professionalism Tutorials Gold Man of the year 2012
Автор
guru
guru
Сообщения: 5501
Зарегистрирован: 02 дек 2009, 17:44
Награды: 7
Версия LabVIEW: 2015, 2016
Откуда: СССР
Благодарил (а): 32 раза
Поблагодарили: 93 раза

Re: Создание DLL для использования в LabVIEW

Сообщение IvanLis »

Над векторными вычислениями я думал уже, но это следующий этап.
Сейчас сделал предварительный расчет SIN и COS, в основном цикле использую уже готовые значения.
Снимок экрана от 2024-07-01 12-07-20.png
Никогда не задумывался, что такие элементарные операции требуют столько времени :crazy:
Аватара пользователя
IvanLis

Activity Professionalism Tutorials Gold Man of the year 2012
Автор
guru
guru
Сообщения: 5501
Зарегистрирован: 02 дек 2009, 17:44
Награды: 7
Версия LabVIEW: 2015, 2016
Откуда: СССР
Благодарил (а): 32 раза
Поблагодарили: 93 раза

Re: Создание DLL для использования в LabVIEW

Сообщение IvanLis »

FMA почему то проигрывает, пробовал компилировать по разному и проверял в разных OS.
Проигрывает всегда, но разница в Linux меньше.
Снимок экрана от 2024-07-01 13-21-07.png

Код: Выделить всё

inline void TestNoFMA(float a[], float b[], float c[], float res[], int Size)
{
   int i;
	
   for(i=0; i < Size; i++) {
      res[i] =  a[i] * b[i] + c[i];
   }
}

inline void TestYesFMA(float a[], float b[], float c[], float res[], int Size)
{
   int i;
	
   for(i=0; i < Size; i++) {
      res[i] =  fmaf(a[i], b[i], c[i]);
   }
}
AndreyDmitriev

Activity Professionalism Tutorials Gold Black
VIP
VIP
Сообщения: 1372
Зарегистрирован: 03 фев 2010, 00:42
Награды: 6
Версия LabVIEW: 6.1 - 2024
Откуда: Германия
Благодарил (а): 1 раз
Поблагодарили: 59 раз
Контактная информация:

Re: Создание DLL для использования в LabVIEW

Сообщение AndreyDmitriev »

IvanLis писал(а): 01 июл 2024, 13:23 FMA почему то проигрывает, пробовал компилировать по разному и проверял в разных OS.
Проигрывает всегда, но разница в Linux меньше.
Снимок экрана от 2024-07-01 13-21-07.png

Код: Выделить всё

inline void TestNoFMA(float a[], float b[], float c[], float res[], int Size)
{
   int i;
	
   for(i=0; i < Size; i++) {
      res[i] =  a[i] * b[i] + c[i];
   }
}

inline void TestYesFMA(float a[], float b[], float c[], float res[], int Size)
{
   int i;
	
   for(i=0; i < Size; i++) {
      res[i] =  fmaf(a[i], b[i], c[i]);
   }
}
Там много факторов, начиная от пропускной способности памяти, в которую обычно и упирается на больших массивах, и заканчивая тем, что не стоит гонять это дело по невыровненным данным.
Если данных немного, чтоб они из кеша брались, то выигрыш в общем есть, особенно если цикл развернуть, хотя б вчетверо:

Код: Выделить всё

SINECOSINE_API int fnNoFMACompute(int n)
{
    for (int i = 0; i < n; i++) dst[i] = a[i] * b[i] + c[i];
    return 0;
}


SINECOSINE_API int fnFMACompute(int n)
{
    // Perform FMA using AVX2
    for (int i = 0; i < n; i += 16) {
        __m256d va = _mm256_load_pd(&a[i]);
        __m256d vb = _mm256_load_pd(&b[i]);
        __m256d vc = _mm256_load_pd(&c[i]);
        __m256d va1 = _mm256_load_pd(&a[i + 4]);
        __m256d vb1 = _mm256_load_pd(&b[i + 4]);
        __m256d vc1 = _mm256_load_pd(&c[i + 4]);
        __m256d va2 = _mm256_load_pd(&a[i + 8]);
        __m256d vb2 = _mm256_load_pd(&b[i + 8]);
        __m256d vc2 = _mm256_load_pd(&c[i + 8]);
        __m256d va3 = _mm256_load_pd(&a[i + 12]);
        __m256d vb3 = _mm256_load_pd(&b[i + 12]);
        __m256d vc3 = _mm256_load_pd(&c[i + 12]);

        // Perform FMA: res[i] = a[i] * b[i] + c[i]
        __m256d vres = _mm256_fmadd_pd(va, vb, vc);
        __m256d vres1 = _mm256_fmadd_pd(va1, vb1, vc1);
        __m256d vres2 = _mm256_fmadd_pd(va2, vb2, vc2);
        __m256d vres3 = _mm256_fmadd_pd(va3, vb3, vc3);

        _mm256_store_pd(&dst[i], vres);
        _mm256_store_pd(&dst[i + 4], vres1);
        _mm256_store_pd(&dst[i + 8], vres2);
        _mm256_store_pd(&dst[i + 12], vres3);
    }
    return 0;
}
Хороший компилятор это и сам сделает.

На 100000 элементов у меня разница в полтора раза в пользу FMA.

У вас скорее всего пенальти при загрузке по невыровненным данным, либо что-то не так с fmaf(). Я б уровнем ниже спустился с явной загрузкой в регистры и вызовом _mm256_fmadd_pd(), либо глянул ассемблерный листинг, во что оно там компиляется.
Мож с опциями компиляции что-то не то. ИИ мне пишет что надо как-то так компилировать: gcc -mavx2 -mfma -O3 -o fma_avx2 fma_avx2.c
Аватара пользователя
IvanLis

Activity Professionalism Tutorials Gold Man of the year 2012
Автор
guru
guru
Сообщения: 5501
Зарегистрирован: 02 дек 2009, 17:44
Награды: 7
Версия LabVIEW: 2015, 2016
Откуда: СССР
Благодарил (а): 32 раза
Поблагодарили: 93 раза

Re: Создание DLL для использования в LabVIEW

Сообщение IvanLis »

AndreyDmitriev писал(а): 01 июл 2024, 15:26 Мож с опциями компиляции что-то не то. ИИ мне пишет что надо как-то так компилировать: gcc -mavx2 -mfma -O3 -o fma_avx2 fma_avx2.c
Всем спасибо за участие