Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call libmvec functions manually on __m128 vectors?

According to this page https://sourceware.org/glibc/wiki/libmvec, I should be able to manually vectorize a few complicated instructions like cosine by using the libmvec functions. However, I don't know how to get gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0 to recognize them. Am I missing some compiler flags or something? Any help or suggestions are appreciated.

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
#include <immintrin.h>

// gcc libmvectest.c -o libmvectest.bin -lm -O3  -Wall -ffast-math -march=msse4


int main(int argc, char **argv)
{
  float input = 0.1;
  float res[4];
  __m128  m128 = _mm_set1_ps(input);
  __m128  cosm128 = _ZGVbN4ua16vl_cosf(m128);
  _mm_storeu_ps(res, cosm128);
  printf("%.8f %.8f\n", cosf(input), res[0]);
}

I've googled the 'implicit declaration...' error for the prefixed functions but failed to find an answer that worked for me. I tried _ZGVbN4ua16vl_cos, _ZGVbN4ua16vl_cosf and other attempts. Does anyone know where the actual function names are listed?

like image 724
Simon Goater Avatar asked Aug 30 '25 17:08

Simon Goater


2 Answers

Thanks to all who looked into this. The main point of the question was to manually vectorize using those built in functions so as to not rely on the optimiser which can easily get confused if you're doing more than just a simple one function loop. The suggestion by Peter Cordes worked on my system so this code now compiles and runs successfully.

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
#include <immintrin.h>

// gcc libmvectest.c -o libmvectest.bin -lm -O3  -Wall -ffast-math -march=msse4

extern __m128  _ZGVbN4v_cosf(__m128);

int main(int argc, char **argv)
{
  float input = 0.1;
  float res[4];
  __m128  m128 = _mm_set1_ps(input);
  __m128  cosm128 = _ZGVbN4v_cosf(m128);
  _mm_storeu_ps(res, cosm128);
  printf("%.8f %.8f\n", cosf(input), res[0]);
}
like image 56
Simon Goater Avatar answered Sep 02 '25 07:09

Simon Goater


Those OpenMP-SIMD clones are not intended to be invoked by hand from portable C. They are not declared as separate functions; instead, they are introduced as multiple variants of a standard function via #pragma omp declare simd or __attribute__((simd)) for use by automatic vectorization. On a Glibc-based system you can inspect the declarations in /usr/include/bits/math-vector.h.

For use in explicitly vectorized code you can write simple wrappers with a trivially vectorizable loop like this:

#include <immintrin.h>

__attribute__((simd("notinbranch")))
float cosf(float);

__m128 t(__m128 x)
{
    for (int i = 0; i < sizeof x / sizeof x[0]; i++)
        x[i] = cosf(x[i]);
    return x;
}

which gcc -O2 -ftree-vectorize is able to optimize to

t:
        jmp     _ZGVbN4v_cosf

https://godbolt.org/z/jdfeoT7K5

like image 35
amonakov Avatar answered Sep 02 '25 08:09

amonakov