Gri*_*ess 9 concurrency cocoa objective-c grand-central-dispatch
您可能还记得,我正在尝试使用GCD来加速我的一些代码,即碰撞检测和分辨率引擎.但是,我显然做错了,因为我的所有GCD代码都比我的串行代码慢得多且不那么一致(慢了1.4倍到10倍之间).请允许我举个例子:我以冒泡排序方式迭代数组,以确定该数组中对象之间可能发生的所有冲突:
- (double) detectCollisionsInArray:(NSArray*)objects
{
int count = [objects count];
if (count > 0)
{
double time = CFAbsoluteTimeGetCurrent();
for (int i = 0; i < count; i++)
{
for (int j = i + 1; j < count; j++)
{
/** LOTS AND LOTS OF WORK FOR EACH OBJECT **/
}
}
return CFAbsoluteTimeGetCurrent() - time;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
非常简单,考虑到问题的限制,它似乎表现良好.但是,我想利用以下事实:在代码部分中不修改每个对象的状态,并使用GCD来并行化这项工作.要做到这一点,我尝试这样的事情:
- (double) detectCollisionsInArray:(NSArray*)objects
{
int count = [objects count];
if (count > 0)
{
NSOperationQueue* opQueue = [[NSOperationQueue alloc] init];
NSBlockOperation* blockOperation = nil;
double time = CFAbsoluteTimeGetCurrent();
for (int i = 0; i < count; i++)
{
for (int j = i + 1; j < count; j++)
{
void (^workBlock) (void) = ^()
{
/** LOTS AND LOTS OF WORK FOR EACH OBJECT **/
};
if (!blockOperation)
{
blockOperation = [NSBlockOperation blockOperationWithBlock:b];
}
else
{
[blockOperation addExecutionBlock:workBlock];
}
}
}
[opQueue addOperation:blockOperation];
[opQueue autorelease];
return CFAbsoluteTimeGetCurrent() - time;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮助我走上正确的轨道,并可能提供一个良好的GCD教程的链接?我已经浏览了几个GCD教程并搜索了所有文档,我仍然觉得我对这个主题的掌握最多是微不足道的.谢谢!
Nat*_*ror 30
您是否有理由不使用GCD C API和dispatch_*函数系列?您无法控制GCD方面NSOperationQueue(例如您要将块提交到哪个队列).此外,我不能告诉,如果你使用的是iOS或没有,但NSOperationQueue也不能在iOS上使用GCD.这可能是它催生这么多线程的原因.无论哪种方式,如果您直接使用GCD API,您的代码将更短更简单:
- (double) detectCollisionsInArray:(NSArray*)objects
{
int count = [objects count];
if (count > 0)
{
double time = CFAbsoluteTimeGetCurrent();
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < count; i++)
{
dispatch_group_async(group, queue, ^{
for (int j = i + 1; j < count; j++)
{
dispatch_group_async(group, queue, ^{
/** LOTS AND LOTS OF WORK FOR EACH OBJECT **/
});
}
});
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
return CFAbsoluteTimeGetCurrent() - time;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
您可以使用a dispatch_group将所有执行组合在一起并等待它们全部完成dispatch_group_wait.如果您不想知道块何时完成,则可以忽略组部件并使用dispatch_async.该dispatch_get_global_queue函数将获得3个并发队列之一(低,默认或高优先级)供您提交块.您不必担心限制线程数或类似的东西.GCD调度程序应该为您完成所有这些.只要确保你提交给并发队列,这既可以是3个全局队列中的一个,或者你已经通过传递创建队列DISPATCH_QUEUE_CONCURRENT来dispatch_queue_create(这是可启动OS X 10.7和iOS 5.0).
如果您在每个块中执行一些文件I/O或对其他资源征税,则可能需要在GCD中进行控制并限制一次提交到队列的块数.这与限制并发操作计数具有相同的效果NSOperationQueue.您可以使用GCD信号量执行此操作:
- (double) detectCollisionsInArray:(NSArray*)objects
{
int count = [objects count];
if (count > 0)
{
double time = CFAbsoluteTimeGetCurrent();
dispatch_group_t group = dispatch_group_create();
dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < count; i++)
{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_group_async(group, queue, ^{
for (int j = i + 1; j < count; j++)
{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_group_async(group, queue, ^{
/** LOTS AND LOTS OF WORK FOR EACH OBJECT **/
dispatch_semaphore_signal(semaphore);
});
}
dispatch_semaphore_signal(semaphore);
});
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
dispatch_release(semaphore);
return CFAbsoluteTimeGetCurrent() - time;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
一旦掌握了它,GCD使用起来非常简单.我现在在我的代码中使用它.
任何人都可以帮助我走上正确的轨道,并可能提供一个良好的GCD教程的链接?
跑,不要走到Mike Ash的博客.他在GCD上的系列节目是我见过的最清晰,最简洁的,只需要大约30分钟的时间来阅读整篇文章.Apple的WWDC视频来自2010年的GCD和块也非常好.
| 归档时间: |
|
| 查看次数: |
7543 次 |
| 最近记录: |