Подтвердить что ты не робот

Как я могу программно ограничить использование моего процессора процессором до 70%?

В последнее время я становлюсь более ориентированным на здоровье при построении своей программы, я заметил, что большинство программ занимают 2 или 3 минуты, и когда я проверяю планировщик задач, я вижу, что они потребляют 100% процессора использование, можно ли ограничить это использование программно в коде? Это, безусловно, позволит мне запускать несколько программ в данный момент времени.

Спасибо, Nidhi

4b9b3361

Ответ 1

Это не ваша забота... Это задача операционной системы распределять процессорное время между запущенными процессами. Если вы хотите, чтобы другие процессы сначала взломали процесс их создания, просто уменьшите приоритет своего процесса, изменив Process.PriorityClass для него.

См. также: Эквивалент Windows" хороший

Ответ 2

Эта тема старше четырех лет, и меня все еще раздражает, что принятый ответ критикует вопрос, а не отвечает на него. Есть много веских причин, по которым вы хотели бы ограничить время процессора, затраченное вашей программой, я могу перечислить несколько от верхней части головы.

Может показаться, что отходы не используют все свободные циклы процессора, но этот менталитет является ошибочным. В отличие от старых процессоров большинство современных процессоров не работают с фиксированной тактовой частотой - у многих есть режимы энергосбережения, где они снижают тактовую частоту и напряжение процессора при низкой загрузке. Процессоры также потребляют больше энергии при выполнении вычислений, чем при использовании NOOP. Это особенно важно для ноутбуков, которые требуют, чтобы вентиляторы охлаждали CPU, когда он находится под большой нагрузкой. Запуск задачи на 100% за короткое время может использовать гораздо больше энергии, чем выполнение задачи на 25% в четыре раза.

Представьте, что вы пишете фоновое задание, предназначенное для периодического индексирования файлов в фоновом режиме. Должна ли задача индексирования использовать как можно большую часть процессора, так как она может иметь более низкий приоритет, или дросселировать себя до 25% и принимать столько, сколько нужно? Ну, если бы он потреблял 100% процессора на ноутбуке, процессор нагревался, вентиляторы могли бы вздрогнуть, и батарея разрядилась бы довольно быстро, и пользователь будет раздражаться. Если служба индексирования дросселировалась сама собой, ноутбук может работать с полностью пассивным охлаждением при очень низкой тактовой частоте и напряжении процессора.

Кстати, служба индексирования Windows теперь активизируется в новых версиях Windows, чего она никогда не делала в более старых версиях. Для примера службы, которая все еще не дросселирует себя и часто раздражает людей, см. Модуль установщика Windows.

Пример того, как внутренне использовать часть вашего приложения внутри С#:

public void ThrottledLoop(Action action, int cpuPercentageLimit) {
    Stopwatch stopwatch = new Stopwatch();

    while(true) {
        stopwatch.Reset();
        stopwatch.Start();

        long actionStart = stopwatch.ElapsedTicks;
        action.Invoke();
        long actionEnd = stopwatch.ElapsedTicks;
        long actionDuration = actionEnd - actionStart;

        long relativeWaitTime = (int)(
            (1/(double)cpuPercentageLimit) * actionDuration);

        Thread.Sleep((int)((relativeWaitTime / (double)Stopwatch.Frequency) * 1000));
    }
}

Ответ 3

Вы можете написать класс Governor, который дросселирует использование ЦП. Этот класс будет содержать метод утилиты, который должен вызываться на регулярной основе (например, вызывать эту служебную функцию в цикле while вашей функции) вашей функцией привязки к процессору. Губернатор будет проверять, превысило ли количество пройденного времени определенного порога, а затем спать в течение определенного периода времени, чтобы не потреблять весь процессор.

Здесь простая реализация Java с моей точки зрения (так вы получите эту идею), которая уменьшит использование процессора до 50%, если у вас есть одна связанная с потоком функция привязки к процессору.

public class Governor
{
  long start_time;

  public Governor()
  {
    this.start_time = System.currentTimeMillis();
  }

