dispatch_apply是同步还是异步?

时间:2013-08-05 00:53:39

标签: objective-c concurrency

有人告诉我,我可以使用Grand Central Dispatch以异步方式同时运行n个进程。文档说如果进程在for循环中,我可以使用函数dispatch_apply。但现在它说了

  

请注意,dispatch_apply是同步的,因此所有应用的块都是同步的   将在它返回时完成。

这是否意味着使用dispatch_apply提交到队列的块按顺序执行?如果是这样,使用并发有什么意义?减速不会一样吗?

3 个答案:

答案 0 :(得分:13)

正如文档中所述,

dispatch_apply是同步的。它并行地在指定队列上运行一个块(如果可能的话),并等待所有块返回。如果您想异步运行一次阻止,请使用dispatch_async,如果您希望并行多次运行阻止而不阻止当前队列,只需在dispatch_apply内调用dispatch_async:< / p>

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    dispatch_apply(10, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(size_t size) {
        NSLog(@"%lu", size);
    });
});

答案 1 :(得分:6)

同步 dispatch_apply 的目的是 异步将内部循环交互分配给可用的并行处理资源。因此,整体循环性能可能会加快。

更快的循环性能?很可能,是的。 (见警告)

阻止调用dispatch_apply的线程?是的,就像循环块一样,直到完成。

对于GCD,dispatch_apply 同步,因为{em> all 异步,<{1}}将不会返回dispatch_apply创建的>并行任务已完成。

但是,dispatch_apply的每个单独任务排队可以作为并发异步任务运行,如果目标dispatch_apply 异步

例如在Swift中:

queue

产生无序输出,如:

let batchCount: Int = 10 
let queue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)
dispatch_apply(batchCount, queue) { 
   (i: Int) -> Void in
   print(i,  terminator: "  ")
}
print("\ndispatch_apply QOS_CLASS_UTILITY queue completed")

因此,0 8 1 9 2 3 4 5 6 7 dispatch_apply QOS_CLASS_UTILITY queue completed 在调用时会同步阻塞,但dispatch_apply生成的“批处理”任务可以并行,异步,并行运行。

请记住警告......

  

每次迭代期间执行的工作与工作区别   在所有其他迭代期间执行,以及每个迭代的顺序   连续循环完成并不重要

另外,请注意,为内循环任务使用串行队列不会有任何性能提升。

  

虽然允许使用串行队列并且做正确的事情   对于您的代码,使用这样的队列没有真正的性能优势   将循环留在原地。

答案 2 :(得分:0)

gcl_create_dispatch_queue()dispatch_apply()

一起使用,可以提高性能

例如:

@import Foundation;
@import OpenCL;        // gcl_create_dispatch_queue()

int main() {
      dispatch_queue_t queue = gcl_create_dispatch_queue(CL_DEVICE_TYPE_ALL, NULL);
      dispatch_apply(10, queue, ^(size_t t) {
           // some code here
      });
}

更多信息: OpenCL Programming Guide for Mac