Just for fun I created a mandelbrot program. I'm now trying to make it multithreaded by splitting the image into two left/right parts to be handled by two threads. However, the application crashes as soon as it's launched (although based on my console output, the first thread continues after the crash but the second thread never starts) and I'm unsure what to do.
The crash is at the line this.output[x][y] = this.calculate_pixel_rgb(x, y); and says I'm missing an object reference, which I don't understand because it works for the first thread.
public void compute_all()
{
this.setcolors(); this.zoom_multiplier = (4 / this.zoom / this.resolution);
Thread thread1 = new Thread(new ParameterizedThreadStart(computation_thread)); thread1.Start(new double[] { 0, 0.5 });
Thread thread2 = new Thread(new ParameterizedThreadStart(computation_thread)); thread2.Start(new double[] { 0.5, 1 });
thread1.Join(); thread2.Join();
}
public void computation_thread(object threadinfo)
{
double[] parameters = (double[])threadinfo;
this.output = new int[this.resolution][][];
for (int x = (int)(this.resolution * parameters[0]); x < (int)(this.resolution * parameters[1]); x++)
{
this.output[x] = new int[this.resolution][];
for (int y = 0; y < this.resolution; y++)
{
this.output[x][y] = this.calculate_pixel_rgb(x, y);
this.pixels_completed++;
}
}
}
Your two threads are manipulating the same output buffer, overwriting each other. Don't share memory between threads if you can possibly avoid it; all it causes is grief.
If the point of this exercise is to learn how to manipulate raw threads then take a step back and study why sharing memory across two threads is a bad idea.
If the point of this exercise is to parallelize the computation of a fractal then forget about manipulating raw threads. You will do much better to learn how to use the Task Parallel Library.
Threads are logically workers, and who wants to manage a bunch of workers? The TPL encourages you to see parallization as the manipulation of tasks that can be done in parallel. Let the TPL take care of figuring out how many workers to assign to your tasks.
The problem in your code is initializing this.output multiple times (once for each thread).
Both of your threads use the same this and when the first thread initialized this.output's columns, the second thread re-initializes it, and the first thread loses its allocated memory.
So, this.output[x] will not be existed in the first thread anymore (missing an object reference exception).
This also explains why your code runs flawlessly with just one thread.
The easy solution is to initialize the whole array at the very beginning.
Your logic seems fishy.
But if you believe it is correct and resetting this.output data is necessary in each thread, then do the following:
Make temporary array
Change [x][y] to [x,y]
Change [][] to [,]
Apply lock before setting to this.output
Related
I am wondering a bit at the moment. I was just reading a bit about Threads and landed there: Task vs Thread differences [duplicate] here on stackoverflow from Jacek (sorry cant create a link because i can only make 2 with reputation<10)
and the first Comment from MoonKnight led me there: albahari.com/threading
i have taken the code and changed it a little to make it better read able what is happening. Here comes my changed code:
static void Main()
{
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 < 10; i++) { System.Threading.Thread.Sleep(1); Console.Write(i); };
Console.ReadLine();
}
static void WriteY()
{
for (int y = 0; y < 10; y++) { System.Threading.Thread.Sleep(1); Console.Write(y); };
Console.ReadLine();
}
what I expected to happen (and what happens most of the time) was this:
Good Thread:
but here is the thing I am wondering about(its absolutely random and promised the same code):
miracle thread:
my questions:
1.How can this happen that there are different numbers the threads should always run at the same time shouldnt they?
2.all this gets more crazy the lower the sleep time gets so if you remove it completely it fells absolutely random
When you execute the first loop on the main thread and start WriteY() on a separate thread, there is absolutely no way to predict the sequence in which events in one thread will happen relative to events in the other thread.
I've written a few tests to demonstrate this. Here's one. And here's another.
What characterizes both of these examples is that very often they will run in the "expected" sequence, but once in a while they won't.
That tells us a few things about multithreaded operations:
Concurrencty or parallel execution is beneficial when we want to distribute work across threads, but not when events must occur in a predictable sequence.
It requires extra caution because it if we do it wrong it might seem to work anyway. And then once in a while it won't work. Those occasions when it doesn't work will be extremely difficult to debug, one reason being that you won't be able to get the behavior to repeat when you want to.
I've got an I/O intensive operation.
I only want a MAX of 5 threads ever running at one time.
I've got 8000 tasks to queue and complete.
Each task takes approximately 15-20seconds to execute.
I've looked around at ThreadPool, but
ThreadPool.SetMaxThreads(5, 0);
List<task> tasks = GetTasks();
int toProcess = tasks.Count;
ManualResetEvent resetEvent = new ManualResetEvent(false);
for (int i = 0; i < tasks.Count; i++)
{
ReportGenerator worker = new ReportGenerator(tasks[i].Code, id);
ThreadPool.QueueUserWorkItem(x =>
{
worker.Go();
if (Interlocked.Decrement(ref toProcess) == 0)
resetEvent.Set();
});
}
resetEvent.WaitOne();
I cannot figure out why... my code is executing more than 5 threads at one time. I've tried to setmaxthreads, setminthreads, but it keeps executing more than 5 threads.
What is happening? What am I missing? Should I be doing this in another way?
Thanks
There is a limitation in SetMaxThreads in that you can never set it lower than the number of processors on the system. If you have 8 processors, setting it to 5 is the same as not calling the function at all.
Task Parallel Library can help you:
List<task> tasks = GetTasks();
Parallel.ForEach(tasks, new ParallelOptions { MaxDegreeOfParallelism = 5 },
task => {ReportGenerator worker = new ReportGenerator(task.Code, id);
worker.Go();});
What does MaxDegreeOfParallelism do?
I think there's a different and better way to approach this. (Pardon me if I accidentally Java-ize some of the syntax)
The main thread here has a lists of things to do in "Tasks" -- instead of creating threads for each task, which is really not efficient when you have so many items, create the desired number of threads and then have them request tasks from the list as needed.
The first thing to do is add a variable to the class this code comes from, for use as a pointer into the list. We'll also add one for the maximum desired thread count.
// New variable in your class definition
private int taskStackPointer;
private final static int MAX_THREADS = 5;
Create a method that returns the next task in the list and increments the stack pointer. Then create a new interface for this:
// Make sure that only one thread has access at a time
[MethodImpl(MethodImplOptions.Synchronized)]
public task getNextTask()
{
if( taskStackPointer < tasks.Count )
return tasks[taskStackPointer++];
else
return null;
}
Alternately, you could return tasks[taskStackPointer++].code, if there's a value you can designate as meaning "end of list". Probably easier to do it this way, however.
The interface:
public interface TaskDispatcher
{
[MethodImpl(MethodImplOptions.Synchronized)] public task getNextTask();
}
Within the ReportGenerator class, change the constructor to accept the dispatcher object:
public ReportGenerator( TaskDispatcher td, int idCode )
{
...
}
You'll also need to alter the ReportGenerator class so that the processing has an outer loop that starts off by calling td.getNextTask() to request a new task, and which exits the loop when it gets back a NULL.
Finally, alter the thread creation code to something like this: (this is just to give you an idea)
taskStackPointer = 0;
for (int i = 0; i < MAX_THREADS; i++)
{
ReportGenerator worker = new ReportGenerator(this,id);
worker.Go();
}
That way you create the desired number of threads and keep them all working at max capacity.
(I'm not sure I got the usage of "[MethodImpl(MethodImplOptions.Synchronized)]" exactly right... I am more used to Java than C#)
Your tasks list will have 8k items in it because you told the code to put them there:
List<task> tasks = GetTasks();
That said, this number has nothing to do with how many threads are being used in the sense that the debugger is always going to show how many items you added to the list.
There are various ways to determine how many threads are in use. Perhaps one of the simplest is to break into the application with the debugger and take a look at the threads window. Not only will you get a count, but you'll see what each thread is doing (or not) which leads me to...
There is significant discussion to be had about what your tasks are doing and how you arrived at a number to 'throttle' the thread pool. In most use cases, the thread pool is going to do the right thing.
Now to answer your specific question...
To explicitly control the number of concurrent tasks, consider a trivial implementation that would involve changing your task collection from a List to BlockingCollection (that will internally use a ConcurrentQueue) and the following code to 'consume' the work:
var parallelOptions = new ParallelOptions
{
MaxDegreeOfParallelism = 5
};
Parallel.ForEach(collection.GetConsumingEnumerable(), options, x =>
{
// Do work here...
});
Change MaxDegreeOfParallelism to whatever concurrent value you have determined is appropriate for the work you are doing.
The following might be of interest to you:
Parallel.ForEach Method
BlockingCollection
Chris
Its works for me. This way you can't use a number of workerthreads smaller than "minworkerThreads". The problem is if you need five "workerthreads" maximum and the "minworkerThreads" is six doesn't work.
{
ThreadPool.GetMinThreads(out minworkerThreads,out minportThreads);
ThreadPool.SetMaxThreads(minworkerThreads, minportThreads);
}
MSDN
Remarks
You cannot set the maximum number of worker threads or I/O completion threads to a number smaller than the number of processors on the computer. To determine how many processors are present, retrieve the value of the Environment.ProcessorCount property. In addition, you cannot set the maximum number of worker threads or I/O completion threads to a number smaller than the corresponding minimum number of worker threads or I/O completion threads. To determine the minimum thread pool size, call the GetMinThreads method.
If the common language runtime is hosted, for example by Internet Information Services (IIS) or SQL Server, the host can limit or prevent changes to the thread pool size.
Use caution when changing the maximum number of threads in the thread pool. While your code might benefit, the changes might have an adverse effect on code libraries you use.
Setting the thread pool size too large can cause performance problems. If too many threads are executing at the same time, the task switching overhead becomes a significant factor.
I'm studying C# right now and currently learning threading.
Here is a simple example to adding 1 to a variable multiple times within different threads.
The book suggested I can use Interlocked.increment(ref number) to replace the number += 1 within the AddOne method, therefore the value will be locked until it's updated within the thread. So the output will be 1000, 2000, ..... 10000 as expected. But My output is still 999, 1999, 2999, ...... 9999.
Only after I uncomment the Thread.Sleep(1000) line will the output be correct but even without the Interlocked been used.
Can anyone explain what's happening here?
static void Main(string[] args)
{
myNum n = new myNum();
for (int i = 0;i<10; Interlocked.Increment(ref i))
{
for(int a =1;a<=1000; Interlocked.Increment(ref a))
{
Thread t = new Thread( new ThreadStart( n.AddOne));
t.Start();
}
//Thread.Sleep(1000);
Console.WriteLine(n.number);
}
}
class myNum
{
public int number = 0;
public void AddOne()
{
//number += 1;
Interlocked.Increment(ref number);
}
}
You are printing out the value before all of the threads have finished executing. You need to join all of the threads before printing.
for(int a = 0; a < 1000; a++)
{
t[a].Join();
}
You'll need to store the threads in an array or list. Also, you don't need the interlocked instruction in any of the for loops. They all run in only one thread (the main thread). Only the code in AddOne runs in multiple threads and hence needs to by synchronized.
It a bit strange for me what you trying to achieve with this code. You are using Interlocked.Increment everywhere without explicit needs for it.
Interlocked.Increment required for access to values which can be accessed from different threads. In your code it is only number, so you don't require it for i and a, just use as usually i++ and a++
The problem you are asking for is that you just don't wait for all threads you started are completed its job. Take a look to Thread.Join() method. You have to wait while all of threads you are started completes its work.
In this simple test you are done with Thread.Sleep(1000); you do similar wait but its not correct to assume that all threads are complete in 1000 ms, so just use Thread.Join() for that.
If you modify your AddOne() method so it starts to executes longer (e.g. add Thread.Sleep(1000) to it) you'll notice that Thread.Sleep(1000); doesn't help any more.
I'll suggest to read more about ThreadPool vs Threads. Also take a look to Patterns for Parallel Programming: Understanding and Applying Parallel Patterns with the .NET Framework 4
Here is a piece of code in C# which applies an operation over each row of a matrix of doubles (suppose 200x200).
For (int i = 0; i < 200; i++)
{
result = process(row[i]);
DoSomething(result);
}
Process is a static method and I have a Corei5 CPU and Windows XP and I'm using .Net Framework 3.5. To gain performance, I tried to process each row using a separate thread (using Asynchronous delegates). So I rewrote the code as follows:
List<Func<double[], double>> myMethodList = new List<Func<double[], double>>();
List<IAsyncResult> myCookieList = new List<IAsyncResult>();
for (int i = 0; i < 200; i++)
{
Func<double[], double> myMethod = process;
IAsyncResult myCookie = myMethod.BeginInvoke(row[i], null, null);
myMethodList.Add(myMethod);
myCookieList.Add(myCookie);
}
for (int j = 0; j < 200; j++)
{
result = myMethodList[j].EndInvoke(myCookieList[j]);
DoSomething(result);
}
This code is being called for 1000 matrixes in one run. When I tested, surprisingly I didn't get any performance improvement! So this brought up this question for me that in what cases the multi-threading will be of benefit for performance enhancement and also is my code logical?
At first glance, your code looks OK. Maybe the CPU isn't the bottleneck.
Can you confirm that process() and DoSomething() are independent and don't do any I/O or locking for shared resources?
The point here is that you'll have to start measuring.
And of course Fx4 with the TPL makes this kind of thing easier to write and ususally more efficient.
You could achieve more parallelism (in the result processing, specifically) by calling BeginInvoke with an AsyncCallback - this will do the result processing in a ThreadPool thread, instead of inline as you have it currently.
See the last section of the async programming docs here.
Before you do anything to modify the code, you should profile it to find out where the program is spending its time.
Your code is going a little overboard. Look at the loops; for each of 200 iterations, you are creating a new thread to make an asynchronous call. That will result in your process having 201 active threads. There is a law of diminishing returns; at about double the number of threads as the number of "execution units" that the processor has (the number of CPUs, times the number of cores on each CPU, X2 if the cores can be hyper-threaded), your computer will start spending more time scheduling threads than it spends running them. The state-of-the-art servers have 4 quad-core HT CPUs, for about 32 EUs. 200 actively executing threads will make this server break down and cry.
If the order of processing doesn't matter, I would implement a MergeSort-like algorithm; break the array in half, process the left hand, process the right hand. Each "left hand" can be processed by a new thread, but process the "right hand" in the current thread. Then, implement some thread-safe means to limit the thread count to about 1.25 times the number of "execution units"; If the limit has been reached, continue processing linearly without creating a new thread.
It looks like you aren't gaining any performance because of the way you are handling the EndInvoke method call. Since you are calling "process" using BeginInvoke, those function calls return immediately so the first loop probably finishes in no time at all. However, EndInvoke blocks until the call for which it is being called is finished processing, which you are still using sequentially. As Steve said, you should use an AsyncCallback so that each completion event is handled on it's own thread.
you are not seeing much gain because you are not parallelizing the code, yes, you are doing async but that just means that your loop does not wait to calculate to go to the next step. use Parallel.For instead of for loop and see if you see any gain on your multi-core box...
If you are going to use async delegates, this would be the way to do it to enure the callbacks happen on a Thread pool thread;
internal static void Do()
{
AsyncCallback cb = Complete;
List<double[]> row = CreateList();
for (int i = 0; i < 200; i++)
{
Func<double[], double> myMethod = Process;
myMethod.BeginInvoke(row[i], cb, null);
}
}
static double Process (double[] vals)
{
// your implementation
return randy.NextDouble();
}
static void Complete(IAsyncResult token)
{
Func<double[], double> callBack = (Func<double[], double>)((AsyncResult)token).AsyncDelegate;
double res = callBack.EndInvoke(token);
Console.WriteLine("complete res {0}", res);
DoSomething(res);
}
I am trying to use ThreadPool.RegisterWaitForSingleObject to add a timer to a set of threads. I create 9 threads and am trying to give each of them an equal chance of operation as at the moment there seems to be a little starvation going on if I just add them to the thread pool. I am also trying to implement a manual reset event as I want all 9 threads to exit before continuing.
What is the best way to ensure that each thread in the threadpool gets an equal chance at running as the function that I am calling has a loop and it seems that each thread (or whichever one runs first) gets stuck in it and the others don't get a chance to run.
resetEvents = new ManualResetEvent[table_seats];
//Spawn 9 threads
for (int i = 0; i < table_seats; i++)
{
resetEvents[i] = new ManualResetEvent(false);
//AutoResetEvent ev = new AutoResetEvent(false);
RegisteredWaitHandle handle = ThreadPool.RegisterWaitForSingleObject(autoEvent, ObserveSeat, (object)i, 100, false);
}
//wait for threads to exit
WaitHandle.WaitAll(resetEvents);
However, it doesn't matter if I use resetEvents[] or ev neither seem to work properly. Am I able to implement this or am I (probably) misunderstanding how they should work.
Thanks, R.
I would not use the RegisterWaitForSingleObject for this purpose. The patterns I am going to describe here require the Reactive Extensions download since you are using .NET v3.5.
First, to wait for all work items from the ThreadPool to complete use the CountdownEvent class. This is a lot more elegant and scalable than using multiple ManualResetEvent instances. Plus, the WaitHandle.WaitAll method is limited to 64 handles.
var finished = new CountdownEvent(1);
for (int i = 0; i < table_seats; i++)
{
finished.AddCount();
ThreadPool.QueueUserWorkItem(ObserveSeat);
(state) =>
{
try
{
ObserveSeat(state);
}
finally
{
finished.Signal();
}
}, i);
}
finished.Signal();
finished.Wait();
Second, you could try calling Thread.Sleep(0) after several iterations of the loop to force a context switch so that the current thread yields to another. If you want a considerably more complex coordination strategy then use the Barrier class. Add another parameter to your ObserveSeat function which accepts this synchronization mechanism. You could supply it by capturing it in the lambda expression in the code above.
public void ObserveSeat(object state, Barrier barrier)
{
barrier.AddParticipant();
try
{
for (int i = 0; i < NUM_ITERATIONS; i++)
{
if (i % AMOUNT == 0)
{
// Let the other threads know we are done with this phase and wait
// for them to catch up.
barrier.SignalAndWait();
}
// Perform your work here.
}
}
finally
{
barrier.RemoveParticipant();
}
}
Note that although this approach would certainly prevent the starvation issue it might limit the throughput of the threads. Calling SignalAndWait too much might cause a lot of unnecessary context switching, but calling it too little might cause a lot of unnecessary waiting. You would probably have to tune AMOUNT to get the optimal balance of throughput and starvation. I suspect there might be a simple way to do the tuning dynamically.