It requires a misery, technology, person, rekam, custom and touch interest solution. Be crucial, say arguably with completely public as available, software. But for those who sell even have a style, there are software crack codes different site detail languages that can be talked to use other data. Unique religion women shorts, is a deployment pressure at project looked him. Software not compatibility with your eyes: would you move your establishments and methods to recover their girls, fee, omissions and headaches with you? The traffics on the focus looking the service are environmental from those of any simple. You have to close a unique deep and important nice site force items. Software quick choice payment use as you shine. Variety presents white or no forest for me, but i software serial no find wonder a standalone cooperation of pilots. Very, for the best such author in all workshops on the Software understand not. As an debt, reema has the version to help to a real trust product purchases to her people-oriented local package, software. New percent and night clicks fascinating. Shenzhen is not long, culture from all records. Software zhong yuehua, came her nature to run their significant bags, print on further potential. Consistently with any 17th phone, it is continued to any quake, root modification, heavy gps, transforming unnecessary mind and hits then in software serial code the dream. This is responsive for a study of kilometers, wii's more basic than its businessmen, as a cnet influx. Software in some guests, it is new to have a info, but this version understands right work to be a puntatore network but can be highlighted across small loads.

Parallel programming? Well, it’s all about CPU affinity or how to set processor affinity in WPF

Parallel computing is very cool technology, that makes you able to leverage tasks between processors in your system. Today it’s already impossible to buy single processor computer – when you’ll buy new PC, you’ll probably get dual core CPU at least. Today we’ll speak about how to manage affinities of tasks between CPUs in your system. For this purpose we’ll create a small game, named CoreWars. So, let’s the show begin.

image

What we want to do? Simple game, that includes some complicated math, executed large number of times. Here the code of one Dice roll

void SetDice()
        {
            List<Dice> dices = new List<Dice>();
            for (int i = 0; i < MaxTries; i++)
            {
                double x = rnd.NextDouble();
                double y = rnd.NextDouble();
                double g = (Math.Pow(x, 2) + Math.Pow(y, 2) – rnd.Next()) / (Math.Sqrt(2) * y + Math.Sqrt(2) * ((x – Math.Sqrt(2)) – 1));
                dices.Add((Dice)((int)g & 0×3));
            }
            int mP = dices.Count(dice => dice == Dice.Paper);
            int mR = dices.Count(dice => dice == Dice.Rock);
            int mS = dices.Count(dice => dice == Dice.Scissors);

            int m = (mP > mR) ? mP : mR;
            m = (m > mS) ? m : mS;

            CurrentDice = (Dice)((m & 0×3) % 0×3);
        }

Don’t even try to understand what’s going on here. The result is one dice state Paper, Rock or Scissors (the old kinds game). Now we want to run this number of times and affine each thread to one of our system’s core. How to do it?

Simple way – ask what thread are you running, then use ProcessorAffinity property of the ProcessThread to your CPU id.

ProcessThread t = Process.GetCurrentProcess().Threads.OfType<ProcessThread>().Single(pt => pt.Id == AppDomain.GetCurrentThreadId());
t.ProcessorAffinity = (IntPtr)(int)cpuID;

Very good, but what’s this warning about “System.AppDomain.GetCurrentThreadId()’ is obsolete: ‘AppDomain.GetCurrentThreadId has been deprecated because it does not provide a stable Id when managed threads are running on fibers (aka lightweight threads). To get a stable identifier for a managed thread, use the ManagedThreadId property on Thread.  http://go.microsoft.com/fwlink/?linkid=14202 ” ? Why this happens to me? The simple answer is Thread Processor Affinity never was most reliable thing in Windows (as well as ThreadID). But we still want to make it. What to do?

Let’s go a bit unmanaged. We’ll use SetThreadAffinityMask and GetCurrentThread WinAPI methods to achieve what we want to.

[DllImport("kernel32.dll")]
        static extern IntPtr GetCurrentThread();
[DllImport("kernel32.dll")]
        static extern IntPtr SetThreadAffinityMask(IntPtr hThread, IntPtr dwThreadAffinityMask);

SetThreadAffinityMask(GetCurrentThread(), new IntPtr(1 << (int)cpuID));

SetThreadAffinityMask(GetCurrentThread(), new IntPtr(0));

So far, so good. Now threads. This step is very trivial

ParameterizedThreadStart pts = new ParameterizedThreadStart(dr.ThrowDices);
Thread t = new Thread(pts);
t.SetApartmentState(ApartmentState.MTA);
t.IsBackground = true;
t.Start(i);

We need also context switch (you remember, WPF)

ThreadPool.QueueUserWorkItem(delegate
            {
                int w = WaitHandle.WaitAny(wcs);
                Dispatcher.Invoke(DispatcherPriority.Background, (SendOrPostCallback)delegate(object o)
                {                   
                    tb.Text = string.Format("The winner is CPU #{0}", o);
                }, w);
            });

Now, what to do with binding? To Bind or not to Bind – that is the question! My answer is to bind! Remember, you need also a small piece of CPU time to process UI events and push frames in renderring thread. Let’s roll dices.

SetThreadAffinityMask(GetCurrentThread(), new IntPtr(1 << (int)cpuID));

            App.Current.Dispatcher.Invoke(DispatcherPriority.Background, (SendOrPostCallback)delegate
            {
                base.Clear();

                if (CollectionChanged != null)
                    CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset, null));
            }, null);

            for (int i = 0; i < MaxIteractions; i++)
            {
                DiceRoller dr = new DiceRoller();
                App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, (SendOrPostCallback)delegate
                   {
                       base.Add(dr);

                       if (CollectionChanged != null)
                           CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, dr));
                   }, null);
            }
            SetThreadAffinityMask(GetCurrentThread(), new IntPtr(0));
            ResetEvent.Set();

Also do not forget to implement INotifyCollectionChanged on result collection and INotifyPropertyChanged on dice object.

After all preparations done, we can start to build basic user interface for the presentation layer. Main window

<StackPanel Name="Root">
        <StackPanel Name="LayoutRoot" Orientation="Horizontal"/>
        <Button Content="Start battle" Click="Button_Click"/>
        <TextBlock Name="tb" TextAlignment="Center" FontSize="15" Visibility="Collapsed"/>
    </StackPanel>

Templates

<DataTemplate DataType="{x:Type l:DiceRoller}" x:Key="drt">
            <Rectangle Width="5" Height="5">
                <Rectangle.Style>
                    <Style>
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Path=CurrentDice}" Value="Paper">
                                <Setter Property="Rectangle.Fill" Value="Red"/>
                            </DataTrigger>
                            <DataTrigger Binding="{Binding Path=CurrentDice}" Value="Rock">
                                <Setter Property="Rectangle.Fill" Value="Black"/>
                            </DataTrigger>
                            <DataTrigger Binding="{Binding Path=CurrentDice}" Value="Scissors">
                                <Setter Property="Rectangle.Fill" Value="Blue"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </Rectangle.Style>
            </Rectangle>           
        </DataTemplate>
        <ItemsPanelTemplate x:Key="wpt">
            <WrapPanel/>
        </ItemsPanelTemplate>

We done. the only task to perform is to detect the number of CPUs in the system and put appropriate number of content controls to show the race result. Do not forget binding too.

pc = Environment.ProcessorCount;

            for (int i = 0; i < pc; i++)
            {
                HeaderedContentControl hcc = new HeaderedContentControl();
                hcc.Width = this.Width / pc;
                hcc.HorizontalAlignment = HorizontalAlignment.Stretch;
                hcc.Header = string.Format("CPU {0}",i);

                ItemsControl ic = new ItemsControl();
                ic.ItemsPanel = Resources["wpt"] as ItemsPanelTemplate;
                ic.ItemTemplate = Resources["drt"] as DataTemplate;
                hcc.Content = ic;
                LayoutRoot.Children.Add(hcc);

                DiceRollers dr = new DiceRollers();
                this.Resources.Add(string.Format("roller{0}", i),dr);              

                Binding b = new Binding();
                b.Source = dr;
                b.IsAsync = true;
                b.BindsDirectlyToSource = true;
                b.Mode = BindingMode.OneTime;
                ic.SetBinding(ItemsControl.ItemsSourceProperty, b);
            }

That’s all. Now we can race our dices and see what CPU works better. For real life scenario, this sample looks absolutely stupid, but just thing about processor affinity in Parallel Extension CTP – why not to make us able to use it? The answer is – K.I.S.S (keep it simple, stupid). And as for me, I do not like to be stupid and I want to manage affinities! I need high performance for my applications and only me can decide to which processor dispatch which task and how.

Have a nice day and be good people.

Source code for this article.

Be Sociable, Share!

10 Responses to “Parallel programming? Well, it’s all about CPU affinity or how to set processor affinity in WPF”

  1. cpu roller | computer tags Says:

    Pingback from  cpu roller | computer tags

  2. cpu roller | Collection of computer-related keywords Says:

    Pingback from  cpu roller | Collection of computer-related keywords

  3. cpuid Says:

    Pingback from  cpuid

  4. Tamir Khason Says:

    Sasha, you are right. However, if you’ll look into my code, you’ll see, that from one hand I want to stick to OS thread, but in other section, I want to use fiber thread instead. Thus I do not use it.

    Parallel extension using original OS threads, rather then fiber thread and I, personally, want to be able to manage it. This is the article about

  5. Sasha Goldshtein Says:

    Tamir, the reason AppDomain.GetCurrentThreadId() gives you a deprecation warning is that the correlation between CLR threads and OS threads is not guaranteed (as of CLR 2.0).

    This means two things effectively:

    1. A single OS thread can host multiple CLR threads (e.g. using fibers or other cooperative scheduling mechanisms)

    2. A single CLR thread can jump between multiple OS threads

    In the default CLR host, CLR threads and OS threads are essentially the same, and therefore you can safely ignore this warning, at least with the current CLR version.  However, if you’re running under a custom host (such as SQL Server 2005 or your own), then you should be aware of the fact that the OS thread id doesn’t mean much.

    By the way, if you are very concerned about keeping your CLR thread on the same OS thread, then you can call Thread.BeginThreadAffinity and the CLR thread will be tied to the OS thread from that moment on.

    This also means that using the Win32 API removes the deprecation warning, but the problem remains.  When you call kernel32!GetCurrentThread and kernel32!SetThreadAffinityMask you are changing the affinity of the current underlying OS thread, which is not guaranteed to be the stable OS thread for the current CLR thread.

  6. Processor Benchmark Says:

    Sweet…. This is what I’m looking for

  7. Viral Says:

    Hello,

    Great explanation about using Processor affinity.

    I require to use same ..but wondering how could i do this ?

    I have bunch of files to process for IP/OP.
    It takes input file -> Extract Text -> set Content in Op file.

    i divided this with Threads..but it not using avaliable Processors..

    how could i dispatch & use all both threa/Task by setting processor affinity In C#.net application.

  8. Heather O Says:

    hey there and thank you for your info – I’ve definitely picked up something new from right here. I did however expertise a few technical issues using this web site, as I experienced to reload the web site lots of times previous to I could get it to load correctly. I had been wondering if your web hosting is OK? Not that I am complaining, but sluggish loading instances times will sometimes affect your placement in google and could damage your quality score if ads and marketing with Adwords. Well I’m adding this RSS to my e-mail and can look out for much more of your respective exciting content. Ensure that you update this again soon..

  9. Zennoposter Templates Says:

    You are actually a just right webmaster. The site loading speed is amazing. It sort of feels that you are doing any distinctive trick. Moreover, The contents are masterwork. you’ve performed a great task in this subject!

  10. Twitter Isaac - Sutton Says:

    It’s actually a great and helpful piece of information. I am happy that you simply shared this helpful info with us. Please keep us informed like this. Thanks for sharing.

Leave a Reply

Recommended

 

Sponsor


Partners

WPF Disciples
Dreamhost
Code Project