- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[csharp]public static extern void DSYEV_INTEROP(string JOBZ, string UPLO, int N, ref double[] A, int LDA, ref double[] W, ref double[] WORK, int LWORK, ref int INFO);[/csharp]
[fortran]SUBROUTINE DSYEV_INTEROP(JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO) !DEC$ ATTRIBUTES DLLEXPORT::DSYEV_INTEROP !DEC$ ATTRIBUTES STDCALL::DSYEV_INTEROP !DEC$ ATTRIBUTES ALIAS:"DSYEV_INTEROP"::DSYEV_INTEROP !DEC$ ATTRIBUTES VALUE::JOBZ !DEC$ ATTRIBUTES VALUE::UPLO !DEC$ ATTRIBUTES VALUE::N !DEC$ ATTRIBUTES REFERENCE::A !DEC$ ATTRIBUTES VALUE::LDA !DEC$ ATTRIBUTES REFERENCE::W !DEC$ ATTRIBUTES REFERENCE::WORK !DEC$ ATTRIBUTES VALUE::LWORK !DEC$ ATTRIBUTES REFERENCE::INFO CHARACTER(LEN=1), INTENT(IN) :: JOBZ, UPLO INTEGER, INTENT(IN) :: N, LDA, LWORK INTEGER, INTENT(OUT) :: INFO !REAL*8, DIMENSION(:,:), INTENT(INOUT) :: A REAL*8, POINTER, DIMENSION(:,:) :: A REAL*8, DIMENSION(:), INTENT(INOUT) :: W, WORK CALL dsyev(JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO) END SUBROUTINE DSYEV_INTEROP[/fortran]
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You do not need to write wrappers. Please see examples of using MKL in C#:
http://software.intel.com/en-us/articles/using-intel-mkl-in-your-c-program/
You need not also to build custom dll if you use MKL 10.3.
Thanks,
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am not using the makefile, but am using it as an example to follow. I first compiled the _fseeki64.c file as in the makefile using the Microsoft C compiler (I don't have the Intel one). I then tried a variation on the link command, having set additional environment variables for the MKL libraries and compiler libraries:
MKLROOT=C:\Program Files (x86)\Intel\ComposerXE-2011\mkl\lib\intel64
OMPLIB=C:\Program Files (x86)\Intel\ComposerXE-2011\compiler\lib\intel64
where each file was preceeded with the necessary environment variable:
link /DLL /MACHINE:X64 /def:user.def _fseeki64.obj %MKLROOT%\mkl_intel_lp64_dll.lib %MKLROOT%\mkl_intel_thread_dll.lib %MKLROOT%\mkl_core_dll.lib %OMPLIB%\libiomp5md.lib msvcrt.lib user32.lib /out:mkl.dll
All files are found, but then I get the error:
LINK : error LNK2001: unresolved external symbol _DllMainCRTStartup
mkl.dll : fatal error LNK1120: 1 unresolved externals
Basically, what am I doing wrong?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I am using eigen values/vectors decomposition DSYEV in mkl for a university project and I need results to be reproductible.
I wrote a little wrapper (according to examples) to call DSYEV from C# :
namespace Eigen
{
class Solve
{
public double[,] decompo(double[,] A)
{
int lwork = -1;
int n = A.GetLength(0);
int lda = n;
double[] A_bis = new double[n * n];
double[] w = new double;
for (int i = 0; i < n; i++)
{
int cte = i * n;
for (int j = 0; j < n; j++)
{
A_bis[cte + j] = A[j, i];
}
}
lwork = -1;
double[] work_1 = new double[1];
int info = LAPACK_mkl.dsyev('V', 'U', n, A_bis, lda, w, work_1, lwork);
lwork = (int)work_1[0];
double[] work = new double[lwork];
info = LAPACK_mkl.dsyev('V', 'U', n, A_bis, lda, w, work, lwork);
double[,] res2 = new double[n, n + 1];
for (int i = 0; i < n; i++)
{
res2[i, 0] = w;
for (int j = 0; j < n; j++)
{
res2[i, j + 1] = A_bis[i + j * n];
}
}
GC.Collect(0);
return res2;
}
}
}
namespace mkl
{
public sealed class LAPACK_mkl
{
private LAPACK_mkl() { }
public static int dsyev(char jobz, char uplo, int N, double[] A, int LDA, double[] w, double[] work, int lwork)
{
LAPACKNative.kmp_set_warnings_off();
int num = Environment.ProcessorCount;
LAPACKNative.omp_set_num_threads(ref num);
int info = -1;
LAPACKNative.dsyev(ref jobz, ref uplo, ref N, A, ref LDA, w, work, ref lwork, ref info);
return info;
}
}
/** LAPACK native declarations */
[SuppressUnmanagedCodeSecurity]
internal sealed class LAPACKNative
{
[DllImport("libiomp5md", EntryPoint = "omp_set_num_threads")]
internal static extern void omp_set_num_threads(ref int num);
[DllImport("libiomp5md", EntryPoint = "kmp_set_warnings_off")]
internal static extern void kmp_set_warnings_off();
[DllImport("mkl", EntryPoint = "DSYEV", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
internal static extern void dsyev(ref char jobz, ref char uplo, ref int n, double[] A, ref int lda, double[] w, double[] work, ref int lwork, ref int info);
private LAPACKNative()
{
kmp_set_warnings_off();
int num = Environment.ProcessorCount;
omp_set_num_threads(ref num);
}
}
}
I red something about memory alignment and 16-byte boundaries... does this apply here ?
Thank you for any answer or comment on my code
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I've seen an assertion that Intel C++ new would observe alignments specified by _declspec(align(16)). The Microsoft page states clearly that you must use _declspec, with _declspec(align(32)) preferred for improved caching and compatibility with AVX.
You omitted needed header definitions, which I wouldn't consider obvious.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[bash] [DllImport("ippcore-7.0.dll",EntryPoint="ippMalloc")] private static externHe checks whether to use the 32-bit or X64 ipp .dll (according to IntPtr.Size), then uses the ippMalloc, which is said to return a 64-byte aligned region. You could use that one, if you don't mind involving another big .dll, or use mkl_malloc(length, alignment)
IntPtr Malloc_x32
(int length );
[DllImport("ippcoreem64t-7.0.dll",EntryPoint="ippMalloc")] private static extern
IntPtr Malloc_x64
(int length );
public IntPtr Malloc (int length ) {
if (IntPtr.Size == 8)
return Malloc_x64(length);
else
return Malloc_x32(length);
}
[/bash]
For that matter, I would think you could still use the _aligned_malloc provided by Visual Studio.
We just noticed that VS2010 doc says the standard default malloc() provides 16-byte alignment. No idea if that would carry over to c# new. Prior to VS2010, malloc was 16-byte aligned only in the X64 version.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
a_ptr=mkl_malloc(alloc_size,alignment);
[csharp] public static unsafe IntPtr mkl_malloc(int length) { LAPACKNative.kmp_set_warnings_off(); int align = 32; IntPtr pointer = LAPACKNative.Malloc(length, align); return pointer; } [DllImport("mkl_rt.dll", EntryPoint = "MKL_MALLOC", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] internal static extern IntPtr Malloc(int length, int align);[/csharp]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[csharp]public unsafe double[] linsolve(ref double[,] A, ref double[] B) { int m = A.GetLength(0); int n = A.GetLength(1); int lwork = -1; int lda = m; int ldb = m; int nrhs = 1; int rank = 0; int align = 128; IntPtr pointer_A_bis_ini = Marshal.AllocHGlobal(m * n * sizeof(double) + align); IntPtr pointer_A_bis = pointer_A_bis_ini; IntPtr pointer_B_bis_ini = Marshal.AllocHGlobal(n * nrhs * sizeof(double) + align); IntPtr pointer_B_bis = pointer_B_bis_ini; Int64 adresse_A_bis = pointer_A_bis.ToInt64() % align; Int64 adresse_B_bis = pointer_B_bis.ToInt64() % align; int offset = 0; while (adresse_A_bis != 0) { offset++; pointer_A_bis = new IntPtr(pointer_A_bis_ini.ToInt64() + offset); adresse_A_bis = pointer_A_bis.ToInt64() % align; } offset = 0; while (adresse_B_bis != 0) { offset++; pointer_B_bis = new IntPtr(pointer_B_bis_ini.ToInt64() + offset); adresse_B_bis = pointer_B_bis.ToInt64() % align; } double* A_bis = (double*)pointer_A_bis.ToPointer(); double* B_bis = (double*)pointer_B_bis.ToPointer(); for (int i = 0; i < nrhs; i++) { int cte = i * m; for (int j = 0; j < m; j++) { B_bis[cte + j] = BIt seems it's working fine.; } } for (int i = 0; i < n; i++) { int cte = i * m; for (int j = 0; j < m; j++) { A_bis[cte + j] = A[j, i]; } } if (m == n) { IntPtr pointer_IPIV_ini = Marshal.AllocHGlobal(m * sizeof(int) + align); IntPtr pointer_IPIV = pointer_IPIV_ini; Int64 adresse_IPIV = pointer_IPIV.ToInt64() % align; offset = 0; while (adresse_IPIV != 0) { offset++; pointer_IPIV = new IntPtr(pointer_IPIV_ini.ToInt64() + offset); adresse_IPIV = pointer_IPIV.ToInt64() % align; } int* IPIV = (int*)pointer_IPIV.ToPointer(); for (int i = 0; i < m; i++) { IPIV = 0; } LAPACK_mkl.dgetrf(m, m, A_bis, m, IPIV); LAPACK_mkl.dgetrs('N', m, nrhs, A_bis, m, IPIV, B_bis, m); double[] res2 = new double ; for (int i = 0; i < n; i++) { res2 = B_bis; } Marshal.FreeHGlobal(pointer_A_bis_ini); Marshal.FreeHGlobal(pointer_B_bis_ini); Marshal.FreeHGlobal(pointer_IPIV_ini); return res2; } else { int maxMN; if (m > n) { maxMN = m; } else { maxMN = n; } IntPtr pointer_JPVT_ini = Marshal.AllocHGlobal(n * sizeof(int) + align); IntPtr pointer_JPVT = pointer_JPVT_ini; Int64 adresse_JPVT = pointer_JPVT.ToInt64() % align; offset = 0; while (adresse_JPVT != 0) { offset++; pointer_JPVT = new IntPtr(pointer_JPVT_ini.ToInt64() + offset); adresse_JPVT = pointer_JPVT.ToInt64() % align; } int* JPVT = (int*)pointer_JPVT.ToPointer(); for (int i = 0; i < n; i++) { JPVT = 0; } double RCOND = 2.0E-16; IntPtr pointer_work_1 = Marshal.AllocHGlobal(sizeof(double)); double* work_1 = (double*)pointer_work_1.ToPointer(); LAPACK_mkl.dgelsy(m, n, nrhs, A_bis, lda, B_bis, maxMN, JPVT, RCOND, rank, work_1, lwork); lwork = (int)work_1[0]; IntPtr pointer_work_ini = Marshal.AllocHGlobal(lwork * sizeof(double) + align); IntPtr pointer_work = pointer_work_ini; Int64 adresse_work = pointer_work.ToInt64() % align; offset = 0; while (adresse_work != 0) { offset++; pointer_work = new IntPtr(pointer_work_ini.ToInt64() + offset); adresse_work = pointer_work.ToInt64() % align; } double* work = (double*)pointer_work.ToPointer(); LAPACK_mkl.dgelsy(m, n, nrhs, A_bis, m, B_bis, maxMN, JPVT, RCOND, rank, work, lwork); double[] res2 = new double ; for (int i = 0; i < n; i++) { res2 = B_bis; } Marshal.FreeHGlobal(pointer_work_1); Marshal.FreeHGlobal(pointer_work_ini); Marshal.FreeHGlobal(pointer_A_bis_ini); Marshal.FreeHGlobal(pointer_B_bis_ini); Marshal.FreeHGlobal(pointer_JPVT_ini); GC.Collect(0); return res2; } }[/csharp]

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page