Use of Intel® oneAPI Math Kernel Library (oneMKL) Data Types in C/C++ Applications

ID 660422
Updated 7/3/2024
Version Latest
Public

Currently, the following Intel® oneAPI Math Kernel Library (oneMKL) types are defined in the mkl_types.h header file:
 
MKL_INT   - for integer values
 
MKL_UINT - for unsigned integer values
 
MKL_Complex8   - for single precision complex values   (a structure that contains single precision real and imaginary parts real and imag)
 
MKL_Complex16  - for double precision complex values (a structure that contains double precision real and imaginary parts real and imag)
 
See the oneMKL User's Guide and the mkl_types.h header file for more details.
 
The types listed above can be redefined in oneMKL version 10.3 update 4 so that C/C++ developers can avoid explicit argument casting when calling the library in applications that use the types "binary compatible" with those in oneMKL.
 
Such a possibility is often needed because the user can use his or her own types that can be "binary compatible", that is, having the same representation or memory layout.
 
For example:
  1. ISO C99 Complex type qualifier _Complex
  2. C++ Complex types std::complex
  3. There are several integer types on Linux* OS for ILP64, for example: __int64, long or long long
To redefine types supported by the oneMKL library, the #define statement should be used before including the mkl.h header file.
Another way to do this is to use the compiler option -D<name>=<username>, for example:
#define MKL_INT size_t
#include "mkl.h"
or
add the compiler option "-DMKL_INT=size_t" in the command line or build configuration.
 
Inaccurate redefinition of the oneMKL types may result in unpredictable computational results and/or crash of the application if the user's data types and those of oneMKL turn out to be incompatible (*). It is the user's responsibility to make a thorough analysis of such cases before redefining data types in oneMKL.
 
An example of incorrect redefinition for the oneMKL integer data type: #define MKL_INT double
 
An example of correct redefinition of MKL_INT for ILP64 if positive integer values less than 2^63 are used:
#define MKL_INT size_t
 
Below is a short C++ example zhetrd.cpp on the Linux OS and Windows, that covers the correct redefinition of MKL_Complex16
and MKL_INT:
 
#include <stdio.h> #define MKL_ILP64 // in order to use size_t instead of MKL_INT #if 1 // to use user-defined MKL_INT and MKL_Complex16 #define FLEXCOMPLEX typedef size_t INT; #define MKL_INT INT // this tells MKL about user's MKL_INT type #ifdef _WIN32 #include <complex> typedef std::complex<double> DCOMPLEX; #else typedef double _Complex DCOMPLEX; #endif #define MKL_Complex16 DCOMPLEX // this tells MKL about user's MKL_Complex16 type #else // using MKL default types MKL_INT and MKL_Complex16 #define DCOMPLEX MKL_Complex16 #define INT MKL_INT #endif #include "mkl.h" /* Auxiliary routine: printing a vector of doubles */ void print_vector_of_doubles( char* desc, int n, double* a ) { int i; printf( "%sn", desc ); for( i = 0; i < n; i++ ) printf( " %.4g", a[i] ); printf( "n" ); } /* Parameters */ #define SIZE 4 #define LDA SIZE #define LWORK (64*SIZE) #define UPLO "Low" int main(void) { // based on NAG F08FSF example /* Locals */ INT n = SIZE; INT lda = LDA; INT lwork = LWORK; INT info = 1000; /* Local arrays */ DCOMPLEX A[LDA*SIZE] = { #ifdef FLEXCOMPLEX #ifdef _WIN32 DCOMPLEX(-2.28, 0.00), DCOMPLEX( 1.78, 2.03), DCOMPLEX( 2.26,-0.10), DCOMPLEX(-0.12,-2.53), DCOMPLEX( 1.78, 2.03), DCOMPLEX(-1.12, 0.00), DCOMPLEX( 0.01,-0.43), DCOMPLEX(-1.07,-0.86), DCOMPLEX( 2.26,-0.10), DCOMPLEX( 0.01,-0.43), DCOMPLEX(-0.37, 0.00), DCOMPLEX( 2.31, 0.92), DCOMPLEX(-0.12,-2.53), DCOMPLEX(-1.07,-0.86), DCOMPLEX( 2.31, 0.92), DCOMPLEX(-0.73, 0.00) #else -2.28+__I__*0.00, 1.78+__I__*2.03, 2.26-__I__*0.10, -0.12-__I__*2.53, 1.78+__I__*2.03, -1.12+__I__*0.00, 0.01-__I__*0.43, -1.07-__I__*0.86, 2.26-__I__*0.10, 0.01-__I__*0.43, -0.37+__I__*0.00, 2.31+__I__*0.92, 0.12-__I__*2.53, -1.07-__I__*0.86, 2.31+__I__*0.92, -0.73+__I__*0.00 #endif #else // struct MKL_Complex16 {-2.28, 0.00}, { 1.78, 2.03}, { 2.26,-0.10}, {-0.12,-2.53}, { 1.78, 2.03}, {-1.12, 0.00}, { 0.01,-0.43}, {-1.07,-0.86}, { 2.26,-0.10}, { 0.01,-0.43}, {-0.37, 0.00}, { 2.31, 0.92}, {-0.12,-2.53}, {-1.07,-0.86}, { 2.31, 0.92}, {-0.73, 0.00} #endif }; DCOMPLEX TAU[SIZE-1]; DCOMPLEX WORK[LWORK]; double D[SIZE]; double E[SIZE-1]; zhetrd_(UPLO, &n, A, &lda, D, E, TAU, WORK, &lwork, &info); if (!info) { print_vector_of_doubles( "Diagonal", SIZE, D); print_vector_of_doubles( "Off-diagonal", SIZE-1, E); } else printf( "FAILEDn" ); return 0; }
Use the following on the Linux OS with the Intel® compiler:
icpx zhetrd.cpp -lmkl_rt -lpthread
 
and the next example illustrates linking that uses Intel® compilers on the Window OS.
icl zhetrd.cpp mkl_rt.lib /Qopenmp

Use the command below to output result:
./a.out
The result:
Diagonal -2.28 -0.1285 -0.1666 -1.925 Off-diagonal -4.338 -2.023 -1.802
(*) this feature is intended for advanced users