Search code examples
c#multithreadingopenmp

Does C# provide a way to set OMP threads for a process?


C / C++ provide for a way to set the number of OMP threads, but I'm wondering if C# has a similar functionality.

Basically, my use case is that I've got an external executable that brings every core up to 100% usage when it runs. I'd like to test if the application performs any better if it was using one core at a time. On my windows machine, I did run the command set OMP_NUM_THREADS=1 and saw that the executable ran in a comparable time, but on only 1 core instead, as expected.

I have a C# test program that can spawn N multiple threads which each run a copy of the executable. I'd like to be able to run each of those threads with OMP_NUM_THREADS set to one, with the hope that only N of my cpu cores go up to full usage.

Note: I'm using the System.Diagnostics Process class to run my process through separate threads.


Solution

  • I was able to arrive at a solution that worked for me, thanks to the various links Robert Harvey posted above. The link most helpful to me was http://blog.rebuildall.net/2010/03/08/Running_NET_threads_on_selected_processor_cores.

    int affinity = 1; // needs to be greater than 0
    string parameters = string.Format("{0} {1} {2}", cmdLineParam1, cmdLineParam2, cmdLineParam3);
    
    Process process = new Process();
    process.StartInfo = new ProcessStartInfo()
    {
        Arguments = parameters,
        CreateNoWindow = true,
        FileName = pathToExe,
        WindowStyle = ProcessWindowStyle.Hidden
    };
    
    process.Start();
    
    try
    {
        // try to run this process on one dedicated CPU
        if (affinity > 0)
            process.ProcessorAffinity = new IntPtr(affinity);
    }
    catch (Exception e)
    {
        Console.WriteLine("Could not set process affinity: {0}", e.Message);
    }
    
    // limit run-time of the process
    if (process.WaitForExit(90000) == false)
    {
        process.Kill();
        Console.WriteLine("Process has ran longer than 90 seconds, timing it out now.");
    }
    

    Note that if you run this code across multiple threads, like I am doing, you will need to set a separate affinity for each thread, so that they'll use different CPU cores.

    Also note that affinity is a bitmask...This means that the number 3 indicates that a process should run on CPU cores 1 and 2, not core 3. to help with generating the bitmask, I wrote the code below:

    public static int GetProcessorBitMask(int numProcessors, int startingProcessor)
    {
        Console.WriteLine("numProcessors: {0}  |  startingProcessor: {1}", numProcessors, startingProcessor);
        int mask = (int) Math.Pow(2, numProcessors) - 1;
        mask <<= (startingProcessor - 1);
        return mask;
    }