  public void throttle()
  {
    long time_elapsed = System.currentTimeMillis() - this.start_time;

    if (time_elapsed > 100) //throttle whenever at least a 100 millis of work has been done
    {
      try { Thread.sleep(time_elapsed); } catch (InterruptedExceptione ie) {} //sleep the same amount of time

      this.start_time = System.currentTimeMillis(); //reset after sleeping.
    }
  }
}

Ваша функция привязки процессора создаст экземпляр Governor, а затем просто вызовет throttle на регулярной основе внутри функции.

Ответ 4

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

Вместо того, чтобы внедрить дросселирование в бизнес-код, вы можете сами разработать алгоритм для работы на полную мощность и просто дросселировать поток, который запускает операцию "извне". Общий подход такой же, как в ответе Райана. Рассчитайте время приостановки на основе текущего использования и приостановите поток для этого промежутка времени, прежде чем возобновлять его снова. Учитывая процесс, который вы хотите активировать, это логика:

public static class ProcessManager
{
    [Flags]
    public enum ThreadAccess : int
    {
        TERMINATE = (0x0001),
        SUSPEND_RESUME = (0x0002),
        GET_CONTEXT = (0x0008),
        SET_CONTEXT = (0x0010),
        SET_INFORMATION = (0x0020),
        QUERY_INFORMATION = (0x0040),
        SET_THREAD_TOKEN = (0x0080),
        IMPERSONATE = (0x0100),
        DIRECT_IMPERSONATION = (0x0200)
    }

    [DllImport("kernel32.dll")]
    static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);

    [DllImport("kernel32.dll")]
    static extern uint SuspendThread(IntPtr hThread);

    [DllImport("kernel32.dll")]
    static extern int ResumeThread(IntPtr hThread);

    [DllImport("kernel32.dll")]
    static extern int CloseHandle(IntPtr hThread);

    public static void ThrottleProcess(int processId, double limit)
    {
        var process = Process.GetProcessById(processId);
        var processName = process.ProcessName;
        var p = new PerformanceCounter("Process", "% Processor Time", processName);
        while (true)
        {
            var interval = 100;
            Thread.Sleep(interval);

            var currentUsage = p.NextValue() / Environment.ProcessorCount;
            if (currentUsage < limit) continue;
            var suspensionTime = (currentUsage-limit) / currentUsage * interval;
            SuspendProcess(processId);
            Thread.Sleep((int)suspensionTime);
            ResumeProcess(processId);
        }
    }

    private static void SuspendProcess(int pid)
    {
        var process = Process.GetProcessById(pid);

        if (process.ProcessName == string.Empty)
            return;

        foreach (ProcessThread pT in process.Threads)
        {
            IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);

            if (pOpenThread == IntPtr.Zero)
            {
                continue;
            }

            SuspendThread(pOpenThread);

            CloseHandle(pOpenThread);
        }
    }

    private static void ResumeProcess(int pid)
    {
        var process = Process.GetProcessById(pid);

        if (process.ProcessName == string.Empty)
            return;

        foreach (ProcessThread pT in process.Threads)
        {
            IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);

            if (pOpenThread == IntPtr.Zero)
            {
                continue;
            }

            var suspendCount = 0;

            do
            {
                suspendCount = ResumeThread(pOpenThread);
            } while (suspendCount > 0);

            CloseHandle(pOpenThread);
        }
    }
}

Преимущество этого решения заключается в том, что интервал проверки не зависит от продолжительности вашей "долгосрочной задачи". Кроме того, бизнес-логика и логика дросселирования разделены. Код ожидания/резюме вдохновлен этой нитью. Обратите внимание, что удаление и прекращение дросселирования должно быть реализовано в вышеприведенном решении, это не производственный код.

Ответ 5

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

Ответ 6

Если у вас многоядерный процессор, вы можете настроить Affinity для каждого процесса, чтобы использовать только те ядра, которые вы хотите использовать. Это самый близкий метод, о котором я знаю. Но это позволит вам назначать проценты, которые составляют 50% на двухъядерном процессоре, и 25% на четырехъядерном ядре.

Ответ 7

Вы можете запустить свою программу в потоке с более низким threadpriority, остальное зависит от вашей операционной системы. Наличие процесса съедает 100% вашего процессора, это неплохо. Мой SETI обычно занимает все оставшееся время процессора, не беспокоясь о моих других программах. Это становится проблемой, когда ваш поток получает приоритет над более важными программами.

