5

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

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

该应用程序在其自己的专用 16 核 64 位计算机上运行,​​该计算机运行 Windows Server,其可用 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

4 回答 4

2

使用这样的应用程序,我希望更改优先级会对整体运行时间产生 0% 的影响。如果您已经在所有 16 个内核以 100% 的速度完成实际工作的情况下最大限度地使用 CPU,那么您就无能为力了。

于 2012-08-21T09:20:02.050 回答
1

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

但是,我不希望它对像您这样的 CPU 密集型应用程序有任何影响。唯一可以强行抢占您自己进程的进程是 I/O 密集型应用程序,这些应用程序传统上受到大多数操作系统的青睐,但由于您有一台专用机器,这不会成为问题(此外,根据我的经验,Windows Server 非常轻量级,因此如果您的应用程序是唯一运行的应用程序,它不会干扰)。

作为旁注:

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

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

于 2012-08-21T10:37:06.867 回答
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;
        }
    }
}
于 2019-02-18T18:43:21.393 回答
0

我希望您将线程数限制为内核/线程数。有时并行任务库使用太多线程。对于您的 cpumaxed 进程,corecount 或 threadcount(添加了超线程 fakecores)是最好的,因此请提供并修复 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 ;-)

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

于 2012-08-21T11:02:49.973 回答