Are you confused by the various ipp*Init*() functions? So was I. So I asked the Intel IPP engineering team for some clarification, and this is what I found.
The Intel® IPP Dispatcher
One of the most valuable features of the Intel IPP library is the instruction set "dispatcher" that is built into the library. This dispatcher automatically executes the optimal version of each IPP function at run time, to match your specific processor type and instruction set. In other words, each IPP function in the library actually consists of multiple "variations on a theme." These variations are functionally identical routines, where each is optimized for a specific class of SIMD instructions. Another way to think of this is that each IPP function has been "overloaded" to support the SSE instructions that are appropriate to the processor being used.
Please note the dispatcher is still valuable feature of IPP. But since Intel IPP 9.0, the ipp*Init*() functions are not necessary to enable the dispatcher. Any first call Intel IPP function is able to detect the processor type and set the dispatcher to use the processor-specific code. The article will be reference for developer who try to understand the dispatcher.
For more information on the SIMD instruction sets that the Intel IPP library has been optimized for see these IPP knowledge base articles:
Initializing the Dispatcher
Before the dispatcher can work your application must initialize the Intel IPP library. Without proper initialization the dispatcher will default to calling the "lowest common denominator" for each of these overloaded functions within the library (aka the "px" and "mx" code in v6.1) *. In that case your 32-bit code will be calling C-optimized functions ("px" does not use MMX or SSE instructions, only standard IA-32 instructions) and your 64-bit code will be calling SSE2-optimized code ("mx" uses only Intel® 64 instructions and MMX through SSE2 instructions). If you fail to initialize the library your application may not achieve optimal performance on your processor.
If your Intel IPP application uses the standard distribution dynamic library this dispatcher initialization step is handled automatically, as part of the dynamic library initialization. However, if you are using one of the static libraries, or a custom dynamic library that does not initialize the Intel IPP library automatically, you must "manually initialize" the dispatcher to insure optimum performance of the IPP library with your application.
Dispatcher Control Functions
The Intel IPP documentation contains a "Dispatcher Control Functions" section inside the "Support Functions" chapter of the "Signal Processing" reference manual. The functions you will find in that manual (as of version 6.1 of the Intel IPP library) are listed below:
- ippStaticInit (DEPRECATED) **
Automatically initializes the static library to that which is most appropriate for the runtime processor.
Automatically initializes the static or dynamic library to that which is most appropriate for the runtime processor.
- ippStaticInitCpu (DEPRECATED)
Manually initialize the static library to use the specified SIMD optimizations, regardless of the runtime processor.
- ippInitCpu (DEPRECATED)
Manually initialize the static or dynamic library to use the specified SIMD optimizations regardless of the runtime processor.
- ippEnableCpu(DEPRECATED) --> use ippSetCpuFeatures()
Enables automatic dispatching for processor simulators and some alpha silicon (used only in unusual cases.)
A little confusing, right. What are the differences? Which one should you use? Does it matter when or where I use them? Must I stop using the deprecated functions?
In general, you only need to make one initialization call to the Intel IPP library from your application: ippInit(). This call causes the dispatcher to analyze the CPU type your application is running on and determines which instruction set class is the best to use for optimal performance of the IPP library with your current run time processor. This call needs to be made before you make any other calls into the IPP library, so it should occur early in your application.
There are two exceptions to the above statements: the ippInitCpu() and ippEnableCpu() functions.
To force the dispatcher to use a specific SIMD instruction set (e.g., you want to always use the SSE2 instruction set) you can call ippInitCpu(), regardless of the actual processor type detected. Use ippInitCpu() as a replacement for ippInit(), since a subsequent call to ippInit() will undo your call to ippInitCpu(). This can be useful for comparing the performance of your application over multiple SSE instruction sets without having to maintain a large array of test systems.
Don't forget to check the return status of these init functions! Especially if you are trying to force usage of a specific SIMD instruction set with ippInitCpu(). Sometimes you may not be running on a compatible processor, the return status can help you resolve such an issue.
If you are using a processor simulator or some alpha silicon (a very rare situation for most developers) you may need to enable detection of the simulated processor. In this case you use the ippEnableCpu() function to insure that the dispatcher "sees" your simulator. For example, ippEnableCpu(ippCpuAVX) enables AVX as a "known architecture" type in the list searched for by the ippInit() function. ippEnableCpu() does not initialize the dispatcher, like ippInitCpu() does, but simply adds the specified architecture as an option to the table of SIMD instruction sets that the dispatcher will search for when you call ippInit().
Note: at the time this article was written Intel processors that support AVX were not yet commercially available.
As of version 6.1 of the Intel IPP library, ippEnableCpu() is only used in conjunction with the AVX instruction set (see /en-us/avx/ for more information about AVX) and only applies to the 64-bit version of the library (AVX support will be broader in future versions of the library). If you are not using AVX you can safely ignore the ippEnableCpu() function. For more information about AVX support in the IPP 6.1 library see this article.
Deprecated Init Functions
In the list above both ippStaticInit() and ippStaticInitCpu() have are marked as deprecated functions. You may have used these functions in the past; they have been replaced by ippInit() and ippInitCpu(), respectively. As of now these older functions continue to work, as originally intended, but will be removed from future versions of the library, in favor of the new functions. So it is best to start using the new functions now and discontinue use of these older functions.
What’s the difference between the older deprecated init functions and the new init functions? The older functions would return an error if you tried to use them with the dynamic link version of the library. That meant that you could not easily write code that could be linked either with the dynamic library or a static library. The new functions work with either the dynamic library or the static libraries. Also, the new init functions can be used for re-initialization of a dynamic library, which the old functions could not do, since they only applied to static editions of the Intel IPP library.
Automatic initialization still takes place in the dynamic library, so calling these init functions is redundant, but harmless. However, future versions of the library could require that these init calls get called explicitly, even with a dynamic link library, so it is a good idea to start using them now even if you only plan to use the dynamic form of the Intel IPP library.