Software Archive
Read-only legacy content
17061 Discussions

How to dllexport with MIC offload?

Aleksandr_S_1
Beginner
733 Views

I got dllexport not recognized error.

I find that certain features are not supported with offload:

"When you use code with these features in your application, you must correctly structure the code so that it is not visible in a target compilation.

These features include, but are not limited to: . . .

  • The storage-class attributes dllexport and dllimport. For example:

    __declspec(dllexport) void foo(void);"
    

Could someone please advise - how do I correctly structure the code to export a method from dll which uses MIC offload.

I ultimately want to call a C++ function from C#, the C++ part should offload some of the calculations to MIC.

I chose p/invoke so I need dllexport for that. But will take another route if its same efficient. 

The current code is:

extern "C"
{
 void MatrixAddConstMic(double *data, int len, double addValue)
 {
#pragma offload target(mic) inout(data:length(len)) 
  {
   for (size_t k = 0; k < 10; k++)
    for (size_t j = 0; j < len; j++)
#pragma omp parallel for
     for (size_t i = 0; i < len; i++)
     {
      data += addValue;
     }
  }
 }

 __declspec(dllexport) void MatrixAddConst(double *data, int len, double addValue)
 {
  MatrixAddConstMic(data, len, addValue);
 }
}

 

0 Kudos
1 Solution
Kevin_D_Intel
Employee
733 Views

I suspect since you found the other related discussion (here) you will be successful using the __MIC__ predefine to guard the Windows* dllexport directive for the host compilation only.

For example, you could modify lines 17-20 in your example snippet as follows:

#ifndef __MIC__  
     __declspec(dllexport) void MatrixAddConst(double *data, int len, double addValue)  
    {
         MatrixAddConstMic(data, len, addValue);  
     }  
#endif

Let us know whether you are successful or have additional questions/problems.

View solution in original post

0 Kudos
4 Replies
Kevin_D_Intel
Employee
734 Views

I suspect since you found the other related discussion (here) you will be successful using the __MIC__ predefine to guard the Windows* dllexport directive for the host compilation only.

For example, you could modify lines 17-20 in your example snippet as follows:

#ifndef __MIC__  
     __declspec(dllexport) void MatrixAddConst(double *data, int len, double addValue)  
    {
         MatrixAddConstMic(data, len, addValue);  
     }  
#endif

Let us know whether you are successful or have additional questions/problems.

0 Kudos
Aleksandr_S_1
Beginner
733 Views

thank you Kevin. it worked. I could compile it ok. but then it fails to run.

I have very simple code - 3 projects. C# WPF app, managed Visual C++, unmanaged Intel C++. C# calls Visual C++ wrapper which call unmanaged exported function which calls unmanaged function with #omp pragma to offload to MIC.

If I comment out #omp pragma all is working. but with the pragma it fails with attempted to write to illegal portion of memory. This is very common error for managed/unmanaged interop, which most likely not related to c++ writing into wrong address (as C++ devs would presume).

You don't happen to know what could it be?

0 Kudos
Kevin_D_Intel
Employee
733 Views

No I do not, sorry. If you can share that simple code with us then we will investigate further. You can attach to a private message to me if you wish the keep the code accessible only to Intel staff

0 Kudos
Aleksandr_S_1
Beginner
733 Views

Ok. I had two approaches - one using P/Invoke (it has 2 projects) and through C++/CLI wrapper (3 projects).

This is P/Invoke version:

Native Intel C++ project (options created by Visual Studio 2013:

/GS /Qopenmp /W3 /Gy /Zc:wchar_t /Zi /O2 /Fd"x64\Release\vc120.pdb" /D "_MBCS" /Qipo /Zc:forScope /Oi /MD /Fa"x64\Release\" /EHsc /nologo /Fo"x64\Release\" /Qprof-dir "x64\Release\" /Fp"x64\Release\Unmanaged2.pch"

#include <cstdlib>
#include <cstdio>

extern "C"
{
 void MatrixAddConstMic(double *data, int len, double addValue)
 {
#pragma offload target(mic) inout(data:length(len)) 
  {
   for (size_t k = 0; k < 10; k++)
    for (size_t j = 0; j < len; j++)
#pragma omp parallel for
     for (size_t i = 0; i < len; i++)
     {
      data += addValue;
     }
  }
 }

#ifndef __MIC__

 __declspec(dllexport) void MatrixAddConst(double *data, int len, double addValue)
 {
  MatrixAddConstMic(data, len, addValue);
 }

#endif

}

The C# code:

        // c# declaration
        [DllImport(@"..\..\..\..\x64\Release\Unmanaged2.exe", CallingConvention = CallingConvention.Cdecl)]
        public static extern void MatrixAddConst
        (
          [In][MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.R8)] double[] arr,
          int len,
          double addValue
        );
...
        int len = 10000;
        private unsafe void Button_Click(object sender, RoutedEventArgs e)
        {
            double[] arr = new double[len];
            GCHandle gch = GCHandle.Alloc(arr, GCHandleType.Pinned);
            IntPtr pArrayData = gch.AddrOfPinnedObject();

            MatrixAddConst(arr, len, 12.1);

            gch.Free();
        }

Error (fires on call MatrixAddConst - in bold):

Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

NB : When I comment out line "#pragma offload target(mic) inout(data:length(len))" everything works fine.

0 Kudos
Reply