Ответ 8

Если код вообще запущен, он находится на уровне 100%

Я полагаю, что скольжение в некоторых сна может иметь эффект.

Мне нужно задуматься об этой 2-3-минутной фигуре. Я тоже это видел, и я полагаю, что он загружает и инициализирует множество вещей, которые мне, вероятно, не нужны.

Ответ 9

Я думаю, что вам нужно понять, что проблема с производительностью в вашем приложении, а не пытаться установить ограничение на использование ЦП. Вы можете использовать Visual Studio Profiler, чтобы узнать, почему приложение использует 100% процессор в течение 2-3 минут. Это должно показать горячую точку в вашем приложении, а затем вы сможете решить эту проблему.

Если вы вообще просите о том, как делать дросселирование ресурсов в окнах, вы можете посмотреть объекты "Задача", объекты "Объект" позволяют устанавливать ограничения, такие как рабочий набор, приоритет процесса... и т.д.

Вы можете проверить документацию объектов работы здесь http://msdn.microsoft.com/en-ca/library/ms684161(VS.85).aspx Надеюсь это поможет. Благодаря

Ответ 10

Спасибо всем за ответ. Я работаю над этим, а exe работает несколько часов и хочет поделиться, чтобы помочь другим. Я написал класс, который я собираюсь установить и забыть в приложении WPF, которое будет зашифровывать и выталкивать данные в облако, но я никогда не мог когда-либо вмешиваться в время создания WPF-приложения и того, что нужно WPF-приложению на пути к ресурсам, которые я также собираюсь добавить флаг для отключения, когда приложение WPF находится в нем с наивысшим уровнем потребления ресурсов. Я уже очень прорисовал этот WPF с помощью TPL. Это решение имеет как приоритет процесса

myProcess.PriorityClass = ProcessPriorityClass.Idle;

и процент процессора ограничен.

то в моем mainDisplay.xaml.cs я буду использовать

ProcessManagement.StartProcess(5);

в MainWindow()

И при вскрытии этого exe окна не появляется окно

RedirectStandardOutput = true,  
UseShellExecute = false,
CreateNoWindow = true

в инициализаторе объекта

internal class ProcessManagement
{
    private static int CpuPercentageLimit { get; set; }

    public static void StartProcess(int cpuPercent)
    {
        CpuPercentageLimit = cpuPercent;
        var stopwatch = new Stopwatch();
        while (true)
        {
            stopwatch.Reset();
            stopwatch.Start();
            var actionStart = stopwatch.ElapsedTicks;
            try
            {
                var myProcess = new Process
                {
                    StartInfo =
                    {
                        FileName = @"D:\\Source\\RemMon\\RemMon\\bin\\Debug\\RemMon.exe",
                        RedirectStandardOutput = true,
                        UseShellExecute = false,
                        CreateNoWindow = true
                    }
                };
                myProcess.Start();
                myProcess.PriorityClass = ProcessPriorityClass.Idle;
                myProcess.Refresh();
                myProcess.WaitForExit();
                var actionEnd = stopwatch.ElapsedTicks;
                var actionDuration = actionEnd - actionStart;
                long relativeWaitTime = (int)((1 / (double)CpuPercentageLimit) * actionDuration);
                var sleepTime = (int)((relativeWaitTime / (double)Stopwatch.Frequency) * 1000);
                Thread.Sleep(sleepTime);
                myProcess.Close();
            }
            catch (Exception e)
            {
                // ignored
            }
        }
    }
}

В моем приложении достаточно времени, например 24/7/365, для загрузки большого количества данных, включая тысячи изображений, но пользовательский интерфейс также должен оставаться активным при использовании и при запуске системы, ничего другого не может быть Бег.

Ответ 11

Если нет другой задачи, не так ли для вашего приложения использовать всю доступную емкость процессора? Он доступен, так как в нем есть и он свободен в использовании. Так что используйте его!

Если вы каким-то образом ограничиваете использование процессора своей задачей, это займет больше времени. Но он все равно будет принимать одинаковое количество циклов процессора, поэтому вы ничего не получите. Вы просто замедляете свое приложение.

Не делай этого. Даже не пытайтесь. Нет причин, почему вы должны.