【问题标题】:Is dispatch_apply synchronous or asynchronous?dispatch_apply 是同步的还是异步的?
【发布时间】:2013-08-05 00:53:39
【问题描述】:

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

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

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

【问题讨论】:

    标签: objective-c concurrency


    【解决方案1】:

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

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

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

    对于 GCD,dispatch_apply 是同步的,因为 dispatch_apply 直到 所有 异步、并行才会返回strong> dispatch_apply 创建的任务已经完成。

    然而,dispatch_applyenqueued 的每个单独任务都可以作为并发异步 任务运行如果目标queue 是异步。

    例如在 Swift 中:

    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 在调用时会同步阻塞,但dispatch_apply 生成的“批处理”任务可以同时、异步、并行运行。

    请记住...

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

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

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

    【讨论】:

      【解决方案2】:

      dispatch_apply 如文档中所述,是同步的。它在指定队列上并行运行一个块(如果可能)并等待所有块返回。如果你想异步运行一个块一次,使用dispatch_async,如果你想在不阻塞当前队列的情况下并行运行一个块,只需在dispatch_async中调用dispatch_apply:

      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);
          });
      });
      

      【讨论】:

      • 太棒了,这正是我想做的。谢谢。
      【解决方案3】:

      您可以通过使用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

      【讨论】:

        猜你喜欢
        • 2020-05-15
        • 2020-02-21
        • 2013-02-25
        • 2012-12-30
        • 2014-04-25
        • 1970-01-01
        • 2019-01-17
        • 2017-06-22
        • 1970-01-01
        相关资源
        最近更新 更多