2012-09-08 6 views
7

(私はこれのどこを行う方法の完全な説明を見つけることができなかったので、私はそれが誰かのためにいくつかの値を持っているかもしれないと思ったので、答えをこの投稿)設定スレッドのプロセッサアフィニティを

どのようにすることができますMicrosoft .Netで特定のスレッドのプロセッサアフィニティを設定しますか?プロセスの親和性の設定はSystem.Diagnostics.Process.ProcessorAffinityでは簡単ですが、System.Threading.Threadクラスではこのような機能は提供されていません。管理されたスレッドが特定のオペレーティングシステムスレッドにリンクされていることを保証するものではありません。

答えて

25

マネージドスレッドとオペレーティングシステムスレッドの分離は、.NET 2.0以降であり、SQL Serverチームがファイバを使用して.Netスレッドを実装することを計画しています。これは本当にどこにも行きませんでした。管理スレッドが常に同じオペレーティングシステムスレッドで実行される保証はありませんが、実際には現在のすべての.Netホストにとって常にそうです。 .Net 2.0の導入以来、これは何年も変わっていないことを考えると、これは変わることはまずありません。

System.Threading.Thread.BeginThreadAffinityメソッドを使用すると、.Netの将来のバージョンでも自信を強めることができます。これにより、マネージスレッドは同じオペレーティングシステムスレッド上にとどまることが保証されます(デフォルトのCLRホストでは何も実行しません。他の管理対象スレッドが同じオペレーティングシステムスレッドを共有できることはまだ考えられますが、現在の.Netホストではそうは思われません。

.Netは、System.Diagnostics.ProcessThreadクラスを使用してネイティブオペレーティングシステムスレッドにアクセスする機能を提供します。このクラスは、ProcessorAffinityプロパティを使用してスレッドのプロセッサアフィニティを変更できます。しかし、特定の管理対象スレッドをそのProcessThreadにリンクすることは、意図的に困難でした。

本当にそれを行う唯一の方法は、スレッド自体の内部からです。 System.AppDomain.GetCurrentThreadIdメソッドを使用してください(または、推奨されないメソッドを呼びたくない場合はGetCurrentThreadId関数を呼び出しますが、Windows以外のオペレーティングシステムではMonoでは機能しません)。これはProcessThread.Idプロパティに一致させることができます。

これは、次のコード(スレッド内から呼び出されるため)とスレッドのプロセッサアフィニティを設定することが可能になる:理論的には、これはネットの現在のバージョンで動作しながら、ということを覚えておいてください

/// <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); 
} 

管理スレッドがOSスレッドにバインドされているという保証がないため、将来このコードが破損する可能性があります。しかし、私はこれを考えていません。

関連する問題