Archive for September, 2009

Simple Multi-threading of a Workload

Monday, September 28th, 2009

Recently I was faced with a prescreening programming question that involved a straightforward problem with one caveat that made it significantly more difficult. I had to compute some 800 trillion+ solutions in as close to 20ms as possible. It only took me a couple days to write an algorithm that could theoretically solve the answer… but it would have taken weeks to run. Eventually I figured out the shortcut to get my run time to less than a second, but carving away each tenth of a second thereafter took some creativity. One obvious way of making up some time would be to make use of the near ubiquity of multicore processors these days. Fortunately the workload was simple enough to split up. I had a large list of objects and I had to do “something” to each element. By splitting the list and farming out the workload to the number of processors in the system I carved off a nice 40% time savings on a segment of my project. Again we will be working in C#.

Jump to final code

Generally the code flows like this:

  1. Add references
  2. Find the number of processors on the current system
  3. Split your workload into pieces
  4. Create a thread for each piece
  5. Wait for the threads to complete before continuing main program execution.

First off add a reference to the System.Threading namespace

using System.Threading;

Next find the number of processors

int numProcs = System.Environment.ProcessorCount;

For my workload I am splitting a list into equal parts. I have to ensure that when I split the list I don’t repeat any of the elements, nor do I leave any elements behind if the list isn’t evenly divisible by the number of processors in the system. It would also be more efficient to check the length of the list and see if it is worthwhile to multithread it. If you only have one list item then multiple threads aren’t going to do you much good.

List<N> myList = new List<N>();
int iRange = list.Count / numProcs;       //# of elements in the list to get
int iStart, iEnd;                        //portion of list that we will get

//for each processor get a piece of the workload
for (int i = 0; i < iProcs; i++) {
     //set start and end values to get
     iStart = iRange * i;
     if (i == iProcs - 1)  //for last processor use the rest of the list
          iEnd = buildRows.Count - iStart;
     else
          iEnd = iRange;

     //Get the subset of list items
     List<N> listSubset = myList.GetRange(iStart, iEnd);
}

Now for the multithreaded part. You create a new thread by creating a new Thread object and specifying a ThreadStart. A ThreadStart represents a method in your program and acts as a delegate. A delegate is an object that refers to a method and can call a method. In this example I want to execute a method on each item in my list. So I create a delegate that points to this method. There are multiple ways to set this up, but the most straightforward way I found is in this example code.

Thread myThread = new Thread(
     delegate() {
          foreach (N item in listSubset) { item.DoSomething();  }
     }
);

You call thread.Start() to begin executing the delegate. However, your main application thread will continue running simultaneously. If you want to wait for all your worker threads to finish before continuing with the main thread you must call thread.Join();. This tells the current thread to wait for the specified thread to finish. Let’s tie everything together now.

private void MultiThreadWorkLoad(List<N> myList) {
    int numProcs = System.Environment.ProcessorCount; //number of processors
    int iRange = buildRows.Count / iProcs;   //# of elements in the list to get
    int iStart, iEnd;       //portion of list that we will get
    Thread[] threads = new Thread[iProcs];      //array of threads

     //for each processor get a piece of the workload
     for (int i = 0; i < numProcs; i++) {
          //range of values to get
          iStart = iRange * i;
          if (i == numProcs - 1)  //for last processor use the rest of the list
               iEnd = buildRows.Count - iStart;
          else
               iEnd = iRange;

          List<N> listSubset = buildRows.GetRange(iStart, iEnd);
          Thread myThread = new Thread(
              delegate() {
                      foreach (N item in listSubset) { item.DoSomething();  }
              }
          );
          myThread.Start();
          threads[i] = myThread;
    }

    //all threads should complete before we continue with main program execution
    foreach (Thread thread in threads) { thread.Join(); }
}

My History With Computer Hardware

Tuesday, September 22nd, 2009

One aspect of computing I have loved for a long time is hardware. I have years of experience building and troubleshooting custom built systems. It all started in my senior year of high school when one of my best buds, Doug, suggested I build a computer instead of buying a prebuilt system. At the time you could save a significant chunk of change by going DIY. Since I am a DIY’er and also cheap I was all for it. And so I ended up with an AMD K6-2 @ 300mhz, 64mb ram, and a 4mb matrox video card all on a VIA motherboard.

Unfortunately the system was finicky worked intermittently cantankerous the spawn of the devil (sorry Doug). The ultimate downside of having a custom built computer is that you have to support it yourself, and when things go wrong you have to fix it yourself. Now the computer’s problems weren’t Doug’s fault. This is back in the day when there were not many decent hardware review sites on the web and also the days of a company called VIA who produced chipsets that were *ahem* garbage. However the computer’s faults became its greatest asset. Through countless hours of troubleshooting I became intimately familiar with OS installations, BIOS settings, overclocking, formatting and every other little thing you could imagine. Although I hated that system it has made me who I am today. An avid overclocker who understands each aspect of system hardware and who loves a challenge in fixing a computer.

I own a t-shirt that I received as a present which reads “No, I will NOT fix your computer.” I love the shirt, but I have never worn it because I find the statement too arrogant to be parading it around town. I enjoy helping people even though it can be a gigantic time suck for me. I’ve repaired laptops by resoldering chips on, repaired laptop screens, soldered on new capacitors to a motherboard, removed spyware that had gone borg on the host computer and stayed up until dawn on more occasions than I care to remember rescuing files from crashed hard drives.

Over the next few days I will share some of my cool custom built computers I have tackled over the years. Stay tuned to check ‘em out!