4

2 つのスレッドによって異なる方法で分析されている巨大な配列があります。

  • データが大きい - コピー不可
  • スレッドは同時に処理する必要があります
  • 最大のパフォーマンスを得るには、境界チェックを無効にする必要があります

したがって、各スレッドは次のようになります。

unsafe void Thread(UInt16[] data)
{
  fixed(UInt16* pData = data)
  {
    UInt16* pDataEnd = pData + data.Length;
    for(UInt16* pCur=pData; pCur != pDataEnd; pCur++)
    {
      // do stuff
    }
  }
}

(意図的に)ミューテックスがないので、並列スレッドで同じデータに対して 2 つの固定ステートメントを使用しても安全かどうか疑問に思っています?? おそらく、メモリは既に固定されているため、2番目の固定は最初と同じポインターを返す必要があります...そして、最初の固定が完了すると、2番目の固定()がまだアクティブであるため、実際にはメモリの固定が解除されません..誰かがこれを試しましたか?シナリオ?

4

3 に答える 3

2

「C#経由のCLR」によると、そうしても安全です。

pDataコンパイラは、変数に (配列インスタンスではなくポインターに) '固定' フラグを設定します。

したがって、複数/再帰的な使用は問題ありません。

于 2012-04-12T19:03:30.757 に答える
1

あなたがする必要があるのは

 for(int i = 0; i < data.Length; i++)
 {
     // do stuff with data[i]
 }

境界チェックは、JITコンパイラによって排除されます。したがって、安全でないコードは必要ありません。

アクセスパターンがそれよりも複雑な場合、これは当てはまらないことに注意してください。

于 2012-04-12T19:15:20.337 に答える
1

fixed を使用する代わりに、GCHandle.Alloc を使用して配列を固定することもできます。

// not inside your thread, but were you init your shared array
GCHandle handle = GCHandle.Alloc(anArray, GCHandleType.Pinned);
IntPtr intPtr = handle.AddrOfPinnedObject();


// your thread
void Worker(IntPtr pArray)
{
  unsafe
  {
     UInt16* ptr = (UInt16*) pArray.ToPointer();
      ....
  }
}        
于 2012-04-12T19:13:30.657 に答える