并发循环

GCD 提供了执行循环的机制,其中循环相互之间同时发生。这在执行一系列计算上昂贵的计算时非常有用。

考虑这个循环:

for index in 0 ..< iterations {
    // Do something computationally expensive here
}

你可以使用 concurrentPerform(在 Swift 3 中)或 dispatch_apply(在 Swift 2 中)同时执行这些计算:

Version = 3.0

DispatchQueue.concurrentPerform(iterations: iterations) { index in
    // Do something computationally expensive here
}

Version < 3.0

dispatch_apply(iterations, queue) { index in
    // Do something computationally expensive here
}

对于每个 index,将从 0 调用循环闭包,但不包括 iterations。这些迭代将相互并发运行,因此不能保证它们运行的​​顺序。在任何给定时间同时发生的实际迭代次数通常由所讨论的设备的能力决定(例如,设备具有多少个核心)。

一些特殊注意事项:

  • concurrentPerform / dispatch_apply 可以相互之间同时运行循环,但这一切都与你调用它的线程同步发生。所以,不要从主线程调用它,因为这将阻塞该线程,直到循环完成。

  • 因为这些循环彼此同时发生,所以你有责任确保结果的线程安全性。例如,如果使用这些计算上昂贵的计算结果更新某些字典,请确保自己同步这些更新。

  • 注意,运行并发循环时会产生一些开销。因此,如果在循环内执行的计算计算量不够大,你可能会发现通过使用并发循环获得的任何性能可能会因与同步所有这些并发线程相关的开销而减少(如果没有完全抵消)。

    因此,你有责任确定在循环的每次迭代中要执行的正确工作量。如果计算过于简单,你可以使用跨越来为每个循环包含更多工作。例如,你可以在循环中执行 100 次迭代,而不是执行 100 万次平凡计算的并发循环,每次循环执行 10,000 次计算。这样就可以在每个线程上执行足够的工作,因此与管理这些并发循环相关的开销变得不那么重要了。