在微软的.Net设置线程处理器的亲和力微软、亲和力、线程、处理器

2023-09-02 01:59:20 作者:心跳好吵

(张贴这与答案,因为我无法找到如何做到这一点的任何地方一个完整的解释,所以我认为这可能是有人一定值)

(Posting this with answer because I couldn't find a full explanation of how to do this anywhere, so I thought it might have some value for someone)

我如何设置在微软的.Net特定线程的处理器关系?设置过程中的亲和力,通过System.Diagnostics.Process.ProcessorAffinity,但System.Threading.Thread类没有提供这样的功能和.Net并不保证托管线程链接到任何特定的操作系统线程。

How can I set the processor affinity of a particular thread in Microsoft .Net? Setting the process's affinity is trivial via System.Diagnostics.Process.ProcessorAffinity, but the System.Threading.Thread class offers no such functionality and .Net doesn't guarantee a managed thread is linked to any particular operating system thread.

推荐答案

之间的分离管理和操作系统的线程可以追溯到NET 2.0,并计划由SQL Server团队实现使用纤维净线程。这从来没有真正去任何地方,所以虽然没有保证,有管理的线程将始终运行在相同的操作系统线程,在实践中,这始终是当前所有的.NET主机的情况下。鉴于这种情况并没有在所有这些日子以来的.Net 2.0的推出改变了,这是不可能的,这将永远改变。

The separation between managed and operating system threads dates back to .Net 2.0, and plans by the SQL Server team to implement .Net threads using fibers. This never really went anywhere, so while there is no guarantee that a managed thread will always run on the same operating system thread, in practice this is always the case for all current .Net hosts. Given that this hasn't changed in all the years since .Net 2.0's introduction, it is unlikely this will ever change.

有可能加强我们甚至对于.NET的未来版本信心通过System.Threading.Thread.BeginThreadAffinity方法。这保证了管理的线程将保持在相同的操作系统线程(所以它什么也不做默认的CLR主机上,因为这已经成为事实默认情况下)。我想这还是有可能的,其他管理线程可以共享相同的操作系统线程,但这似乎不太可能,绝对不会在任何当前的.Net主机的情况下。

It is possible to strengthen our confidence even for future versions of .Net by using the System.Threading.Thread.BeginThreadAffinity method. This guarantees that the managed thread will stay on the same operating system thread (so it does nothing on the default CLR host, as that is already true by default). I suppose it is still possible that other managed threads can share the same operating system thread, but this seems unlikely and is definitely not the case in any current .Net hosts.

的.Net提供了使用访问本机操作系统线程System.Diagnostics.ProcessThread类,这个类有采用改变线程的处理器亲和力ProcessorAffinity属性。但是,链接一个特定的管理线程的 ProcessThread 有人故意为难。

.Net provides the ability to access native operating system threads using the System.Diagnostics.ProcessThread class, and this class has the ability to change the thread's processor affinity using the ProcessorAffinity property. However, linking a particular managed thread to its ProcessThread was made deliberately difficult.

的唯一真正的方式来做到这一点是从螺纹自身内部。使用System.AppDomain.GetCurrentThreadId方法(或PInvoke的的GetCurrentThreadId如果你不想叫去precated方法,尽管这将与单声道Windows以外的操作系统无法正常工作)的功能。这然后可以匹配到ProcessThread.Id属性。

The only real way to do it is from inside the thread itself. Use the System.AppDomain.GetCurrentThreadId method (or PInvoke the GetCurrentThreadId function if you don't want to call a deprecated method, though that would not work with Mono on operating systems other than Windows). This can then be matched to the ProcessThread.Id property.

这使得可以与下面的code设置线程的处理器关系(从线程内部调用):

This makes it possible to set the thread's processor affinity with the following code (to be called from inside the thread):

/// <summary>
/// Sets the processor affinity of the current thread.
/// </summary>
/// <param name="cpus">A list of CPU numbers. The values should be
/// between 0 and <see cref="Environment.ProcessorCount"/>.</param>
public static void SetThreadProcessorAffinity(params int[] cpus)
{
    if( cpus == null )
        throw new ArgumentNullException("cpus");
    if( cpus.Length == 0 )
        throw new ArgumentException("You must specify at least one CPU.", "cpus");

    // Supports up to 64 processors
    long cpuMask = 0;
    foreach( int cpu in cpus )
    {
        if( cpu < 0 || cpu >= Environment.ProcessorCount )
            throw new ArgumentException("Invalid CPU number.");

        cpuMask |= 1L << cpu;
    }

    // Ensure managed thread is linked to OS thread; does nothing on default host in current .Net versions
    Thread.BeginThreadAffinity();

#pragma warning disable 618
    // The call to BeginThreadAffinity guarantees stable results for GetCurrentThreadId,
    // so we ignore the obsolete warning
    int osThreadId = AppDomain.GetCurrentThreadId();
#pragma warning restore 618

    // Find the ProcessThread for this thread.
    ProcessThread thread = Process.GetCurrentProcess().Threads.Cast<ProcessThread>()
                               .Where(t => t.Id == osThreadId).Single();
    // Set the thread's processor affinity
    thread.ProcessorAffinity = new IntPtr(cpuMask);
}

请记住,尽管这个工程上的.Net的当前版本,理论上缺乏保证,管理线程绑定到操作系统的线程可以打破这个code的未来。但是,我认为这是极不可能的。

Keep in mind that while this works on current versions of .Net, theoretically the lack of a guarantee that managed threads are bound to OS threads could break this code in the future. However, I consider this extremely unlikely.

 
精彩推荐