Error de C++: ''_mm_sin_ps'' no se declaró en este ámbito
optimization sse (3)
Estoy tratando de comparar diferentes formas de aplicar una función a una matriz.
_mm_sin_ps
no es conocido por mi alcance pero
_mm_sqrt_ps
?
¿Cómo lo hago saber? Y compilarlo sin errores.
#include <random>
#include <iostream>
#include <cmath>
#include <chrono>
#include <algorithm>
#include <valarray>
#include "immintrin.h"
#include <array>
int main()
{
std::cout<<"start/n";
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(-1000, 1000);
int N=100;
while(N--)
{
std::cout<<"/nN: "<<N;
const int T1=4E6;
{
int T=T1,T0=T1/4;
std::array<float,T1> array;
while(T--)
{
array[T]=dis(gen);
}
auto start_time = std::chrono::high_resolution_clock::now();
auto it =array.begin();
while(T0--)
{
__m128 X = _mm_loadu_ps(it);
__m128 result = _mm_sin_ps(X);
_mm_storeu_ps(it, result);
it+=4;
}
auto time2=std::chrono::high_resolution_clock::now()-start_time;
std::cout<<"/nintr1: "<<std::chrono::duration_cast<std::chrono::microseconds>(time2).count();
}
}
std::cout<<"/nfin/n";
return 0;
}
compilador
g ++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion=''Ubuntu 4.8.2-19ubuntu1'' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable- plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
Como ya se ha señalado, está intentando utilizar la biblioteca SVML de Intel.
Sin embargo, hay varias funciones trascendentales SIMD en la biblioteca
sse_mathfun
código abierto.
La versión original, que usa solo SSE2 está aquí:
http://gruntthepeon.free.fr/ssemath/
pero hay una versión más actualizada aquí que se ha actualizado para SSE3 / SSE4 aquí:
https://github.com/RJVB/sse_mathfun
La función que desea se llama
sin_ps
:
v4sf sin_ps(v4sf x);
donde
v4sf
es solo un typedef para
__m128
.
El
sse_mathfun
original también tiene
cos_ps
,
log_ps
y
exp_ps
, y la versión más nueva (RJVB) tiene algunas funciones adicionales para precisión simple y doble.
He utilizado con éxito ambas versiones de esta biblioteca con gcc, clang e Intel''s ICC (con algunas modificaciones menores para esta última).
__mm_sin_ps es una función intrínseca para llamar a la biblioteca SVML (ya mencionada).
En GCC, SVML está disponible como parte de libmvec en glibc.
Las funciones se nombran de acuerdo con Vector ABI, descrito en el enlace anterior. Las funciones sin, cos, exp, sincos, log, pow están disponibles. Aquí hay un ejemplo para __m128:
#include <x86intrin.h>
#include <stdio.h>
typedef union
{
__m128 x;
float a[4];
} union128;
__m128 _ZGVbN4v_sinf_sse4(__m128);
void main()
{
union128 s1, res;
s1.x = _mm_set_ps (0, 0.523599, 1.0472 , 1.5708);
res.x =_ZGVbN4v_sinf_sse4(s1.x);
fprintf(stderr, "%f %f %f %f/n", res.a[0], res.a[1], res.a[2], res.a[3]);
}
¿Hay alguna razón, por qué intrínseco es mejor que usar la función SVML directamente?
_mm_sin_ps
es parte de la biblioteca
SVML
, que se entrega solo con compiladores de inteligencia.
Los desarrolladores de GCC se centraron en las instrucciones de la máquina de envoltura y las tareas simples, por lo que no hay SVML en
immintrin.h
hasta ahora.
Tienes que usar una biblioteca o escribirla tú mismo. Implementación sinusal: