2012-09-08 38 views
7

Ben nasılSeti iplik işlemci yakınlık .Net

(I Bu her yerde nasıl yapılacağı tam bir açıklamayı bulamadığı için cevap bu Gönderme, bu yüzden birisi için bazı değere sahip olabileceğini düşündüm) Belirli bir iş parçacığının işlemci benzeşimini Microsoft .Net? İşlemin afinitesini ayarlamak System.Diagnostics.Process.ProcessorAffinity aracılığıyla önemsizdir, ancak System.Threading.Thread sınıfı böyle bir işlev sunmaz ve .Net, yönetilen bir iş parçacığının herhangi bir işletim sistemi iş parçacığına bağlı olduğunu garanti etmez.

cevap

25

Yönetilen ve işletim sistemi iş parçacıkları arasındaki ayrılık, .Net 2.0'a kadar uzanır ve SQL Server ekibinin, fiberleri kullanarak .Net iş parçacıklarını gerçekleştirmesi için planlar. Bu hiçbir zaman gerçekten hiçbir yere gitmedi, bu yüzden yönetilen bir iş parçacığının her zaman aynı işletim sistemi iş parçacığı üzerinde çalışacağını garanti etmese de, pratikte bu her zaman geçerli. Net ana bilgisayarları için geçerlidir. Net 2.0'ın girişinden bu yana tüm yılların değişmediği düşünüldüğünde, bu durumun hiç değişmeyeceği düşünülüyor.

System.Threading.Thread.BeginThreadAffinity yöntemini kullanarak .Net'in gelecek sürümlerinde bile güvenimizi güçlendirmek mümkündür. Bu, yönetilen iş parçacığının aynı işletim sistemi iş parçacığında kalmasını garanti eder (bu nedenle varsayılan CLR ana bilgisayarında hiçbir şey yoktur, varsayılan olarak zaten doğrudur). Diğer yönetilen iş parçacıklarının aynı işletim sistemi iş parçacığını paylaşabilmesinin hala mümkün olduğunu düşünüyorum, ancak bu olası görünmüyor ve kesinlikle geçerli olan herhangi bir .NET sunucusunda durum böyle değil.

.Net, System.Diagnostics.ProcessThread sınıfını kullanarak yerel işletim sistemi iş parçacıklarına erişme yeteneği sağlar ve bu sınıf, iş parçacığının işlemci benzeşimini ProcessorAffinity özelliğini kullanarak değiştirme yeteneğine sahiptir. Bununla birlikte, belirli bir yönetilen ipliğin ProcessThread'a bağlanması kasıtlı olarak zorlaştırılmıştır.

Bunu yapmanın tek gerçek yolu, iş parçacığının içinden geliyor. System.AppDomain.GetCurrentThreadId yöntemini kullanın (ya da kullanımdan kaldırılmış bir yöntemi çağırmak istemiyorsanız, GetCurrentThreadId işlevini çağırın), ancak bu, Windows dışındaki işletim sistemlerinde Mono ile çalışmayacaktır). Bu daha sonra ProcessThread.Id özelliğine eşleştirilebilir.

Bu sayede aşağıdaki kodla parçacığının işlemci yakınlık ayarlamayı sağlar (iplik içinden çağrılacak):

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

unutmayın bu teorik olarak, Net bugünkü sürümlerinde çalışır iken bu Yönetilen iş parçacıklarının OS iş parçacıklarına bağlı olduğu garantisinin olmaması, bu kodu gelecekte bozabilir. Ancak, bu son derece olası düşünmüyorum.