Using Intel® MKL in your C# program

Introduction 

Some users have asked how to call and link the Intel® Math Kernel Library (Intel® MKL) functions from their C# programs. While the standard way of interfacing with third party software libraries from C# is well documented, some of the steps in interfacing with Intel MKL specifically may still be confusing. The attached source code package is intended to show how to navigate the whole process for Intel MKL users. These examples show how to create a custom DLL from Intel MKL libraries, call those functions from their C# source, and interface with that custom DLL.

Examples are provided for calling mkl from 5 intel MKL domains 
1. dgemm.cs - BLAS (CBLAS)
2. dgeev.cs - LAPACK
3. pardiso.cs - PARDISO direct sparse solver
4. dfti_d1.cs - DFTI (the FFT interface)
5. vddiv.cs - VML vector math library

Let's take the function "dgeev" as example, The function is a typical routine in the Linear Algebra PACKage (LAPACK). It computes the eigenvalues and left and reight eigenvectors of a general matrix. As LAPACK are Fortran interface, that means scalars are passed as references, and only Fortranstyle (column-major) matrices are allowed. Many LAPACK routines use work arrays. Some array arguments may be not referenced for certain condition.   The interface in C# is like below 

[SuppressUnmanagedCodeSecurity]
[DllImport("mkl.dll", CallingConvention=CallingConvention.Cdecl)]
static extern void dgeev(ref char jobvl, ref char jobvr,
ref int n, [In, Out] double[] a, ref int lda,
[Out] double[] wr, [Out] double[] wi,
[Out] double[] vl, ref int ldvl, [Out] double[] vr, ref int ldvr,
[In, Out] double[] work, ref int lwork, ref int info);

In this LAPACK routine vr is not referenced if jobvr = 'N', and vl is not referenced if jobvl = 'N'. The 
user  can  pass  a "null"  value  in  the  case  unreferenced  arguments.  It  does  not  matter  for  automatic 
pinning but it may require additional efforts to check null values in case of passing arrays as pointers 
with fixed keyword within unsafe block. 

Building the Examples

Follow these steps to build the example programs:

  • unzip the contents of the attached zip file
  • Open a Microsoft Visual Studio command prompt or add the Microsoft.NET Framework to the PATH environment variable in another command prompt
  • Run the build script (makefile) using nmake
    Example:

          >"C:\Program Files (x86)\Intel_sw_development_tools\compilers_and_libraries\windows\mkl\bin\mklvars.bat" ia32
          >nmake ia32 

  • The makefile provides further explanation of the parameters in comments

This will create custom DLL mkl.dll, which include the used functions and several executables for each of the example programs.

Example files: Intel_MKL_C#_Examples.zip

Building the Examples with  Intel® MKL Single Dynamic Library

Dynamic interface libraries have been added since Intel MKL 10.3 for improving linkage from C#. It is not required to build a custom DLL. The Intel MKL library named mkl_rt.dll can be called directly from C# code. Below is an updated version of the examples. Follow the same steps and run the nmake command.

Example:  
>"
C:\Program Files (x86)\Intel_sw_development_tools\compilers_and_libraries\windows\mkl\bin\mklvars.bat" ia32
>n
make ia32 

Example files: Intel_MKL_C#_Examples_02.zip

Examples with Complex Data Types

The below examples are provided for calling complex data types  from 3 intel MKL domains 
1. cscal.cs - BLAS (CBLAS)
2. cgemm.cs - LAPACK
3. LAPACKE_zgesv.cs - C interface LAPACK function

There is an informative discussion in MKL Forum, please read the thread. It includes several issues:

1) System.Numerics Complex type

If you use System.Numerics Complex type, it corresponds to Z  type in MKL function : complex, double precision(64bit, 8 bytes)

for example, LAPACKE_zgesv, not LAPACKE_cgesv

2) Use the large Array >2G

2.1) .NET allow allocate large array since .NET 4.5, by set the gcAllowVeryLargeObjects = true into the config file.

2.2) when passing large array to native space, the default marshaling doesn't allow large array > 2Bb.  One workaround is to pin the array and pass a pointer to its first element to the native function with the fixed keyword:

using System.Numerics;
using System.Runtime.InteropServices;

[SuppressUnmanagedCodeSecurity]
 internal sealed unsafe class CNative
 {
  private CNative() {}

 /**  native LAPACKE_zgesv declaration */
    [DllImport("mkl_rt.dll", CallingConvention=CallingConvention.Cdecl,
      ExactSpelling=true, SetLastError=false)]
    internal static extern int LAPACKE_zgesv(
    int matrix_layout, 
    int n,
    int nrhs,
    Complex* A,
    int lda,
    int[] ipiv,
    Complex* B,
    int ldb
    );
   }

