我遇到了这样一个时间密集的for循环:
int sum = 0;
for (int i = 0; i < max; ++i)
sum += dosomething(i);
do something(i)
次来电是独立的。这呼吁多线程。在双核机器上使用NSOperationQueue,我可以这样做:
int __block midpoint;
int __block sum1;
int __block sum2;
midpoint = max/2;
sum1 = 0;
sum2 = 0;
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSOperation *operation = [NSBlockOperation blockOperationWithBlock: ^{
for (int i = 0; i < midpoint; ++i)
sum1 += dosomething(i);
}];
[queue addOperation: operation];
operation = [NSBlockOperation blockOperationWithBlock: ^{
for (int i = midpoint; i < lines.count; ++i)
sum2 += dosomething(i);
}];
[queue addOperation: operation];
[queue waitUntilAllOperationsAreFinished];
int sum = sum1 + sum2;
使用单个NSBlock并将循环的开始/停止值作为参数传递会更好,但是与NSOperation一起使用的块不能有参数。更好的一个原因是,为不同数量的核心编码所需的体操变得相当过分。
有没有更好的方法在iOS中设置它,以便可以使用参数创建单个NSBlock(或其等效的),然后多次调用并发执行?理想情况下,该技术必须是方法的本地技术,并且具有对局部变量的读/写访问权限(使用局部变量上的__block限定符可以使用NSBlock)?
对于那些后来出现的人,这里是我最终使用的代码,从答案和几条评论中收集到的。
dispatch_queue_t coreQueue = dispatch_queue_create("coreQueue", DISPATCH_QUEUE_CONCURRENT);
int __block count = 0;
int processorCount = (int) [[NSProcessInfo processInfo] processorCount];
dispatch_apply(processorCount, coreQueue, ^(size_t i) {
int localCount = 0;
int imax = (i + 1)*max/processorCount;
if (i + 1 == processorCount)
imax = lines.count;
int imin = i*max/processorCount;
for (int j = imin; j < imax; ++j)
localCount += dosomething(j);
// The results array should only be accessed from the main queue.
dispatch_async(dispatch_get_main_queue(), ^{
count += localCount;
});
});
答案 0 :(得分:2)
您应该使用NSEnumerationConcurren标志:
假设您有一个想要迭代的对象数组,您可以这样做:
[myArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
//do something
}];
Here's the apple documentation on NSEnumerationConcurrent
Here's a link to show how well it profiles!
使用dispatch_apply:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(count, queue, ^(size_t i) {
printf("%u\n",i); //Do expensive operation here.
});
答案 1 :(得分:0)
使用并发调度队列。
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
[self doAnExpensiveOperation];
});
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
[self doAnotherExpensiveOperation];
});
dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
// called when both have finished.
// calculate sum here
});
});