shibatch / sleef Goto Github PK
View Code? Open in Web Editor NEWSIMD Library for Evaluating Elementary Functions, vectorized libm and DFT
Home Page: https://sleef.org
License: Boost Software License 1.0
SIMD Library for Evaluating Elementary Functions, vectorized libm and DFT
Home Page: https://sleef.org
License: Boost Software License 1.0
For double precision sleef gives
2.7182818284590455
instead of
2.718281828459045
despite the fact that the sleef answer is within 1 ulp, since it is such an important number it would be good that exp(1.0) was correctly rounded
As we all know, the current build scheme with makefile is a little messy. I recently tried to learn how to use cmake, and I think it is now possible to begin migration. The new scheme should make it easier for llvm to adopt the latest version of SLEEF. I committed (kind of) llvm-compatibility support already, but it is just renaming of the functions. I think it is better to talk about how we design these features.
Hi,
I'm trying to wrap your vectorized functions in type-generic constructs for generic programming, but I'm unable to compile. My final error message is:
Undefined symbols for architecture x86_64:
"_vmldCos2", referenced from:
(function_name) in kernel_test.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
It seems to be a problem with trying to link against SVML. (I am largely using your project to avoid using SVML.) I've tried adding "#define NOSVML" to prevent this from happening but can't seem to prevent it.
I'm compiling with g++7 on OSX.
Is there some change that's needed to be made to the CMake scheme?
IMHO it would make sense to add logic for additional argument reduction (i.e. payne-hanek) for huge arguments at least for the non-vectoriced pure-c variant of sleef.
As this is table based this is obviously not possible for the vectorized SIMD variants.
I could be wrong, but it may be useful to take a look at:
https://stackoverflow.com/questions/30573443/optimize-for-fast-multiplication-but-slow-addition-fma-and-doubledouble and http://hal.archives-ouvertes.fr/docs/00/06/33/56/PDF/float-float.pdf for a faster method to add two floatfloat or doubledouble values. If this methods still applies to sleef please ignore my request.
Hi all,
Just testing out this library on a new AMD EPYC. Using the latest git repo, cmake3 and gcc 4.8, the library builds but the tests fail when trying to link the tester because of undefined reference to Sleef_x86CpuID. Looking into link.txt into tester.dir shows the reason why. The shared library is linked after the libcommon.a meaning the dependencies of that shared library won't be satisfied.
I don't know Cmake or I'd submit a patch, but the solution for me was to add the ../common/libcommon.a to the end of src/libm-tester/CMakeFiles/tester.dir/link.txt
This is against current git head. I must assume that others are seeing this? I couldn't find anything special about my config that would cause that ordering.
The tests appear to pass ok, but alas, I cannot use it because libsleef.so does not include common.a as well. I need to keep looking.
One minor bug is found in SLEEF-3.1 and I am planning a minor update. That would be 3.1.1.
https://sourceforge.net/p/sleef/discussion/general/thread/5b641594/
Diana was also mentioning about incrementing version number, though I cannot find the message.
Is it okay to move to three-part version numbering scheme?
I am planning to add aliases that conform to the GNU Vector ABI specification to the functions whose names start with Sleef_. By doing this, compilers including GCC and Clang will be able to utilize SLEEF functions with their automatic vectorizers. For example,
The Intel version of Sleef_sind2_u10 will have an alias _ZGVbN2v_Sleef_sin_u10.
The Intel version of Sleef_sind4_u10 will have an alias _ZGVcN4v_Sleef_sin_u10.
If a weak alias is not supported by the compiler that compiles SLEEF library, functions with the corresponding names are added instead.
This change will not affect the current GNUABI version of functions.
e.g. log_u1 for small denormals not accurate to within 1 ulp.
I am considering to run the tests on Intel software development emulator. With this, we can test AVX2 and AVX512F implementations in addition to the currently tested ones.
Testing won’t be too much slower than now, since only IUT runs on the emulator.
We can see a similar travis configuration in the following pull request.
On Linux x86 and building with CMake, there are no generic functions in the resulting library.
For example, I do see Sleef_sind4_u10avx, Sleef_sind4_u10avx2 and Sleef_sind4_u10fma4, but no Sleef_sind4_u10.
The mkdisp executable is build. Am I supposed to do something with it, or should that happen automatically during building the library?
As part of the LLVM- compatibility effort, we decided to move SLEEF documentation to doxygen
.
This task is the initial experimental support for doxygen.
We are not sure that this is what we want to use for the project, therefore to avoid wasting time we limit the scope of this initial investigation to the following:
sleefsimddp.c
sin
, cos
, and exp
. For each functions, add the precision and the range where this precision is valid.cmake
configuration to build the documentation as the make docs
target. That should required:
CMakeLists.txt
configuration file in the doc
folder with the definitiona of the docs
target that invokes doxygen
.CMakeLists.txt
in the root folder that will include the doc
folder.Once we are happy with this configuration, we can think at extending it to the whole library.
Since the word "helper" is too generic, I would like to rename this name to a more specific one.
My proposal is "veal" which stands for vector extension abstraction layer.
As you know, veal means meat of calves, and I like this naming since it is food-related.
I am going to unify helperavx2_128.h and helpersse2.h, since these have the same vector length.
It would be also cleaner to unify helperneon32.h and helperadvsimd.h.
Each file should be named in a more coherent way.
My proposal of the format of new file names is veal[extension system]_[bit length].h, as follows.
helpersse2.h -> vealintel_128.h
helperavx2_128.h -> unified to vealintel_128.h
helperavx.h -> vealintelavx_256.h
helperavx2.h -> vealintel_256.h
helperavx512f.h -> vealintel_512.h
helperadvsimd.h -> vealarm_128.h
helperneon32.h -> unified to vealarm_128.h
AVX requires a different file from AVX2 since handling of vint2 data type is different.
We need to expose the vector routines using the name mangling functions defined in the target vector ABI.
For Intel vector extensions, the mangling function can be found at [1]. The vector ABI for AArch64 is not public yet, but it is exposed in this patch [2] for clang.
For our math functions (they are all non-masked), the name mangling functions reduces to:
_ZGV<isa>N<vlen><vparameters>_<original_name>
For example, a cos
function will become:
_ZGVnN2v_cos // AArch64 AdvSIMD, see [2], <isa> == n
_ZGVdN4v_cos // Intel AVX2
_ZGVeN8v_cos // Intel AVX512
Another example, for powf
:
_ZGVnN4vv_powf // AArch64 AdvSIMD, see [2], <isa> == n, two vector input parameters (vv)
_ZGVdN8vv_powf // Intel AVX2
_ZGVeN16vv_powf // Intel AVX512
The reason for adding these symbols is that it will allow compiler like gcc
and clang
to link the library transparently when vectorizing math routines in loops, as in the example in [3] (we will need to provide a header file with math.h
definition and expose teh vector math routines by means of #pragma omp declare simd
).
Note that some of the vector extensions that SLEEF supports are not specified in the vector ABI in [1] (e.g. SSE2). We can skip to create vector ABI symbols for such vector extensions for now.
[1] https://sourceware.org/glibc/wiki/libmvec?action=AttachFile&do=view&target=VectorABI.txt
[2] https://reviews.llvm.org/D30739
[3] https://godbolt.org/g/DnxT6D
Dear @shibatch. I am offering the following logo from my julia port, if you would like to use it instead:
https://github.com/musm/SLEEF.jl
https://github.com/musm/SLEEF.jl/blob/master/doc/src/assets/logo.svg
Of course there is no obligation on this. Just thought I would throw it out there.
Hello,
How could one generate Static Sleef Library under macOS?
Could you update the documentation to show how it is done using xCode and GCC?
Could you also add examples how could one set the compilation flags (For instant, Fast Math).
Thank You.
I am now considering to move the documents to a new repository shibatch.github.io. By doing this, it would be easier for the users to see the documents. The license management would be a little bit troublesome, though. I want to hear comments on this.
in several sleef functions standard sqrt/sqrtf math functions are referenced. As xsqrt_u05 / xsqrtf_u05 are defined: why not use this functions to get rid of this references?
BTW: the magic number 0x5fe6ec85e7de30da (sleefdp.c:1665) is not exact according to the wikipedia article.
There is a request for making scalar functions produce the same results as the vectorized functions.
https://sourceforge.net/p/sleef/discussion/general/thread/bed4208e/
In order to follow this request, I am now considering to write helper files for scalar functions. With these helper functions, only one element in the vector registers are used for computation using each vector extension. We can use the current naming scheme.
In order to allow using sleef as a substitute of libm, it is desirable to remove dependency on libm.
As we already discussed in #30 and #33, we can consider a use case where users link their programs against libsleef instead of libm. In this case, all standard math functions are implemented by libsleef. libsleef should export all symbols exported by libm.
In order to realize this, we need to remove all dependency on libm from sleef. For this, calls for libm functions have to be all replaced with builtin functions, e.g. sqrt is replaced by _builtin_sqrt. Since the names of the builtin functions are compiler-dependent, we need some renaming and detection.
We can think of both merits and demerits in doing this.
Merits :
Demerits :
Although there is some demerit, sleef should support usage like this. Currently, the gnuabi version and the normal version of sleef are built. It is natural to add scalar math.h functions to the gnuabi version.
There is also a requirement of making the scalar functions return the exactly same values as the vectorized functions, as discussed in #47 . This can be realized by calling dispatcher functions from the API of the gnuabi sleef.
I am planning to make big changes for version 3.3.
Most of them are already discussed in the issues, but here I list them.
It would be a little tricky to implement all of these while keeping the source code tidy.
Hey, I just had a quick look a bit more at the performance of sleef and tried just a simple benchmark with Sleef_sinf_u10
and Sleef_sinf_u35
, compare also against a stock sin with MSVC compiler:
The bench is something in the line of:
float BenchFloat_Sin(unsigned long count)
{
float value = 0;
float f = 5;
for (unsigned long i = 0; i < count; i++)
{
value += sin(f);
value += sin(f + 1);
value += sin(f + 2);
value += sin(f + 3);
value += sin(f + 4);
f += i;
}
return value;
}
where the count was dynamically calibrated from another bench, but in that case on my machine was set to 6574622.
The timing results are:
MSVC sinf: 418ms
Sleef_sinf_u10: 2058ms
Sleef_sinf_u35: 179ms
between u10 and u35, there is more than x10 different (!)... I haven't checked the accuracy of MSVC sinf, so likely it is not 1 ULP. Looks like exponential to get 1ULP.
Do you think this results are expected?
Also, If it is not possible to achieve 1ULP without this cost, would it be possible to introduce an intermediate precision (ULP 2?) that could lower the gap there and make it more viable?
More generally, I was also wondering if adding also more ULP precisions choices (u10, u20, u35, u60) could be helpful in some cases...
Use the google benchmark library [1] to write micro-benchmarks for the vector math routines.
Each benchmark should be invoking the function with random values in the input range.
Appveyor provides CI on windows machines for open source projects, and it is integrated with github.
It provides "Visual Studio , LLVM/Clang, MinGW and MinGW-w64 compiler infrastructures": https://www.appveyor.com/docs/lang/cpp/
The idea is similar to travis-ci, the build is triggered on new commit via a YAML configuration file. Thank you @rofirrim for pointing this out!
Should at least be documented
Since #121 is fixed, the dispatch functions are compiled in libsleef again.
But now I see the problem that the dispatch function chooses AVX instead of AVX2.
For a certain (fixed) number sincos evaluations I see the following runtime:
Sleef_sincosf8_u35avx: 74 ms
Sleef_sincosf8_u35avx2: 54 ms
Sleef_sincosf8_u35: 80 ms
This is not what I would expect.
Indeed, when profiling the code, the AVX function is being called.
As mentioned in #48, we should consider using multiple branches for our development.
The current situation is:
master
-> new features development and releasescmake-transition
-> port of the makefile build system to cmake
Once 2 is done, we can merge cmake-transition
into master.
@shibatch , can you explain how you would like to change this? Having different branches for different version seems like to be a good idea. What would end up in the 3.1.* branch and in teh 3.2 branch? how they would relate to master
and cmake-transition
?
One alternative solution would be to keep master being the release branch, and git tag
those points in the history of master
where we do a particular release, and consider any other branch a development branch that we might merge into master when ready, and mark with a release tag if needed.
It is now time to think how we can build testing programs with MSVC.
The main obstacle is building libmpfr.
The easy way is to build the IUT with Cygwin, as it is done with the old makefile.
Another way is to use the version that can be built with MSVC.
https://github.com/BrianGladman/mpfr
Tester1 was first introduced in version 2.00, and many functions are added to SLEEF since then.
The basic structure has not been changed, and the testing criteria for new functions were added in an ad-hoc way. As a result, it can now be seen as a very dirty code.
Tester1 consists of two parts : the tester and IUT. In the IUT, the implementation of SLEEF functions are executed, and the tester checks if the returned values are correct. Those two programs are connected by a pipe. The advantage of having this structure is that the IUT does not need to depend on any external library. It is even possible to execute the tester on another host, and do testing over the network. The obvious disadvantage is slow speed.
Tester1 is designed to check the error for only part of the input domain. Since this is considered inadequate, the new tester2, which randomly generates arguments and checks if each function returns a correct value, is introduced as of version 3.0. As a result, tester1 does not need to check wide variety of input values anymore.
There are distinct roles for tester1 and tester2. The role for tester1 is to check correctness of return values for some particular input values. There are also some special numbers that need attention for some of the functions in SLEEF. There is one more role for tester1, which is to check the correctness of implementation with MSVC. Since I have not made MPFR work with MSVC, tester1 is the only way to check correctness on this platform. On the other hand, the aim for tester2 is to find glitches without prior knowledge. By continuously running tester2, it is expected to find unknown bugs.
We need both testers, but since the design of tester1 is old, I need to do a major overhaul of tester1. I have the concerns listed below:
So, in order to solve all of these problems, I already rewrote tester1. Francesco suggested that we should introduce google micro-benchmarking library, but I still need a tester whose IUT and tester are separated.
In the new tester1, all 4 testers are unified into one, and it uses the ULP-counting functions that can be shared with tester2. By rewriting in this way, the dependencies on long double data type can be also eliminated. The code will be cleaned so that what is tested is easier to understand. It is also easy to add new functions and testing criteria.
pretty trivial to add since all the pieces are already there
The test in https://github.com/shibatch/sleef/blob/master/src/libm-tester/finite_names_testing.c make sure that the finite symbols expected for GLIBC compatibility are available in the library.
They are currently checking only a couple of functions for the Intel vector extensions.
We should decide whether we want to keep them and extend them to all the finite symbols and all the supported vector extensions, or if we want to remove them.
Any thoughts?
One argument for keeping them and extending them is the following. I came up with this idea when I first used the library in our compiler. The compiler was generating the finite names (because of the -ffast-math
option) which were not available in the library. I added them in the library and decided that I should have made a regression tests to prevent the symbols to disappear.
@shibatch , I think we are ready for the release of 3.2. What do you think?
Hi,
So I have started to pull the cmake-transition
branch.
I have already open the PR #66 to fix gnuabi problem.
I will submit other patches, mainly to simplify the process of mkrename/headers, which is currently not robust (don't fail if the file is not generated), a bit hacky (using external cmake command), and cumbersome to follow (external cmake files, not configurable...etc.)
I have already refactored the mkrename
part and it seems to work well. I will do the same for the header files.
Let me know if I can proceed further.
Thanks!
Here is the design I discuss with @diaena:
libsleef.so
out of sleefsp.c
and sleefdp.c
. For the moment, we can live with a single CMakeLists.txt
script in src/libm
.sleef.h
header file which exports the un-mangled names of the functions, as in xsin
for the double precision SIN function, and adds the Sleef_*
names mapped in rename.h
[1] as function attribute "alias" [2]..travis.yml
to execute the cmake build of the library as an additional stepbuild-with-cmake.md
document in the doc
folder.When this is done, we can add the sleefdl.c
and sleefqp.c
to the scalar library, but I will create a separate issue for that.
@shibatch , @hfinkel: let us know if you have any questions.
Francesco
[1] https://github.com/shibatch/sleef/blob/master/src/libm/rename.h
[2] https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
I.e. when x = NaN, 0, Inf
See: https://github.com/musm/Libm.jl/blob/master/src/Sleef/log.jl#L18
for the fix
https://github.com/shibatch/sleef/blob/master/src/libm/sleefdp.c#L1192
should be
if (!xisinff(d) && (xisnegzerof(d) || fabsfk(d) > TRIGRANGEMAXf)) u = -0.0f;
right?
I don't get tan(-0.0) = -0.0
similarly for the float version
For the x86 vector functions, function names without vector extension is used to call the dispatcher.
In order to improve portability of the source code of the programs that call SLEEF functions, it would be also desirable for aarch64 and aarch32 functions to have aliases without vector extension name.
For example, Sleef_sind2_u10 can be used instead of Sleef_sind2_u10advsimd.
If a weak alias is not supported by the compiler that compiles SLEEF library, functions with the corresponding names are added instead.
This change will not affect the current GNUABI version of functions.
I made a pull request for implementing masked functions by combining the current unmasked functions and a selection(blending) function.
However, there is a concern on the performance of this implementation, since the ALUs for unused elements are all active. This could lead to increased power consumption and generated heat by the computer. It is considered better to implement the masked functions in such a way that they utilize native masked intrinsic functions.
My plan is to approve the above PR, and after the release of version 3.2, we will start implementing masked functions using native masked intrinsic functions in the following way.
All existing FP functions in the helper files will be converted to masked functions. For example,
vdouble vadd_vd_vd_vd_vo(vdouble x, vdouble y, vopmask m) {
return vaddq_f64(x, y);
}
for an unmasked intrinsic function, and
vdouble vadd_vd_vd_vd_vo(vdouble x, vdouble y, vopmask m) {
return svadd_f64_x(m, x, y);
}
for a masked intrinsic function.
Then, the implementation of each math function would be like the following.
static const inline vdouble xsin(vdouble arg, vopmask mask) { ... }
EXPORT const vdouble Sleef_sindX_u35YYY(vdouble arg) {
return xsin(arg, SLEEF_OPMASK_ALLONE);
}
EXPORT const vdouble Sleef_mask_sindX_u35YYY(vdouble arg, vopmask mask) {
return xsin(arg, mask);
}
The mask argument is assumed to be optimized away if it is not used.
Should be straightforward to add
The command to generate this file is currently
$(FLOCK) mkrename.lock ./mkrename 2 4 sse2 > renamesse2.h
which omits both the -c
flag and correct quoting, leading to a failure when noflock.sh attempts to execute 2
.
$(FLOCK) mkrename.lock -c './mkrename 2 4 sse2 > renamesse2.h'
works as intended. I have not tested whether the existing version works on Linux, but based on reading the flock
manpage it does not appear that it should, since -c
is apparently required for a command to be executed.
We currently need a special case for building the ADVSIMD test executable. This is something that needs fixing.
glibc remaps log2[f]
to __log2[f]_finite
. We need to make sure that the vector form of this symbol is available in libsleefgnuabi.so
. One it is done, the correspondent gnuabi compatibility test must be activated. See 450a746#diff-e5e7a421d82269193c02ad7fb6261d97R265 and 450a746#diff-e5e7a421d82269193c02ad7fb6261d97R335
Following the discussion on the issues regarding to migration to new cmake build system, I here created a discussion thread for naming of functions that will be used in llvm runtime.
#30
https://reviews.llvm.org/D24951
Requirements and observation :
It is better to follow the specification of the vector ABI.
glibc already has vectorized math functions, and there should be a way to choose which math library to link.
Libraries to link should be separately selected for vectorized and non-vectorized math functions.
Compiler should be able to choose between functions with different accuracy (and possibly additional support for errno, exception, extended input domain, etc.) according to the compiler options. e.g. The compiler chooses the less-accurate version if -ffast-math is specified.
Do we need support for vector mask?
At which level should dispatcher be placed? Is it a good idea to always link to the functions with dispatcher?
It would be nice if the compiler can collect information as to which features are supported by the specified library from only the exported symbol names. For this, each symbol name should contain the following information.
Isn't it better to add definition on half and quad FP data type? 80-bit float? double-double?
OpenCL compatibility?
Hello,
I'm trying to install Sleef on Windows.
My system is Windows 10 Pro 64 Bit with Visual Studio 2017 (15.5.6).
The problem is Cmake requires a file called CMakeLists.txt
.
It seems this file is available in the master
branch of GitHub yet it is not part of the Releases
.
If one download the ZIP form GitHub Releases or SourceForge he doesn't get the CMakeLists.txt
file.
What should I do?
Go with Master (Which I assume isn't validated as stable releases) or is the any other way?
Thank You.
According to the table on Sleef web page compilation with Clang won't generate AVX compatible code for Windows x64:
Yet if one have a look at:
msys2/MSYS2-packages#1209 (comment)
Then:
I'm trying to raise the GCC issue so people with knowledge will take care of it.
Just opening an issue to track the remaining work on cmake.
There are a few remaining steps to backport from the old makefile to the cmake-transition
branch:
dft
dft_tester
gencoef
Once this is done, we could remove all the previous makefiles and the cmake-transition
branch could be merged back on master.
There is also the #71, but not sure it is critical to have it entirely ready on cmake-transition
for now. It could be done later.
I can help in the process on working on a bit on these steps.
Is there any chance we could get documentation on the algorithms used for each function, e.g. details on the reduction, approximation, scaling back methods? I know this is asking much, but it would help a lot.
I guess denormals can appear in intermediate variables. But not all architectures support denormal, or denormal can be disabled by user with FTZ flag. Have we reviewed precision for such cases?
Both sin and sin_u1, tan and tan_u1 , log1p do not return correct sign for -0.0, noticed this during testing. Thanks.
Fix for sin and sin_u1 is simple , just needs a flipsign operation
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.