|
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.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.