janusfidel
janusfidel

Reputation: 8106

fastest way to execute multiple methods all at the same time

I have 4 methods, each method takes a second or two before the method returns, these methods return UIImage, I need these images to display the fastest way I can.

-(NSMutableArray*)prepareImages{
  UIImage *imageToModifyUsingUIImageCategory;

  NSMutableArray *imageArray = [[NSMutableArray alloc]initWithObjects:
  [imageToModifyUsingUIImageCategory doSomethingAndReturn1],
  [imageToModifyUsingUIImageCategory doSomethingAndReturn2],
  [imageToModifyUsingUIImageCategory doSomethingAndReturn3],
  [imageToModifyUsingUIImageCategory doSomethingAndReturn4],nil];    
  return imageArray;
}

at the end of the method above, I will have 4 images from that array. each "doSomethingAndReturn" method takes a second or two, means my prepareImages method will finish execution approximately 5 seconds. too long huh?

my QUESTION is, what could be the other way to accomplish all these faster? is GCD an option for me? how?

Any help would be much appreciated. thanks!

Upvotes: 6

Views: 4382

Answers (5)

nhahtdh
nhahtdh

Reputation: 56819

I have an idea how to solve, but not yet tested. I'm drawing the solution from several other problems that I encountered and solved:

  • Insert NSNull to NSMutableArray as placeholders.
  • dispatch_async the heavy work and replace the corresponding entry in NSMutableArray (use @synchronized keyword to lock the NSMutableArray)
  • Also in dispatch async function, dispatch back to main queue the function to update the view.

Upvotes: 1

user523234
user523234

Reputation: 14834

I just do it as an exercise: Use GCD concurrent Q for each doSomethingAndReturn and use a serial q to monitor the number of callbacks. When the number of callbacks equals to number of doSomethingAndReturn(s) then return the prepareImages array.

I created the code to test the concept.

-(NSString *)doSomethingAndReturn1
{
    for (int i=0; i<30; i++) 
    {
        NSLog(@"soSomethingAndReturn1 i: %i", i);
    }
    return @"soSomethingAndReturn1";
}

-(NSString *)doSomethingAndReturn2
{
    for (int i=0; i<10; i++) 
    {
        NSLog(@"soSomethingAndReturn2 i: %i", i);
    }
    return @"soSomethingAndReturn2";
}

-(NSString *)doSomethingAndReturn3
{
    for (int i=0; i<20; i++) 
    {
        NSLog(@"soSomethingAndReturn3 i: %i", i);
    }
    return @"soSomethingAndReturn3";
}

-(void)addToArray:(NSString *)str
{
    [asyncArray addObject:str];
    NSLog(@"asyncArray: %@", asyncArray);
}

- (IBAction)buttonMultitasksPressed:(id)sender 
{
    dispatch_queue_t serialdQueue;
    serialdQueue = dispatch_queue_create("com.mydomain.testbed.multimethods", NULL);
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self addToArray:[self doSomethingAndReturn1]];
        });
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self addToArray:[self doSomethingAndReturn2]];
        });
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self addToArray:[self doSomethingAndReturn3]];
        });
        dispatch_sync(serialdQueue, ^{
            while (!([asyncArray count] == 3)) 
            {
                NSLog(@"not there yet count: %i", [asyncArray count]);
            }
        });

    NSLog(@"end of dispatch_sync serialQueue");
//    return asyncArray;
}

Edit: 2nd thought: The serial is not necessary.

Upvotes: 0

JMBise
JMBise

Reputation: 690

You can execute in same time on another core of your processor for do that try:

NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil];
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil];
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil];
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil];

If your processor has four core each method will be perform on a different core.

Upvotes: 1

Mike Weller
Mike Weller

Reputation: 45598

Assuming you don't mind loading the images sequentially in the background (rather than in parallel), a simple dispatch to a background queue to run prepareImages will do the trick:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    NSArray *images = [self prepareImages];

    // now send the result back to the main thread so we can do
    // UIKit stuff
    dispatch_async(dispatch_get_main_queue(), ^{
        // set the images on your UIImageViews here...
    });
});

This will load the images in a low priority background queue, then dispatch back to the main thread once it is done.

If you want to keep this even lower priority, you can use the DISPATCH_QUEUE_PRIORITY_BACKGROUND, although this is only available in iOS 4.3 and later. You should check the return value from dispatch_get_global_queue in this case and if it returns 0 you can fallback on one of the other priorities.

If you want to load each image in parallel, you should probably turn your doSomethingAndReturn methods into NSOperation subclasses and use an NSOperationQueue to run them all. That would require a bit more effort to implement. Also beware of memory usage if processing multiple large images at once.

Upvotes: 16

CarlJ
CarlJ

Reputation: 9481

you could use a NSOperationQueue:

The NSOperationQueue class regulates the execution of a set of NSOperation objects. After being added to a queue, an operation remains in that queue until it is explicitly canceled or finishes executing its task. Operations within the queue (but not yet executing) are themselves organized according to priority levels and inter-operation object dependencies and are executed accordingly. An application may create multiple operation queues and submit operations to any of them.

example for a NSOperationQueue imeplementation

or a GCD Queue:

Grand Central Dispatch (GCD) dispatch queues are a powerful tool for performing tasks. Dispatch queues let you execute arbitrary blocks of code either asynchronously or synchronously with respect to the caller. You can use dispatch queues to perform nearly all of the tasks that you used to perform on separate threads. The advantage of dispatch queues is that they are simpler to use and much more efficient at executing those tasks than the corresponding threaded code.

example for a GCD Queue implementation

Upvotes: 1

Related Questions