Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Периодические задержки при выполнении программы


Автор: constant 21.12.2015, 09:47
Выполняю задачу, требуется произвести вычисления, настолько быстро, насколько это позволяют ресурсы системы, пусть даже в ущерб всем остальным процессам.
При анализе производительности обратил внимание на следующую особенность. Как правило участки кода выполняются за более-менее одинаковое время, однако, периодически происходят непонятные мне задержки, достаточно длительные.

Я попытался сделать упрощенную модель программы, чтобы показать, то, что я имею в виду.
В программе итеративный процесс, на каждой итерации  длинный внутренний цикл, имитирующий вычисления.
Далее, на каждом цикле запоминаем время окончания вычисления. После  этого находим продолжительность каждой итерации. Находим среднее время итерации. После чего ищем итерации, продолжительность которых более чем в три раза выше средней и выводим их. 
Если посмотреть на продолжительность итераций, то в большинстве случаев они практически одинаковые (порядка 70 мкс в моем случае).Но есть итерации,которые более чем в 8 раз больше среднего.

Следует отметить также, что процессор во время выполнения программы загружается где-то процентов на 13%. Т.е. свободных ресурсов процессора - "выше крыши", процессор используется неэффективно, и программа может быть выполнена гораздо быстрее.Пробовал увеличивать приоритет процесса и потока до максимальных - эффекта практически нет.

Вопросы:

1. Из-за чего происходят большие периодические задержки в выполнении программы, и как от них избавится ?
2. Почему процессорное время используется неэффективно, как задействовать все ресурсы процессора для выполнения программы ?

Код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics;
using System.Threading;
using System.Runtime;
using System.Runtime.CompilerServices;


namespace PerfomanceTest
{
    class Program
    {
        static void Main(string[] args)
        {


            CPerfomanceTest p = new CPerfomanceTest();
            Console.ReadKey();
        }
    }

    public class CPerfomanceTest
    {
        public CPerfomanceTest()
        {
         
           
            List<double> lstTicks = new List<double>();
            List<double> lstTicksDelta = new List<double>();
            
            const int numIter = 100000;
            Stopwatch sw = new Stopwatch();
            sw.Start();

            for (int i = 0; i < numIter; i++)
            {                             
                //Какие-то вычисления
                for (int j = 0; j < 100000; j++) ;

                //запоминаем врмя с начала итерации в микросекундах
                lstTicks.Add(sw.ElapsedTicks * 0.1);                               
            }

            sw.Stop();

            double sum =0;
            double av = 0;

                                       
            for (int i = 1; i < numIter; i++)
            {
                //определяем продолжительность каждой итерации 
                double delta = lstTicks[i] - lstTicks[i - 1];
                lstTicksDelta.Add(delta);                             
            }

            for (int i = 1; i < numIter-1; i++)            
                sum += lstTicksDelta[i];

            
            //находим среднее время итерации
            av = sum / (numIter - 2);

            Console.WriteLine("Average time: "+av);

            Console.WriteLine("");
            Console.WriteLine("Large deviation from average:");

            for (int i = 0; i < numIter-1; i++)            
                //находим отклонение от среднего  времени выполнения итерации в три раза
                if (lstTicksDelta[i] > 3 * av)                
                    Console.WriteLine(i +" -- "+   lstTicksDelta[i]);

                            
            Console.WriteLine("Press any key");
            Console.ReadKey();

        }

    }
}

Автор: chupachups 22.12.2015, 13:13
1) Windows + .NET = никогда не позволят тебе загрузить процессор на 100%, в моем случае процессор загрузился только на 25%.
2) Никогда не определяй производительность запуская программу из студии, особенно с включенным параметром "Enable the Visual Studio hosting process".
3) Даже тестовый код оптимизируй по максимуму (5 запусков, ни одного превышения):
Код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Threading;

namespace PerfomanceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            CPerfomanceTest p = new CPerfomanceTest();

            ThreadStart ts = new ThreadStart(p.Start);
            Thread t = new Thread(ts);
            t.IsBackground = true;
            t.Priority = ThreadPriority.Highest;
            t.Start();
            t.Join();

            p.Results();
            Console.ReadKey();
        }
    }

    public class CPerfomanceTest
    {
        const int numIter = 100000;
        List<double> lstTicks = new List<double>();
        List<double> lstTicksDelta = new List<double>();
        Stopwatch sw = new Stopwatch();

        public CPerfomanceTest()
        {
        }

        public void Start()
        {
            for (int i = 0; i < numIter; i++)
            {
                sw.Restart();
                //Какие-то вычисления
                for (int j = 0; j < numIter; j++)
                {
                    int a = 5 * j;
                }
                //запоминаем время с начала итерации в микросекундах
                double ticks = sw.ElapsedTicks;
                lstTicks.Add(ticks * 0.1);
            }
        }
        public void Results()
        {
            //находим среднее время итерации
            double avg = lstTicks.Average();

            Console.WriteLine("Average time: " + avg);

            Console.WriteLine("");
            Console.WriteLine("Large deviation from average:");

            lstTicks.Where(val => val > 3 * avg)
                .ToList().ForEach(over => Console.WriteLine(String.Format("{0}  ---  {1:n2}", over, over / avg)));

            Console.WriteLine("Press any key");
        }
    }
}


Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Periodicheskiye-zaderzhki-pri-vypolnenii-programmy-id5677a0a3ae20158f668b4568#findElement_E7045_5679223dae20159b44151241_0

Автор: sgrey 23.12.2015, 16:44
Такое поведение программы вплне ожидаемо. Очень трудно нагрузить процессор полностью вычислениями в одном потоке. А причин задержек может быть множество - может context switch происходит в этот момент, а может неудачно в линию кэша попала часть массива, а может ещё много чего и без самих вычислений нельзя сказать точно что происходит. 
Код только из студии запускался? Так нельзя, нужно его отдельно запускать и измерять производительность.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)