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

问题描述 投票:4回答:4

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

该应用程序是.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的任何东西都不应该在优先级方面被搞乱。所以如果我需要切换到手动线程,那就这样吧。

题:

  • 如何将上述代码更改为手动线程以从增加的线程优先级(不使用线程池等)中受益?
  • 将所有子线程的优先级设置为最高甚至是否有帮助?我的意思是,孩子们的线程会相互争斗,还是会让他们比外部OS任务更具优势?
  • 考虑到有16个核心,我应该运行16或15个线程吗?这是否有一般指导原则?
  • 将设置过程优先考虑到实时帮助吗?
c# .net multithreading performance optimization
4个回答
2
投票

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


1
投票

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

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

作为旁注:

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

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


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;
        }
    }
}

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绑定的线程应用程序上,我也从未真正受益于优先级摆弄。

© www.soinside.com 2019 - 2024. All rights reserved.