Повышение производительности цикла for при очистке буфера - PullRequest
0 голосов
/ 07 октября 2018

Я собираю 16384 двойных значения с аппаратного устройства, используя библиотеку обработки сигналов.Получаемые мной 16384 значения являются выходом фильтра нижних частот.Я хочу уменьшить выборку в 10 раз. Другими словами, я хочу сохранить 1 балл из каждых 10. Так что в целом это работает так:

  1. Я получаю буфериз моей библиотеки, когда фильтр нижних частот завершен.

  2. Затем я собираю 10 из этих буферов.

  3. Когда все 10 буферов собираются в один буфер, который имеет 10 * 16384, удваивается I, затем я зацикливаюсьсобирая каждый 10-й дубль из буфера.В результате получается один буфер с 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 мс, тогда как все остальноеоколо 20 мкс.
Итак, есть ли способ улучшить общую производительность без использования цикла for?

Обновление ************************** Я определил, что все время обработки в цикле занято, назначая realbuffer 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 голосов
/ 07 октября 2018

Вы можете попробовать поместить каждый буфер в словарь и обработать их для каждого.Теоретически это должно быть быстрее, потому что массивы будут обрабатываться параллельно.20 мс довольно быстро, зачем нужна такая скорость?

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

Затем обработайте что-то вроде этого:

var myData = realbuffer.ToArray();

buffers.Add(bufferCount, myData);

if (bufferCount == 10)
{
   Parallel.ForEach(buffers, (buffer) =>
   {
      //process buffer independently
   });
}
0 голосов
/ 07 октября 2018

Это решено.В библиотеках, которые я использую, есть функция, которая присваивает все значения из двойного [] внутреннему реальному буферу

 realbuffer.Equals(finalBuffer);

Это занимает 50 мкс ... Спасибо за помощь.

0 голосов
/ 07 октября 2018

Вы на самом деле получаете все, а затем отбрасываете ненужные.Как насчет того, чтобы сбросить их без копирования на первом этапе.Я имею в виду, вместо того, чтобы использовать 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++;
}

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...