抽取缓冲区时提高for循环的性能

时间:2018-10-06 21:12:38

标签: c# performance for-loop

我正在使用信号处理库从硬件设备收集16384个双精度值。我收到的16384值是低通滤波器的输出。我想将采样降低10倍。换句话说,我希望每10个采样点中保留1分。因此,总的来说,它的工作原理如下:

  1. 低通滤波器完成后,我从库中获取了一个缓冲区。

  2. 然后我收集了10个这些缓冲区。

  3. 当所有10个缓冲区都收集到一个具有10 * 16384双精度的缓冲区中时,我然后从该缓冲区循环收集每10个double。结果是一个缓冲区有16384双打。这将用于其余的数据处理。

代码如下:

double[] rawData = new double[163840];
int bufferCount = 0;

private void genericReal2_ProcessData(object Sender, Mitov.SignalLab.ProcessRealNotifyArgs Args)
{
    var realbuffer = Args.InBuffer; //get the buffer of processed doubles

    var myData = realbuffer.ToArray(); //must be converted to an array since the data type is not quite an array of doubles.

    Array.Copy(myData, 0, rawData, bufferCount * 16384, 16384);

    bufferCount++;

    if (bufferCount == 10)
    {
        bufferCount = 0;

        int j = 0;

        for (int i = 0; i < 163840; i += 10) //this loop takes 20ms
        {
            realbuffer[j] = rawData[i];                   
            j++;
        }

        genericReal2.SendData(realbuffer); //send data off for further processing
    }
}

for循环大约需要20毫秒才能运行,而其他一切大约需要20uS。
因此,有什么方法可以在不使用for循环的情况下提高整体性能吗?

更新************************** 我已经确定将循环中的所有处理时间都分配给realData给rawData。所以我将其更改如下:

    private void genericReal2_ProcessData(object Sender, Mitov.SignalLab.ProcessRealNotifyArgs Args)
    {
        double[] finalBuffer = new double[16384];

        var realbuffer = Args.InBuffer; //get the buffer of processed doubles

        var myData = realbuffer.ToArray(); //must be converted to an array since the data type is not quite an array of doubles.

        Array.Copy(myData, 0, rawData, bufferCount * 16384, 16384);

        bufferCount++;

        if (bufferCount == 10)
        {
            bufferCount = 0;

            int j = 0;

            for (int i = 0; i < 163840; i += 10)
            {
                finalBuffer[j] = rawData[i];
                j++;
            }

             var pointer= realbuffer.Read();
             //I can get a pointer to the realbuffer.
             //It stores 8 bytes for every double value
             how can I copy 16384 8 byte values from finalbuffer to realbuffer?


            genericReal2.SendData(realbuffer); //send data off for further processing
        }

3 个答案:

答案 0 :(得分:1)

此问题已解决。我使用的库具有一个函数,该函数会将double []的所有值分配给它的内部实缓冲区

 realbuffer.Equals(finalBuffer);

这需要50us ... 感谢您的所有帮助。

答案 1 :(得分:0)

您实际上正在得到所有东西,然后丢弃不必要的东西。如何在不进行复制的情况下删除这些文件,该如何做?我的意思是不是使用Array.Copy而是复制所需的内容;

int j = bufferCount * 16384;
for (int i = 0; i < 16384; i += 10)
{
    realbuffer[j++] = rawData[i];
}

这样做,您将不需要在if语句中运行循环。

如果由于任何条件都无法更改代码的整体结构,则可以通过排序算法中使用的技术来提高循环性能。定义大小为163840 + 1的数组。为数组的最后一个位置分配一些值,例如-1,它将不在接收到的数据之内。并按如下所示更改循环,以减少执行循环中的比较次数;

for (int i = 0; i < rawData[i+=10 ] !=-1; ) 
{
    realbuffer[j] = rawData[i];
    j++;
}

希望有帮助。

答案 2 :(得分:-1)

您可以尝试将每个缓冲区放入字典,然后对每个缓冲区进行处理。从理论上讲,这应该更快,因为将并行处理数组。 20ms相当快,为什么需要这样的速度?

var buffers = new Dictionary<int, double[]>();

然后执行以下操作:

var myData = realbuffer.ToArray();

buffers.Add(bufferCount, myData);

if (bufferCount == 10)
{
   Parallel.ForEach(buffers, (buffer) =>
   {
      //process buffer independently
   });
}