Click here to Skip to main content
15,895,740 members
Articles / Programming Languages / C#

Code optimization tutorial - Part 2

Rate me:
Please Sign up or sign in to vote.
4.84/5 (15 votes)
22 Jun 2012CPOL4 min read 27K   389   39  
Beginner optimization tutorial.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;

namespace program_to_optimize
{
    class Program
    {
        private class ThreadedSolver
        {
            public int MaxCycleCount;
            private const int FirstNumber = 1;
            private const int SecondNumber = 1000000;

            //queues used to store the numbers to be processed
            private Queue<int>[] workQueue;
            //threads that will process the numbers
            private Thread[] workerThreads;
            //flag that controlls the lifetime of the threads
            private bool bRunning;

            //public constructor
            public ThreadedSolver()
            {
                //initialize work queue array
                workQueue = new Queue<int>[System.Environment.ProcessorCount];

                ////initialize thread array
                workerThreads = new Thread[System.Environment.ProcessorCount];

                //create a thread and a work queue for each processor core
                for (int i = 0; i < System.Environment.ProcessorCount; ++i)
                {
                    workerThreads[i] = new Thread(new ParameterizedThreadStart(this.ThreadProc));
                    workQueue[i] = new Queue<int>();
                }

                MaxCycleCount = 0;
                bRunning = true;
            }

            //thread procedure
            public void ThreadProc(object obj)
            {
                int iMaxCycleCount = 1;

                //work queue index, passed as a parameter to the thread
                int iQueueIndex = (int)obj;

                //while program is running
                while (bRunning)
                {
                    //if the work queue of this thread is not empty
                    if (workQueue[iQueueIndex].Count != 0)
                    {
                        long iNumberToTest = 1;
                        int iCurrentCycleCount = 1;

                        //lock the work queue, only to retrieve a number to process
                        lock (workQueue[iQueueIndex])
                        {
                            //test again if the queue has entries
                            if (workQueue[iQueueIndex].Count > 0)
                            {
                                //get first number in queue
                                iNumberToTest = workQueue[iQueueIndex].Dequeue();
                            }
                        }

                        //process number
                        for (iCurrentCycleCount = 1; iNumberToTest != 1; ++iCurrentCycleCount)
                        {
                            if ((iNumberToTest & 0x1) == 0x01)
                            {
                                iNumberToTest += (iNumberToTest >> 1) + 1;
                                ++iCurrentCycleCount;
                            }
                            else
                                iNumberToTest >>= 1;
                        }

                        if (iMaxCycleCount < iCurrentCycleCount)
                        {
                            iMaxCycleCount = iCurrentCycleCount;
                        }
                    }
                    else
                    {
                        //if no entries in the queue, give up remaning processing time
                        Thread.Sleep(0);
                    }
                }

                //when thread is done, lock to update the maximum cycle count
                lock (this)
                {
                    if (MaxCycleCount < iMaxCycleCount)
                    {
                        MaxCycleCount = iMaxCycleCount;
                    }
                }
            }

            //method used to solve the problem
            public void Solve()
            {
                //start the threads
                for (int i = 0; i < System.Environment.ProcessorCount; i++)
                {
                    workerThreads[i].Start(i);
                }

                //load numbers into the work queues, 250 numbers at a time
                int index = FirstNumber;
                while (index <= SecondNumber)
                {
                    for (int j = 0; j < System.Environment.ProcessorCount; j++)
                    {
                        lock (workQueue[j])
                        {
                            int upperLimit = index + 250;
                            for (int k = index; k < upperLimit; ++k)
                            {
                                workQueue[j].Enqueue(k);
                            }
                        }
                        index += 250;
                    }
                }

                //wait until all queues are empty
                bool bWait = true;
                while (bWait)
                {
                    bWait = false;
                    for (int i = 0; i < workQueue.Length; ++i)
                    {
                        if (workQueue[i].Count != 0)
                        {
                            bWait = true;
                        }
                    }

                    Thread.Sleep(0);
                }

                //signal application is shuting down
                bRunning = false;

                //wait for worker threads to finish
                for (int i = 0; i < System.Environment.ProcessorCount; ++i)
                {
                    workerThreads[i].Join();
                }
            }
        }



        static void Main(string[] args)
        {
            //stopwatch used to measure the time it takes to solve the problem
            Stopwatch tmrExecutionTime = new Stopwatch();
            //threaded solver
            ThreadedSolver ts = new ThreadedSolver();

            //solve the problem
            tmrExecutionTime.Start();
            ts.Solve();
            tmrExecutionTime.Stop();

            //write the result and the time
            Console.WriteLine("{0} {1}", ts.MaxCycleCount, tmrExecutionTime.ElapsedMilliseconds);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Spain Spain
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions