Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Sunday, 05 May 2013

Microsoft® Accelerator v2 provides an effective way for applications to implement array-processing operations using the parallel processing capabilities of multi-processor computers.

Accelerator handles all the details of parallelizing and running the computation on the selected target processor, including GPUs and multicore CPUs.

http://research.microsoft.com/en-us/projects/accelerator/

Install DirectX (98MB)

http://www.microsoft.com/en-us/download/details.aspx?id=35

or entire SDK (571MB) – June 2010

“Failure to create a DirectX 9 Device” – error fixed by target change to .NET2.  And running without attaching a debugger.. ie Ctrl-F5

image

To get the AddArrays first sample working:

  • Add ref to c:\Program Files (x86)\Microsoft\Accelerator v2\bin\Managed\Microsoft.Accelerator.dll
  • Target to x64
  • .NET version to 2
  • Copy copy accelerator.dll from C:\Program Files (x86)\Microsoft\Accelerator v2\bin\x64 to bin debug of my project

dxdiag tool useful to see what version of DirectX

image

Non debug…works!

image

Conways Game of Life Sample

Included in the install file for Accelerator

image
Turned ticks down to 1.  So GPU is going at 12%.. and I’ve got 1 core running fairly hard updating the UI

image
Running only on CPU’s.

| | # 
# Wednesday, 01 May 2013

http://msdn.microsoft.com/en-us/library/ee256691.aspx – Using Cancellation tokens

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ParallelCancel
{
    class Program
    {
        static void Main()
        {
            // want to break out of a parallel.for when a condition occurs
            var cts = new CancellationTokenSource();
            // Use ParallelOptions instance to store the CancellationToken
            var po = new ParallelOptions();
            po.CancellationToken = cts.Token;

            try
            {
                // could use syntax i => {
                Parallel.For(1, 100, po, delegate(int i)
                {
                    po.CancellationToken.ThrowIfCancellationRequested();
                    Console.WriteLine(i);
                    if (i == 50)
                    {
                        cts.Cancel();
                    }
                });
            }
            catch (OperationCanceledException e)
            {
                Console.WriteLine("Cancelled");
            }
        }
    }
}

Simple example of cancellation tokens
using System;
using System.Threading;
using System.Threading.Tasks;

namespace ParallelCancel
{
    class Program
    {
        static void Main()
        {
            // want to break out of a parallel.for when a condition occurs
            var cts = new CancellationTokenSource();
            // Use ParallelOptions instance to store the CancellationToken
            var po = new ParallelOptions();
            po.CancellationToken = cts.Token;

            long counterTotal = 0;

            try
            {
                // could use syntax i => {

                // want to have a sum of counts at the end
                Parallel.For<long>(1, 10000000, po, () => 0, delegate(int i, ParallelLoopState state, long counterSubtotal)
                    {
                        po.CancellationToken.ThrowIfCancellationRequested();
                        //CConsole.WriteLine(i);
                        counterSubtotal++;
                        if (i == 50000)
                        {
                            cts.Cancel();
                        }
                        //});
                        return counterSubtotal;
                    }, (x) => Interlocked.Add(ref counterTotal, x)
                    );
            }
            catch (OperationCanceledException e)
            {
                Console.WriteLine("Cancelled");
                Console.WriteLine("Total iterations across all threads {0}", counterTotal);
            }
        }
    }
}

Cancellation tokens with a ‘global state’ variable handled well.  ie the counter is summed up at the end.

this code works well (from http://stackoverflow.com/questions/16344736/parallelfor-not-cancelling-all-threads-immediately-if-condition-met)

static void Main()
        {
            // want to break out of a Parallel.For immediately when a condition occurs
            var cts = new CancellationTokenSource();
            var po = new ParallelOptions();
            po.CancellationToken = cts.Token;

            long counterTotal = 0;

            try
            {
                // want to have a sum of counts at the end
                // using type param here to make counterSubtotal a long
                Parallel.For<long>(1, 26, po, () => 0, delegate(int i, ParallelLoopState state, long counterSubtotal)
                        {
                            Console.WriteLine(i.ToString());
                            // 1 billion
                            for (int k = 0; k < 1000000000; k++)
                            {
                                //po.CancellationToken.ThrowIfCancellationRequested();
                                if (po.CancellationToken.IsCancellationRequested)
                                {
                                    return counterSubtotal;
                                }
                                counterSubtotal++;

                                if (i == 4 && k == 400000000)
                                {
                                    Console.WriteLine("Inner Cancelled");
                                    cts.Cancel();
                                }
                            }
                            return counterSubtotal;
                        }, (x) => Interlocked.Add(ref counterTotal, x)
                    );
            }
            catch (OperationCanceledException e)
            {
                Console.WriteLine("Cancelled");
                Console.WriteLine("Total iterations across all threads {0}", String.Format("{0:n0}", counterTotal));
                Console.ReadLine();
            }
        }

and here is the coding challenge using tokens:

To optimise this, I’d break up the chunks into smaller bits.  As a speed test, 750million comparisons per second is great.

image

    internal class Program
    {
        private static void Main()
        {
            var cts = new CancellationTokenSource();
            var po = new ParallelOptions();
            po.CancellationToken = cts.Token;

            long counterTotal = 0;
            var stopwatchOverall = new Stopwatch();
            stopwatchOverall.Start();
            try
            {
                Parallel.For<long>(97, 123, po, () => 0, (i, state, counterSubtotal) =>
                    {
                        Console.WriteLine("Starting " + i);

                        // array of bytes (can be 0 to 255) eg 100, 97, 118, 101, 100, 97, 118
                        byte[] secretBytes = Encoding.UTF8.GetBytes("aavedave");
                        // same size array that we'll populate many times to compare with
                        var comparisonBytes = new byte[8];

                        comparisonBytes[0] = (byte) i;
                        for (byte j = 97; j < 123; j++)
                        {
                            comparisonBytes[1] = j;
                            //loop 3
                            for (byte k = 97; k < 123; k++)
                            {
                                comparisonBytes[2] = k;
                                //loop4
                                for (byte l = 97; l < 123; l++)
                                {
                                    comparisonBytes[3] = l;
                                    //loop 5
                                    for (byte m = 97; m < 123; m++)
                                    {
                                        comparisonBytes[4] = m;
                                        //loop6
                                        for (byte n = 97; n < 123; n++)
                                        {
                                            comparisonBytes[5] = n;
                                            //loop7
                                            for (byte o = 97; o < 123; o++)
                                            {
                                                comparisonBytes[6] = o;
                                                //loop8
                                                for (byte p = 97; p < 123; p++)
                                                {
                                                    comparisonBytes[7] = p;

                                                    if (po.CancellationToken.IsCancellationRequested)
                                                    {
                                                        Console.WriteLine("Returning " + i.ToString());
                                                        return counterSubtotal;
                                                    }

                                                    counterSubtotal++;

                                                    bool found = true;
                                                    for (int a = 0; a < 8; a++)
                                                    {
                                                        if (comparisonBytes[a] != secretBytes[a])
                                                        {
                                                            found = false;
                                                            break;
                                                        }
                                                    }

                                                    if (found)
                                                    {
                                                        var comparisonString = Encoding.UTF8.GetString(comparisonBytes);
                                                        var secretString = Encoding.UTF8.GetString(secretBytes);
                                                        Console.WriteLine("Comparison is {0} and secret is {1} after {2} pattern matches on this thread",comparisonString, secretString,String.Format("{0:n0}", counterSubtotal));
                                                        Console.WriteLine("Inner cancelled");
                                                        cts.Cancel();
                                                    }
                                                } //end loop 8
                                            } //end loop 7
                                        } // end loop 6
                                    } // end loop 5
                                } //end loop 4
                            } // end loop 3
                        } // end loop 2
                        return counterSubtotal;
                    }, (x) => Interlocked.Add(ref counterTotal, x)
                    );
            }
            catch (OperationCanceledException e)
            {
                Console.WriteLine("Total counts on all threads is {0}", String.Format("{0:n0}", counterTotal));
                stopwatchOverall.Stop();
                TimeSpan ts = stopwatchOverall.Elapsed;
                Console.WriteLine("Timespan: {0}s", ts.TotalSeconds);

                long throughput = counterTotal/(long) ts.TotalSeconds;
                Console.WriteLine("Throughput across all cores: {0}comparisons/sec", String.Format("{0:n0}", throughput));
            }

            Console.WriteLine("End of program");
        }
    }
| | # 
# Tuesday, 07 August 2012

http://www.yoda.arachsys.com/csharp/threads/ Jon Skeet

Threading: “..trying to do more than one thing at a time within a process”

Process:  eg a browser downloading on one process, and a word processor allowing you to type on another process

Josepth Albahari

http://www.albahari.com/threading/ – Joseph Albahari (24th July 2011 updated).  C#5 book now available (.NET4.5 still in RC)

class Program
    {
        static void Main(string[] args)
        {
            Thread t = new Thread(WriteY);          // Kick off a new thread
            t.Start();                               // running WriteY()

            // Simultaneously, do something on the main thread.
            for (int i = 0; i < 1000; i++) Console.Write("x");
        }
        
        static void WriteY()
        {
            for (int i = 0; i < 1000; i++) Console.Write("y");
        }
    }

image
2 Threads writing to the console

Local Variables Separate

static void Main(string[] args)
        {
            new Thread(Go).Start();
            Go();
        }
        
        static void Go()
        {
            //CLR assigns thread its own memory stack so that local variables are kept separate
            for (int i = 0; i < 5; i++) Console.Write("?");
        }

10 ?’s are printed.

Same Object Instance share Data

class ThreadTest
    {
        bool done;

        static void Main()
        {
            ThreadTest tt = new ThreadTest();   // Create a common instance
            new Thread(tt.Go).Start();
            tt.Go();
        }

        // Note that Go is now an instance method
        void Go()
        {
            if (!done) { done = true; Console.WriteLine("Done"); }
        }
    }

Threads share data if they have a common reference to the same object instance.

Done is only printed once.

Static Fields Shared

class ThreadTest
    {
        static bool done;    // Static fields are shared between all threads

        static void Main()
        {
            new Thread(Go).Start();
            Go();
        }

        static void Go()
        {
            if (!done) { done = true; Console.WriteLine("Done"); }
        }
    }

Thread non Safety

class ThreadTest
    {
        static bool done;    // Static fields are shared between all threads

        static void Main()
        {
            new Thread(Go).Start();
            Go();
        }

        static void Go()
        {
            //Swapped the order of statements - usually get Done twice now
            //ie This is not thread safe
            if (!done) { Console.WriteLine("Done"); done = true; }
        }
    }

Usually displays Done twice

Locking

class ThreadTest
    {
        static bool done;    // Static fields are shared between all threads
        static readonly object locker = new object();

        static void Main()
        {
            new Thread(Go).Start();
            Go();
        }

        static void Go()
        {
            //When two threads simultaneously contend a lock (in this case, locker), one thread waits, or blocks, until the lock becomes available
            lock (locker)
            {
                if (!done)
                {
                    Console.WriteLine("Done");
                    done = true;
                }
            }
        }
    }
Display Done once!

Parallel Programming

eg PLINQ makes it easy.

image

static void Main()
        {
            // Calculate prime numbers using a simple (unoptimized) algorithm.
            //
            IEnumerable<int> numbers = Enumerable.Range(3, 100000000 - 3);

            var parallelQuery =
              from n in numbers.AsParallel()
              where Enumerable.Range(2, (int)Math.Sqrt(n)).All(i => n % i > 0)
              select n;

            int[] primes = parallelQuery.ToArray();
            //foreach (var prime in primes)
            //{
            //    Console.WriteLine(prime);
            //}
        }

Spell Checker in Parallel with PLINQ

struct IndexedWord { public string Word; public int Index; }

        static void Main()
        {
            if (!File.Exists("WordLookup.txt"))    // Contains about 150,000 words
                new WebClient().DownloadFile("http://www.albahari.com/ispell/allwords.txt", "WordLookup.txt");

            var wordLookup = new HashSet<string>(File.ReadAllLines("WordLookup.txt"),StringComparer.InvariantCultureIgnoreCase);

            var random = new Random();
            string[] wordList = wordLookup.ToArray();

            //Test document of a 100 million different words
            string[] wordsToTest = Enumerable.Range(0, 100000000)
              .Select(i => wordList[random.Next(0, wordList.Length)])
              .ToArray();

            wordsToTest[12345] = "woozsh";     // Introduce a couple
            wordsToTest[23456] = "wubsie";     // of spelling mistakes.

            Stopwatch s = new Stopwatch();
            s.Start();
            var query = wordsToTest
                      //.AsParallel()
                      .Select((word, index) => new IndexedWord { Word = word, Index = index })
                      .Where(iword => !wordLookup.Contains(iword.Word))
                      .OrderBy(iword => iword.Index);
           
            foreach (var indexedWord in query)
            {
                Console.WriteLine(indexedWord.Word);
            }
            s.Stop();
            TimeSpan t = s.Elapsed;
            Console.WriteLine(t.Seconds);

        }

11s for Parallel (8 cores)
52s non Parallel (1 core)

SpellChecker with Parallel.ForEach

struct IndexedWord { public string Word; public int Index; }

        static void Main()
        {
            if (!File.Exists("WordLookup.txt"))    // Contains about 150,000 words
                new WebClient().DownloadFile("http://www.albahari.com/ispell/allwords.txt", "WordLookup.txt");

            var wordLookup = new HashSet<string>(File.ReadAllLines("WordLookup.txt"),StringComparer.InvariantCultureIgnoreCase);

            var random = new Random();
            string[] wordList = wordLookup.ToArray();

            //Test document of a 100 million different words..
            string[] wordsToTest = Enumerable.Range(0, 100000000)
              .Select(i => wordList[random.Next(0, wordList.Length)])
              .ToArray();

            wordsToTest[12345] = "woozsh";     // Introduce a couple
            wordsToTest[23456] = "wubsie";     // of spelling mistakes.

            Stopwatch s = new Stopwatch();
            s.Start();

            var misspellings = new ConcurrentBag<Tuple<int, string>>();

            Parallel.ForEach(wordsToTest, (word, state, i) =>
            {
                if (!wordLookup.Contains(word))
                    misspellings.Add(Tuple.Create((int)i, word));
            });

            foreach (var tu in misspellings)
            {
                Console.WriteLine("{0}, {1}",tu.Item1,tu.Item2);
            }
            s.Stop();
            TimeSpan t = s.Elapsed;
            Console.WriteLine(t.Seconds);
        }

10s for Parallel. Indexed ForEach is more efficient than Select.

| | #