views:

76

answers:

5

I'm working on a game sim and want to speed up the match simulation bit. On a given date there may be 50+ matches that need simulating. Currently I loop through each and tell them to simulate themselves, but this can take forever. I was hoping

1) Overlay a 'busy' screen

2) Launch a thread for each

3) When the last thread exits, remove the overlay.

Now I can do 1 & 2, but I cannot figure out how to tell when the last thread is finished, because the last thread I detach may not be the last thread finished. What's the best way to do that?

Also, usually threads are used so that work can be done in the background while the user does other stuff, I'm using it slightly different. My app is a core-data app and I want to avoid the user touching the store in other ways while i'm simulating the matches. So I want single-threading most of the time, but then multithreading for this situation because of how long the sim engine takes. If someone has other ideas for this approach I'm open.

Rob

+1  A: 

You're on a single core, so threading probably won't help much, and the overhead may even slow things down.

The first thing to do is use Instruments to profile your code and see what can be sped up. Once you've done that you can look at some specific optimizations for the bottle necks.

One simple approach (if you can use GCD) is dispatch_apply(), which'll let you loop over your matches, automatically thread them in the best manner for your hardware, and doesn't return until all are complete.

Graham Perks
Thanks, good point, let me try.
rob5408
Threading can help if the processing is IO related
vodkhang
A: 

Most straightforward solution would be to have all your threads 'performSelectorOnMainThread' to a particular method that decrements a counter, before they exit. And let the method remove the overlay screen when the counter it decremented reaches zero.

Simulating all the matches concurrently may not necessarily improve performance though.

Şafak Gezer
Thanks, Let me give this a shot.
rob5408
A: 

You may get the solution for your specific question from @drowntoge, but generally, I want to give you advice about multithreading:

1/ It is not always speed up your program like Graham said. Your iPhone only has single core.

2/ If your program has some big IO, database or networking process that takes time, then you may consider multithreading because now data processing does not take all the time, it needs to wait for loading data. In this case, multithreading will significantly boost up your performance. But you still need to be careful because thread switching has overhead.

Maybe you only need 1 thread for IO processing and then has a cache layer to share the images/data. Then, you only need the main thread to loop and do simulation

3/ If you want 50 simulation seems to happen at the same time for user to watch, multithreading is also required:)

vodkhang
+2  A: 

Likely you want to use NSOperation and NOT 50 threads - 50 threads is not healthy on an iPhone, and NSOperations are easier to boot. It may be that you are killing performance (it would be my guess) by trying to run 50 at once. NSOperation is designed for exactly this problem. Plus its easy to code.

My only problem with NSOperation is that they don't have a standard way to tell the caller that they are done.

You could periodically poll the NSOperationQueue - when its count is 0 there are none left. You could also make each operation increment some counter - when the count is 50 you are done. Or each operation could post a notification using performSelectorOnMainThread on the main thread that its done.

You should see a boost in performance with even a single core - there are lots of times that the main thread is blocked waiting for user input/graphics drawing/etc. Plus multicore phones and iPads will likely be out within a year (total guess - but they are coming).

Also make sure you look at the operation with Instruments. It may be that you can speed the calculations up be a factor of 2 or even 10x!

Tom Andersen
You can use KVO to observe the `operationCount` of the operation queue; no polling needed. Just note that the operation will not come in on the main thread, so you'll probably want to do a main-thread perform from your observer method to your actual extract-the-new-operation-count-from-the-change-dictionary-and-check-it method.
Peter Hosey
You can also observe the isFinished property of each NSOperation
sbooth
A: 

If you use threading, you won't know in what order the CPU is doing your tasks, and you could potentially be consuming a lot of thread scheduling resources. Better to use an NSOperationQueue and signal completion of each task using performSelectorOnMainThread. Decrementing a counter has already been mentioned, which may be useful for displaying a progress bar. But you could also maintain an array of 50 busy flags and clear them on completion, which might help debugging whether any particular task is slow or stuck if you mark completion with a time stamp.

hotpaw2