. 1, 2, 4, 8 16 float 1, 2, 4, 8 double. CPU , : SSE2, SSE4.1, AVX, AVX + FMA AVX512.
, 1, - . SIMD-, : Agner Fog Vector Class Library. .
VCL , AVX, , SSE ( AVX512 SSE). AVX ( AVX512), , .
void Memcopy(void *dst, void *src, size_t size)
{
Vec8f v;
for(int i = 0; i < size; i +=v.size())
{
v.load(src);
v.store(dst);
dst += v.size();
src += v.size();
}
}
( memcpy . temroal-, IVB rep movsb
). , , , , vector
Vec8f
.
VLC, CPU, , /, . , , .
CPU. :
: , . TYPE float
, double
doubledouble
N 1, 2, 4, 8 16. doubledouble
, VCL. Vec1f, Vec4f, Vec8f, Vec16f, Vec1d, Vec2d, Vec4d, Vec8d, doubleledouble1, doubleedouble2, doubleedouble4, doubleledouble8.
template<typename TYPE, unsigned N>
static inline intn calc(floatn const &cx, floatn const &cy, floatn const &cut, int32_t maxiter) {
floatn x = cx, y = cy;
intn n = 0;
for(int32_t i=0; i<maxiter; i++) {
floatn x2 = square(x), y2 = square(y);
floatn r2 = x2 + y2;
booln mask = r2<cut;
if(!horizontal_or(mask)) break;
add_mask(n,mask);
floatn t = x*y; mul2(t);
x = x2 - y2 + cx;
y = t + cy;
}
return n;
}
, SIMD , . , .
:
g++ -m64 -c -Wall -g -std=gnu++11 -O3 -fopenmp -mfpmath=sse -msse2 -Ivectorclass kernel.cpp -okernel_sse2.o
g++ -m64 -c -Wall -g -std=gnu++11 -O3 -fopenmp -mfpmath=sse -msse4.1 -Ivectorclass kernel.cpp -okernel_sse41.o
g++ -m64 -c -Wall -g -std=gnu++11 -O3 -fopenmp -mfpmath=sse -mavx -Ivectorclass kernel.cpp -okernel_avx.o
g++ -m64 -c -Wall -g -std=gnu++11 -O3 -fopenmp -mfpmath=sse -mavx2 -mfma -Ivectorclass kernel.cpp -okernel_avx2.o
g++ -m64 -c -Wall -g -std=gnu++11 -O3 -fopenmp -mfpmath=sse -mavx2 -mfma -Ivectorclass kernel_fma.cpp -okernel_fma.o
g++ -m64 -c -Wall -g -std=gnu++11 -O3 -fopenmp -mfpmath=sse -mavx512f -mfma -Ivectorclass kernel.cpp -okernel_avx512.o
g++ -m64 -Wall -Wextra -std=gnu++11 -O3 -fopenmp -mfpmath=sse -msse2 -Ivectorclass frac.cpp vectorclass/instrset_detect.cpp kernel_sse2.o kernel_sse41.o kernel_avx.o kernel_avx2.o kernel_avx512.o kernel_fma.o -o frac
:
int iset = instrset_detect();
fp_float1 = NULL;
fp_floatn = NULL;
fp_double1 = NULL;
fp_doublen = NULL;
fp_doublefloat1 = NULL;
fp_doublefloatn = NULL;
fp_doubledouble1 = NULL;
fp_doubledoublen = NULL;
fp_float128 = NULL;
fp_floatn_fma = NULL;
fp_doublen_fma = NULL;
if (iset >= 9) {
fp_float1 = &manddd_AVX512<float,1>;
fp_floatn = &manddd_AVX512<float,16>;
fp_double1 = &manddd_AVX512<double,1>;
fp_doublen = &manddd_AVX512<double,8>;
fp_doublefloat1 = &manddd_AVX512<doublefloat,1>;
fp_doublefloatn = &manddd_AVX512<doublefloat,16>;
fp_doubledouble1 = &manddd_AVX512<doubledouble,1>;
fp_doubledoublen = &manddd_AVX512<doubledouble,8>;
}
else if (iset >= 8) {
fp_float1 = &manddd_AVX<float,1>;
fp_floatn = &manddd_AVX2<float,8>;
fp_double1 = &manddd_AVX2<double,1>;
fp_doublen = &manddd_AVX2<double,4>;
fp_doublefloat1 = &manddd_AVX2<doublefloat,1>;
fp_doublefloatn = &manddd_AVX2<doublefloat,8>;
fp_doubledouble1 = &manddd_AVX2<doubledouble,1>;
fp_doubledoublen = &manddd_AVX2<doubledouble,4>;
}
....
, . .