mch*_*.ja 5 arrays multithreading swift
我最近一直在Swift 2.1中操作字节数组,我经常发现自己编写这样的代码:
// code to add functions to a [UInt8] object
extension CollectionType where Generator.Element == UInt8 {
func xor(with byte: UInt8) -> [UInt8] {
return map { $0 ^ byte }
}
}
// example usage: [67, 108].xor(with: 0) == [67, 108]
Run Code Online (Sandbox Code Playgroud)
是否有一种简单的方法可以并行化此map调用,以便多个线程可以同时在阵列的非重叠区域上运行?
我可以编写代码来手动将数组划分为子数组,并map在不同的线程中调用每个子数组.但我想知道Swift中是否存在一些自动进行除法的框架,因为它map是一个可以在没有副作用的线程安全环境中工作的函数调用.
澄清笔记:
[UInt8]对象,不一定每个都有CollectionType.并行执行计算循环的最简单方法是concurrentPerform(以前称为dispatch_apply;请参阅" 并发编程指南"中的" 同时执行循环迭代").但是,不,没有任何map表现可以为你做到这一点.你必须自己做.
例如,您可以编写扩展来执行并发任务:
extension Array {
public func concurrentMap<T>(_ transform: (Element) -> T) -> [T] {
var results = [Int: T]()
let queue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".sync", attributes: .concurrent)
DispatchQueue.concurrentPerform(iterations: count) { index in
let result = transform(self[index])
queue.async { results[index] = result }
}
return queue.sync(flags: .barrier) {
(0 ..< results.count).map { results[$0]! }
}
}
}
Run Code Online (Sandbox Code Playgroud)
注意:
这将阻止你调用它的线程(就像非并发的一样map),所以一定要把它调到后台队列.
需要确保每个线程上有足够的工作来证明管理所有这些线程的固有开销.(例如,每个循环的简单xor调用是不够的,你会发现它实际上比非并发再现慢.)在这些情况下,请确保你迈步(参见改进循环代码,以平衡每个并发的工作量)块).例如,不是对一个非常简单的操作进行5000次迭代,而是每次循环执行10次500次操作的迭代.您可能需要尝试合适的跨越值.
虽然我怀疑你不需要这个讨论,对于不熟悉concurrentPerform(以前称为dispatch_apply)的读者,我将在下面说明它的用法.有关该主题的更完整讨论,请参阅上面的链接.
例如,让我们考虑比简单更复杂的东西xor(因为有些东西很简单,开销超过任何获得的性能),例如天真的Fibonacci实现:
func fibonacci(_ n: Int) -> Int {
if n == 0 || n == 1 {
return n
}
return fibonacci(n - 1) + fibonacci(n - 2)
}
Run Code Online (Sandbox Code Playgroud)
如果你有一个array的Int值,你要计算,而不是:
let results = array.map { fibonacci($0) }
Run Code Online (Sandbox Code Playgroud)
你可以:
var results = [Int](count: array.count, repeatedValue: 0)
DispatchQueue.concurrentPerform(iterations: array.count) { index in
let result = self.fibonacci(array[index])
synchronize.update { results[index] = result } // use whatever synchronization mechanism you want
}
Run Code Online (Sandbox Code Playgroud)
或者,如果您想要功能再现,您可以使用extension我在上面定义的:
let results = array.concurrentMap { fibonacci($0) }
Run Code Online (Sandbox Code Playgroud)
对于Swift 2的演绎,请参阅此答案的上一版本.