- 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 extern
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] He 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)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] = B;
}
}
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] It seems it's working fine.- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page