Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Increasing thread and process priority to reduce execution time for a processor-intensive, parallelized application

I know that setting thread priority is a bit of a taboo subject on stack overflow but I am convinced that my application is a good candidate for increased priority. To justify that, I have explained the context below. The question now is HOW to do that effectively?

The application is .NET 4 (C#) console application that executes a complex algorithm with an execution time of about five hours. The algorithm is not memory-intensive at all, just processor intensive. It does number crunching and does NOT perform any disk I/O, database connectivity, network connectivity, etc. The output of the application is a just ONE number that it writes to the console at the end. In other words, the algorithm is completely self-contained and has no dependencies.

The application runs on its own dedicated 16 core 64 bit machine running Windows Server with far more free RAM than it requires (8GB). By dedicated I mean the server has been procured to run this application EXCLUSIVELY.

I have already optimized the code as much as I could with extensive profiling, fancy math shortcuts and bit twiddling hacks.

Here is the overall structure in pseudocode:

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

Now based on the thread priority related questions on SO, I gather that anything using ThreadPool should not be messed around with in terms of priority. So If I need to switch to manual threads, so be it.

Question:

  • How should I change the above code to manual threading to benefit from increased thread priority (not using thread pool etc.)?
  • Will setting priority to highest on all child threads even help? I mean will the child threads just be fighting with each other or will that give them an edge over external OS tasks?
  • Considering there are 16 cores, should I be running 16 or 15 threads? Is there a general guideline to this?
  • Will setting process priority to real-time help as well?
like image 880
Raheel Khan Avatar asked Oct 07 '22 21:10

Raheel Khan


2 Answers

With such an app, I would expect changing the priorities to make 0% difference to the overall runtime. If you're already maxed out on CPU use with all 16 cores at 100% doing real work, there's not much more you can do.

like image 134
Martin James Avatar answered Oct 10 '22 02:10

Martin James


You don't need to bother with setting the priority for individual threads, just do it for the entire process, since most of its threads are doing important work apparently.

However, I don't expect it to make any difference for CPU intensive apps like yours. The only processes that could forcibly preempt your own process are I/O intensive apps that traditionally are favored by most OSes, but since you have a dedicated machine, that won't be a problem (also, Windows Server is pretty lightweight in my experience, so it won't interfere if your app is the only one running).

As a side-note:

The algorithm is not memory-intensive at all, just processor intensive. It does number crunching and does NOT perform any disk I/O, database connectivity, network connectivity, etc.

The fact that it does not perform "obvious" I/O operations does not mean that it cannot be memory intensive. If you are processing large arrays or other data-structures, the CPU will constantly emit read/write operations to the main memory and a lot of work is being done to move data between the various memory levels. Even working with just numbers can negatively impact the performance of a program if done incorrectly.

like image 40
Tudor Avatar answered Oct 10 '22 04:10

Tudor