A bunch of C++ extensions to the Intel Performance Primitives C library. This repository is meant to be compiled directly with your own source code; it requires no separate compilation by itself.
See below for the available extensions. All individual extensions are under the namespace ippe
, and can be universally included with
#include "ipp_ext.h"
For now, the wrappers in IPP appear to have very little coverage; that means most functions are not available to you (for example, the DFT which I use very often).
Also, I'm not a fan of their containers. This project really started with the vector
container, and I tried very hard to make it as close to the std
flavour as possible, so that it would be simpler to drop in and use.
There's also namespaces here, which I'm a bigger fan of than pre-pending all classes and functions with Iws
or something like that.
And finally, there's no extra linking steps. This is a header-only library, so if you're used to building with just the raw functions then you don't need to change any libraries.
The day Intel decides to do all (or most) of the above, I'll switch back.
git clone https://github.com/icyveins7/ipp_ext.git
# In your project directory now...
cl mysource1.cpp mysource2.cpp ... -I"path/to/ipp_ext/include" ...
On Apple Silicon chips like M1, you can cross-compile using the in-built clang
compiler, as long as the target architecture is specified as x86_64, and static linking is used; that is, you link to the .a
versions rather than the .dylib
versions. Dynamic linking does not seem to work properly as the linker fails to find the symbols for some unknown reason...
Compiling with static linking has been tested to work with the native Apple clang
compiler and a Homebrew CMake.
Note that there may be a lot of linker warnings that look like this:
ld: warning: no platform load command found in '/opt/intel/oneapi/ipp/2021.9.0/lib/libipps.a[11443](pscopyca_y8---ippsCopy_64fc.o)', assuming: macOS
The compilation should still work however (which means you can run the same code on your Intel machine as you would on the M1/M2 machine).
For examples, see how the CMake is written in the tests
folder.
Individual header is contained in ipp_ext_vec.h
, but ipp_ext
contains it.
The ippe::vector<>
container is meant as a drop-in replacement for the std::vector<>
container. It doesn't have all the features of the latter, but probably enough to get you going for most cases.
This vector has templates for all the IPP types (Ipp64fc
all the way to Ipp8u
), but specifically excludes all non-IPP types (like float
, double
etc).
Importantly, it utilises the ippsMalloc
and ippsCopy
functions to deal with memory allocation, so that IPP can properly utilise the 64-byte boundary of the arrays allocated.
See examples/vector_example.cpp
for a simple example.
The ippe::vector<>
container was designed primarily as a memory management container, and as such does not replicate all of the std::vector<>
features.
- Constructor does not set values to 'default-insertable'. This means that the underlying array elements for
ippe::vector<>
are undefined by default, whereasstd::vector<>
instead usually sets this to 0. - We bridge over this zero-ing functionality to the other constructor which
std::vector<>
also has, of the formvector(count, value)
, and invoke theippsSet
andippsZero
functions appropriately. Hence, to achieve the same 0-valued array, useippe::vector<>(count, zeroval)
(wherezeroval
may need to be defined beforehand for complex IPP types). - Instead of
std::vector
'sassign
, we instead haveset
(andzero
), which does not mutate the array size. The call structure uses integers to mark the index of the element to start, and the length of the array to use, which corresponds to the IPP function structure. There is also a convenience overload with no arguments for both, which will simplyset
/zero
the entire vector.
Individual header is contained in ipp_ext_dft.h
. This ippe::DFTCToC
class wraps the available flavours for DFTCToC
functions, which are the most common DFT/FFT use-case in IPP, as they are not limited to powers of 2.
The class takes care of internal workspace allocation and deallocation, and allows you to simply call fwd()
or bwd()
which are the equivalent of FFT/IFFT functions. See the dft_example.cpp
for the simplest example.
Individual header is contained in ipp_ext_filter.h
. The parent class ippe::FIRSR
is not meant to be instantiated directly; instead, use the derived classes with the below currently implemented flavours:
ippe::FIRSRLowpass
creates a lowpass filter.
These classes take care of internal taps generation, memory allocation and de-allocation, and all workspace requirements, including a delay vector that properly accounts for repeated filter()
invocations. See filter_example.cpp
for a simple example.
Individual header is contained in ipp_ext_math.h
, but this simply includes the separate headers in the math
folder. Each individual header contains the template specializations for a specific operation, like ippsAdd
for example.
Invocation is wrapped in a ippe::math
namespace, with the functions retaining the call structure of the original C functions.
Example:
ippe::vector<Ipp32fc> x, y, z;
ippe::math::Add(x.data(), y.data(), z.data(), x.size()); // Performs z = x + y using ippsAdd_32fc()
Currently implemented templates:
- Add
- Sub
- Mul (incomplete)
- Norm (only Norm_L2)