none
在C++/CLI底下使用OpenMP的問題 RRS feed

  • 問題

  • OS: XP SP3

    IDE: VS2010 C++/CLI

    若是使用array型別,則會發生類型 'System.AccessViolationException' 的未處理例外狀況發生於 Test1.exe

    其他資訊: 嘗試讀取或寫入受保護的記憶體。這通常表示其他記憶體已損毀。

    若不用array型別,改用原生的型別,就都正常,但因為UI的部份是C#寫的,會傳入配置好大小的array,在C++這邊再將結果填入

    我的問題是,OpenMP能用.Net的型別嗎?如果可以該怎麼用呢?謝謝

    #include "stdafx.h"<br/>
    #include <omp.h><br/>
    <br/>
    using namespace System;<br/>
    <br/>
    #define DATA_WIDTH 10<br/>
    #define DATA_HEIGHT 10<br/>
    <br/>
    int main(array<System::String ^> ^args)<br/>
    {<br/>
      //模擬硬體產生的資料。<br/>
      double* pH = new double[DATA_WIDTH * DATA_HEIGHT];<br/>
      Byte* pI = new Byte[DATA_WIDTH * DATA_HEIGHT]; <br/>
      for(int i = 0; i < DATA_WIDTH * DATA_HEIGHT; i++)<br/>
      {<br/>
       pH[i] = i;<br/>
       pI[i] = (Byte)i;<br/>
      }<br/>
      //模擬C# Copy資料。<br/>
      array<double>^ arDouble = gcnew array<double>(DATA_WIDTH * DATA_HEIGHT);<br/>
      array<Byte>^ arByte = gcnew array<Byte>(DATA_WIDTH * DATA_HEIGHT);<br/>
      //double* arDouble = new double[DATA_WIDTH * DATA_HEIGHT];<br/>
      //Byte* arByte = new Byte[DATA_WIDTH * DATA_HEIGHT];<br/>
    <br/>
    #pragma omp parallel<br/>
    {<br/>
      #pragma omp for<br/>
      for(int y = 0; y < DATA_HEIGHT; y++)<br/>
       for(int x = 0; x < DATA_WIDTH; x++)<br/>
       {<br/>
        int index = y * DATA_WIDTH + x;<br/>
        arDouble[index] = pH[index];<br/>
        arByte[index] = pI[index];<br/>
       }<br/>
    }<br/>
    <br/>
      for (int i = 0; i < DATA_HEIGHT * DATA_HEIGHT; i++)<br/>
      {<br/>
       Console::WriteLine(String::Format("i = {0}, arDouble = {1}, arByte = {2}", i, arDouble[i], arByte[i]));<br/>
      }<br/>
      Console::ReadLine();<br/>
      return 0;<br/>
    }
    

    2010年11月30日 上午 01:46

解答

  • 謝謝回覆

    不過不是為了使用OpenMP才從C#呼叫C++/CLI的,而是因寪第3方的DLL是用DCOM寫的,直接用C#叫用很慢,所以才用C++包起來。

    以下是我目前覺得比較可行的方式。

    利用GCHandle這個類別

    然後將array的位址固定住,再轉成原生的指標型別,這樣子做就行了。

    前後程式碼就省了。

      GCHandle h1 = GCHandle::Alloc(arDouble, GCHandleType::Pinned);
      GCHandle h2 = GCHandle::Alloc(arByte, GCHandleType::Pinned);
      double *pD2 = (double*)(void*)h1.AddrOfPinnedObject();
      unsigned char *pI2 = (unsigned char*)(void*)h2.AddrOfPinnedObject();
      
    #pragma omp parallel
      {
    #pragma omp for
       for(int y = 0; y < DATA_HEIGHT; y++)
        for(int x = 0; x < DATA_WIDTH; x++)
        {
         int index = y * DATA_WIDTH + x;
         //arDouble[index] = pH[index];
         //arByte[index] = pI[index];
         pD2[index] = pH[index];
         pI2[index] = pI[index];
        }
      }
      h1.Free();
      h2.Free();

    • 已標示為解答 Howard_cmit 2012年9月6日 上午 05:51
    2010年11月30日 上午 03:22

所有回覆

  • 如果您是為了OpenMP平行運算功能, 才從C#呼叫C++/CLI, 可以考慮直接在C#執行平行運算, 請參考:Parallel Computations in C#
    2010年11月30日 上午 02:46
  • 謝謝回覆

    不過不是為了使用OpenMP才從C#呼叫C++/CLI的,而是因寪第3方的DLL是用DCOM寫的,直接用C#叫用很慢,所以才用C++包起來。

    以下是我目前覺得比較可行的方式。

    利用GCHandle這個類別

    然後將array的位址固定住,再轉成原生的指標型別,這樣子做就行了。

    前後程式碼就省了。

      GCHandle h1 = GCHandle::Alloc(arDouble, GCHandleType::Pinned);
      GCHandle h2 = GCHandle::Alloc(arByte, GCHandleType::Pinned);
      double *pD2 = (double*)(void*)h1.AddrOfPinnedObject();
      unsigned char *pI2 = (unsigned char*)(void*)h2.AddrOfPinnedObject();
      
    #pragma omp parallel
      {
    #pragma omp for
       for(int y = 0; y < DATA_HEIGHT; y++)
        for(int x = 0; x < DATA_WIDTH; x++)
        {
         int index = y * DATA_WIDTH + x;
         //arDouble[index] = pH[index];
         //arByte[index] = pI[index];
         pD2[index] = pH[index];
         pI2[index] = pI[index];
        }
      }
      h1.Free();
      h2.Free();

    • 已標示為解答 Howard_cmit 2012年9月6日 上午 05:51
    2010年11月30日 上午 03:22
  • 你好,

    我在C#所撰寫的UI下引用C++的dll, 此dll開啟了OpenMP支援

    但是在執行時卻發生dll not found的錯誤,

    可以請問一下C#引用支援OpenMP的c++ dll有什麼需要注意的地方嗎?

    2012年9月5日 上午 09:20
  • Hi,

    你可以用Dependency Walker去看缺少什麼DLL

    請您確認此DLL是否為VS所開發的,若是,基本上是不需要特別注意什麼的。

    若不是在開發環境,只要裝VC Redistribution就可以了。

    2012年9月6日 上午 05:56