增加线程和进程优先级,以减少处理器密集型并行化应用程序的执行时间

时间:2012-08-21 08:30:32

标签: c# .net multithreading performance optimization

我知道设置线程优先级是堆栈溢出时的一个禁忌主题,但我确信我的应用程序是提高优先级的一个很好的候选者。为了证明这一点,我已经解释了下面的背景。现在的问题是如何有效地做到这一点?

该应用程序是.NET 4(C#)控制台应用程序,它执行复杂的算法,执行时间约为5小时。该算法根本不是内存密集型的,只是处理器密集型。它执行数字运算并且不执行任何磁盘I / O,数据库连接,网络连接等。应用程序的输出只是一个数字,它最后写入控制台。换句话说,该算法完全是自包含的,没有依赖性。

该应用程序在运行Windows Server的专用16核64位计算机上运行,​​其可用RAM远远超过其要求(8GB)。通过专用,我的意思是服务器已被采购以独家运行此应用程序。

我已经通过广泛的分析,花哨的数学快捷方式和尖锐的黑客攻击来尽可能地优化代码。

以下是伪代码的整体结构:

public static void Main ()
{
    Process.GetCurrentProcess().PriorityBoostEnabled = true;
    Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;

    // Of course this only affects the main thread rather than child threads.
    Thread.CurrentThread.Priority = ThreadPriority.Highest;

    BigInteger seed = SomeExtremelyLargeNumber; // Millions of digits.

    // The following loop takes [seed] and processes some numbers.
    result1 = Parallel.For(/* With thread-static variables. */);

    while (true) // Main loop that cannot be parallelized.
    {
        // Processes result1.
        result2 = Parallel.For(/* With thread-static variables. */);

        // Processes result2.
        result1 = Parallel.For(/* With thread-static variables. */);

        if (result1 == criteria)
            break;

        // Note: This loop does not need to sleep or care about system responsiveness.
    }
}

现在基于SO上的线程优先级相关问题,我认为使用ThreadPool的任何东西都不应该在优先级方面被搞乱。所以如果我需要切换到手动线程,那就这样吧。

问题:

  • 如何将上述代码更改为手动线程以从增加的线程优先级(不使用线程池等)中受益?
  • 将所有子线程的优先级设置为最高甚至是否有帮助?我的意思是,子线程会相互争斗还是会让它们优于外部操作系统任务?
  • 考虑到有16个核心,我应该运行16或15个线程吗?是否有一般指导原则?
  • 将设置流程优先考虑到实时帮助吗?

4 个答案:

答案 0 :(得分:2)

使用这样的应用程序,我希望更改优先级,使整个运行时间有0%的差异。如果您已经完全消耗了CPU使用率,并且所有16个内核都在100%做真正的工作,那么您可以做的就更多了。

答案 1 :(得分:1)

您不需要为单个线程设置优先级,只需为整个过程执行此操作,因为它的大多数线程显然都在做重要的工作。

然而,我不认为它会对像您这样的CPU密集型应用产生任何影响。可强制抢占自己进程的唯一进程是传统上受大多数操作系统青睐的I / O密集型应用程序,但由于您拥有专用计算机,因此不会出现问题(同样,Windows Server在我的体验中非常轻量级) ,如果您的应用程序是唯一正在运行的应用程序,它将不会干扰。

作为旁注:

  

该算法根本不是内存密集型的,只是处理器   密集。它执行数字运算并且不执行任何磁盘I / O,   数据库连接,网络连接等

它不执行“明显的”I / O操作这一事实并不意味着它不会占用大量内存。如果您正在处理大型数组或其他数据结构,CPU将不断地向主存储器发出读/写操作,并且正在进行大量工作以在各种存储器级别之间移动数据。如果处理不当,即使只处理数字也会对程序的性能产生负面影响。

答案 2 :(得分:1)

我的代码可以更改进程和线程的优先级。

public void SetPriorityProcessAndTheards(string nameProcess,ProcessPriorityClass processPriority, ThreadPriorityLevel threadPriorityLevel)
{
    foreach(Process a in Process.GetProcessesByName(nameProcess))
    {
        a.PriorityBoostEnabled = true;
        a.PriorityClass = processPriority;

        foreach(ProcessThread processThread in a.Threads)
        {
            processThread.PriorityLevel = threadPriorityLevel;
            processThread.PriorityBoostEnabled = true;
        }
    }
}

答案 3 :(得分:0)

我希望您将线程数限制为核心/线程数。有时并行任务库使用太多线程。对于你的cpumaxed进程,corecount或threadcount(添加超线程假冒伪造)最好,所以提供并修复threadcount;

 // Create a ParallelOptions object and supply this to the Parallel.For() 

 var po = new ParallelOptions {MaxDegreeOfParallelism = Environment.ProcessorCount}
 Parallel.For(,,po,);

 // Environment.ProcessorCount gives number of Cores (NOT processors)
 // Never found out how to detect fake cores or hyperthreads, check Task Monitor ;-)

您可以为所有parallel.For()语句重用po对象。即使在CPU绑定的线程应用程序上,我也从未真正受益于优先级摆弄。