public unsafe sealed class LAPACK
 {
/** LAPACKE_zgesv wrapper */
  public static int zgesv(int matrix_layout, int n, int nrhs,
   Complex[] A, int lda, int[] ipiv,
   Complex[] B, int ldb)
  {
      fixed (Complex* pA = &A[0])
      fixed (Complex* pB = &B[0])
      // fixed (int* pipiv = &ipiv[0])
   return CNative.LAPACKE_zgesv(matrix_layout, n, nrhs, pA, lda,
      ipiv, pB, ldb);
  }
For more complete information about compiler optimizations, see our Optimization Notice.

Comments


Hello, Micha,

Thank you for the interest to these examples. For MKL 10.0 you need add one more library:

44c44
< MKL_LIB="mkl_intel_c_dll.lib mkl_intel_thread_dll.lib mkl_core_dll.lib"
---
> MKL_LIB="mkl_intel_c_dll.lib mkl_intel_thread_dll.lib mkl_core_dll.lib mkl_solver.lib"

And replace OMP library:

99c99
< libiomp5md.lib $(MSLIB) /out:mkl.dll
---
> libguide40.lib $(MSLIB) /out:mkl.dll

It’s better also to run examples on the drive C: The security permission problem can be appeared otherwise:

Run dgemm example
<…skipped…>
Unhandled Exception: System.Security.SecurityException: System.Security.Permissions.SecurityPermission
at mkl.CBLAS.dgemm(Int32 Order, Int32 TransA, Int32 TransB, Int32 M, Int32 N, Int32 K, Double alpha, Double[] A, Int32 lda, Double[] B, Int32 ldb, Double beta, Double[] C, Int32 ldc)
at test_dgemm.Main(String[] args)

Best regards,
-Vladimir


Sorry, here comes the error code:
D:CsharpTestUmgebungMKL_Einbinden>nmake ia32 MKLROOT="C:ProgrammeIntelMKL10.0.1.015"

Microsoft (R) Program Maintenance Utility, Version 8.00.50727.42
Copyright (C) Microsoft Corporation. Alle Rechte vorbehalten.

Add path of the MKL libraries to the lib environment variable
set lib=%MKLROOT%ia32lib;%lib%
MKL entries for custom dll
Workaround for pardiso
Microsoft (R) 32-Bit C/C++-Optimierungscompiler Version 14.00.50727.42 für 80x86
Copyright (C) Microsoft Corporation. Alle Rechte vorbehalten.

_fseeki64.c
Build MKL custom dll
nmake mkl.dll MACHINE=IX86 MKL_LIB="mkl_intel_c_dll.lib mkl_intel_thread_dll.lib mkl_core_dll.lib" MSL

Microsoft (R) Program Maintenance Utility, Version 8.00.50727.42
Copyright (C) Microsoft Corporation. Alle Rechte vorbehalten.

link /DLL /MACHINE:IX86 /def:user.def _fseeki64.obj mkl_intel_c_dll.lib mkl_intel_thread_dll.lib mkl_cor
Microsoft (R) Incremental Linker Version 8.00.50727.42
Copyright (C) Microsoft Corporation. All rights reserved.

Bibliothek "mkl.lib" und Objekt "mkl.exp" werden erstellt.
mkl_intel_c_dll.lib(_pardiso.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_mkl_solver_pa
mkl.dll : fatal error LNK1120: 1 nicht aufgelöste externe Verweise.
NMAKE : fatal error U1077: ""C:ProgrammeMicrosoft Visual Studio 8VCBINlink.EXE"": Rückgabe-Code "0x460"
Stop.
NMAKE : fatal error U1077: ""C:ProgrammeMicrosoft Visual Studio 8VCBINnmake.EXE"": Rückgabe-Code "0x2"
Stop.


Hi, the example does not work on my system.
As you can see in the errorcode below I am working with MKL 10.0.1.015. I am using Visual Studio 2005 Framework 2.0. Are there any known solutions to this?
Best regards Micha



>> Example: nmake ia32 MKLROOT="c:\program files\intel\mkl\10.1.1.015\ia32\lib"

value of MKLROOT environment variable should be reduced to "C:\Program Files\Intel\MKL\RR.r.y.xxx", where RR.r is the version number, y is the release-update number, and xxx is the package number, for
example, "C:\Program Files\Intel\MKL\10.1.0.004", otherwise you will get compilation and linkage errors.


Pages