2017-10-13 63 views
0

我有一個傳感器向我發送一維浮點數組,我必須在4個不同的子數組中分裂。我的數組表示一個Frame,由1024個Ramps組成。每個Ramp都有4個通道的標題和數據(我想要分割的數據)。每個通道有2個浮標,一個用於實體部分,另一個用於複雜部分。爲了澄清這一點,我已附加的圖像結構爲:拆分由扭曲陣列組成的數組

enter image description here

我需要在4個陣列只數據,每一個用於一個單個信道,以解開這個大陣列。這必須快速完成。我的實施需要大約850毫秒,但可惜這不夠快。到目前爲止,我已經寫下了下面的代碼:

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

也許你應該試試[CodeReview](https://codereview.stackexchange.com/) –

+0

你的圖表看起來不符合你的描述或代碼? 「每個頻道有2個浮動」,但你的圖表顯示每個頻道有8個浮動?什麼是點,什麼是nPoints?你爲什麼一次只複製2個浮點數(根據你的圖,這將是re0 + re1,然後是re2 + re3)?由於您爲其分配了一個「新的float []」,因此我假設'data'是一個'float''Array'。 – NetMage

+0

@NetMage不,它顯示每個通道2個浮動。每個浮點數是4個字節,因此Re0Re1Re2Re3產生一個浮點數並且Im0Im1Im2Im3產生另一個浮點數。 nPoints是4096. Marshal.Copy已將4個字節更改爲浮點數。我需要將兩個浮點數,實部和虛部複製到通道數組中。 – Ignacio

回答

1

Marshal.Copy()很可能是性能瓶頸,因爲它會調用非託管代碼,而且這個調用過於昂貴而無法複製2個浮動內容。以下使用不安全代碼(必須在項目屬性中啓用並且方法必須使用unsafe修飾符修飾)以避免使用Marshal.Copy()並手動複製數據。內循環(遍歷通道)被展開,以獲得一些額外的性能增益(缺點是代碼被硬編碼爲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++); 
     } 
    } 
}