在 C# 中设置处理器关联性不起作用

问题描述 投票:0回答:1

我正在 Amzon EC2 云中运行的 Windows 服务器上运行程序。我使用的实例有 32 个可用虚拟核心。我想展示系统的线性可扩展性,因此需要控制系统可以运行的内核数量。我正在尝试使用

ProcessorAffinity
类的
Process
属性来做到这一点。准确地说,我设置亲和力的代码如下:

void SetCPU(int numCPU)
{
    var currentProcess = Process.GetCurrentProcess();
    Debug.Assert(numCpu <= Environment.ProcessorCount)
    var str = GetProcessorAffinityString(numCPU);
    var serverProcessorAffinity = Convert.ToInt64(str, 2);
    currentProcess.ProcessorAffinity = (IntPtr)serverProcessorAffinity;
}
//Produces output: numCpu=4 -> 0000 0000 0000 0000 0000 0000 0000 1111
//...............: numCpu=8 -> 0000 0000 0000 0000 0000 0000 1111 1111
//...............: numCpu=16 -> 0000 0000 0000 0000 1111 1111 1111 1111
//...
static string GetProcessorAffinityString(int numCPU)
{
    var str = "";
    for (int i = 0; i < Environment.ProcessorCount; i++)
    {
        if (i < numCPU) str += "1";
        else str += "0";
    }
    //Reverse
    char[] charArray = str.ToCharArray();
    Array.Reverse(charArray);
    return new string(charArray);
}

但是,当我运行程序时,无论输入

numCpu
是什么,进程始终使用32个核心。我可以在资源管理器中手动更改它作为解决方法,但理想情况下我希望以编程方式完成此操作。

有人知道这段代码可能有什么问题吗?

c# process
1个回答
0
投票

不要构建和解析一些 Int64 值(这里我很困惑你为什么这样做),而是尝试使用简单的位掩码来获取必要的 CPU 编号:

var cpuBitMask = 1 << (cpuNumber - 1);

这里

cpuNumber
int
值,代表CPU(核心)数量(非从零开始)。

为了简化使用,可以创建一个扩展方法来设置

ProcessorAffinity

public static class ProcessExtensions
{
    public static void SetProcessorAffinity(this Process process, int cpuNumber)
    {
        if (process is null)
            throw new ArgumentNullException(nameof(process));
        if (cpuNumber <= 0 || cpuNumber > Environment.ProcessorCount)
            throw new ArgumentOutOfRangeException("CPU number must be greater than 0 and less than total CPUs amount");

        var cpuBitMask = 1 << (cpuNumber - 1);
        process.ProcessorAffinity = (IntPtr)cpuBitMask;
    }
}

以及 ofc,使用示例(控制台应用程序):

public static void Main()
{
    using var currentProcess = Process.GetCurrentProcess();

    for (var cpuNumber = 1; cpuNumber <= Environment.ProcessorCount; cpuNumber++)
    {
        currentProcess.SetProcessAffinity(cpuNumber);
        Console.WriteLine($"Running single-CPU test for 10 seconds on CPU #{cpuNumber}...");

        // Primitive CPU (core) loadout for 10 seconds
        var timer = Stopwatch.StartNew();
        while (timer.Elapsed.TotalSeconds < 10) { }
        timer.Reset();
    }
 
    Console.ReadKey();
}
© www.soinside.com 2019 - 2024. All rights reserved.