2017-10-13 20 views
0

私は4つの異なるサブアレイに分割しなければならない1次元のフロートアレイを私に送るセンサを持っています。私の配列はフレームを表し、それは1024ランプで構成されています。各ランプには4つのチャンネル(分割したいデータ)のヘッダとデータがあります。各チャンネルには2つの浮動小数点数があり、1つは実部用、もう1つは複雑部用です。これを明確にするために、私は構造の画像を添付した:私はデータと4列、単一チャネルのための各一つにこの大きな配列を解明する必要がねじれたアレイで構成されたアレイを分割する

enter image description here

。これは速く行わなければなりません。私の実装には約850msかかりますが、残念ながらこれは十分に速くはありません。これまでのところ私は次のコードを書いています:

IntPtr ptr = (IntPtr)frameInfo.ptr; // The pointer to the buffer 

for (int i = 0; i < nChannels; i++) 
{ 
    channelFrames[i].data = new float[nRamps * nPoints * 2]; 
} 

for (int ramp = 0; ramp < nRamps; ramp++) 
{ 
    ptr += (int)rawHeaderSize; // Skip the header 

    for (int point = 0; point < nPoints; point++) 
    { 
      for (int channel = 0; channel < nChannels; channel++) 
      { 
       Marshal.Copy(ptr, channelFrames[channel].data, (int)(point *2 + ramp*nPoints*2), 2); 

       ptr += (sizeof(float) * 2); // Move to the next data       
      } 
    } 
} 

これをもっと速くする方法はありますか?

+1

たぶん、あなたは試してみてください[コードレビュー](https://codereview.stackexchange.com/) –

+0

あなたの図は、あなたの説明やコードが一致していないようですか? 「各チャンネルには2つの浮動小数点数がありますが、ダイアグラムにはチャネルごとに8つの浮動小数点が表示さ何がポイントで、nPointsとは何ですか?そして、なぜあなたは一度に2つのフロートをコピーしていますか(それはあなたのダイアグラムに従ってre0 + re1、re2 + re3になります)?あなたが 'new float []'を代入しているので、 'data'は' float''Array'であると仮定します。 – NetMage

+0

@NetMageいいえ、チャンネルごとに2つのフロートを表示します。各フロートは4バイトなので、Re0Re1Re2Re3はフロートを作成し、Im0Im1Im2Im3は別のフロートを作成します。 nPointsは4096です.Marshal.Copyはすでに4バイトをfloatに変更します。浮動小数点数、実数部、虚数部の両方をチャンネル配列にコピーする必要があります。 – Ignacio

答えて

1

Marshal.Copy()は、アンマネージコードを呼び出すため、パフォーマンスのボトルネックになりがちです。この呼び出しは、2つのフロートをコピーするには高価です。以下は、Marshal.Copy()の使用を避けるために、安全でないコード(プロジェクトのプロパティで有効にする必要があり、メソッドにunsafe修飾子を付ける必要があります)を使用してデータを手動でコピーします。また、いくつかの追加のパフォーマンス向上のために、内部ループ(チャネルを反復する)がアンロールされます(これは、4つのチャネルに対してコードがハードコードされていることを意味します)。

私の測定では、元の方法に比べてパフォーマンスが約10倍向上しています。

//Pin arrays with channel data in memory and get pointers of these fixed arrays 
fixed (float* fixed_ch0ptr = channelFrames[0].data) 
fixed (float* fixed_ch1ptr = channelFrames[1].data) 
fixed (float* fixed_ch2ptr = channelFrames[2].data) 
fixed (float* fixed_ch3ptr = channelFrames[3].data) 
{ 
    //fixed arrays pointer cannot be modified, we must create writable copies ot these pointers 
    float* ch0ptr = fixed_ch0ptr; 
    float* ch1ptr = fixed_ch1ptr; 
    float* ch2ptr = fixed_ch2ptr; 
    float* ch3ptr = fixed_ch3ptr; 

    //unsafe pointer to array from sensor 
    float* floatptr = (float*)ptr; 

    for (int ramp = 0; ramp < nRamps; ramp++) 
    { 
     floatptr = (float*)((byte*)(floatptr) + (int)rawHeaderSize); // Skip the header 

     for (int point = 0; point < nPoints; point++) 
     { 
      //Unrolling loop that iterates over channelFrames can give as some additional performance gains 

      //copy channel 0 data 
      *ch0ptr++ = *(floatptr++); 
      *ch0ptr++ = *(floatptr++); 

      //copy channel 1 data 
      *ch1ptr++ = *(floatptr++); 
      *ch1ptr++ = *(floatptr++); 

      //copy channel 2 data 
      *ch2ptr++ = *(floatptr++); 
      *ch2ptr++ = *(floatptr++); 

      //copy channel 3 data 
      *ch3ptr++ = *(floatptr++); 
      *ch3ptr++ = *(floatptr++); 
     } 
    } 
} 
関連する問題