这有很多线程,但是Using Grand Central Dispatch in Swift to parallelize and speed up “for" loops?使用Swift< 3.0代码而我无法获得相当于3的代码(参见代码)。 Process Array in parallel using GCD使用指针,它有点难看,所以我要在这里断言我正在寻找漂亮的Swift 3 方法来做到这一点(效率很高)当然可能)。我也听说团体很慢(?)也许有人可以确认。我也无法让小组工作。
这是我对跨步并行映射函数的实现(在Array的扩展中)。它希望在全局队列上执行,以便不阻止UI。可能是并发位不需要在范围内,只有余数循环。
extension Array {
func parallelMap<R>(striding n: Int, f: @escaping (Element) -> R, completion: @escaping ([R]) -> ()) {
let N = self.count
var res = [R?](repeating: nil, count: self.count)
DispatchQueue.global(qos: .userInitiated).async {
DispatchQueue.concurrentPerform(iterations: N/n) {k in
for i in (k * n)..<((k + 1) * n) {
res[i] = f(self[i]) //Error 1 here
}
}
//remainder loop
for i in (N - (N % n))..<N {
res[i] = f(self[i])
}
DispatchQueue.main.sync { //But it will pause on this line.
print("\nPlease work!\n") //This doesn't execute either.
completion(unwrap(res)!) //Error 2 here, or rather "not here"
}
}
}
}
public func unwrap<T>(_ arr: Array<T?>) -> Array<T>? {
if (arr.contains{$0 == nil}) {
return nil
} else {
return arr.map{(x: T?) -> T in x!}
}
}
错误1:内部数组分配线上的旧朋友EXC_BAD_ACCESS
大约是我测试它的一半时间。我猜这是一个同时访问问题。
错误2:completion
永远不会执行!
错误3:错误会一直持续下去,我确信一旦修复上述错误就会发生错误。
最后:代码为最快的并行(确保它尽可能并行,我不喜欢我的代码中的&#39;并且)功能可能。这是另外来修复我的代码。
答案 0 :(得分:7)
马丁的原始方法仍然是正确的方法。将你的方法与他的方法合并并转换为Swift 3是相当简单的(尽管我已经摆脱了你的选项并且只是手工处理了内存)。
extension Array {
func parallelMap<R>(striding n: Int, f: @escaping (Element) -> R, completion: @escaping ([R]) -> ()) {
let N = self.count
let res = UnsafeMutablePointer<R>.allocate(capacity: N)
DispatchQueue.concurrentPerform(iterations: N/n) { k in
for i in (k * n)..<((k + 1) * n) {
res[i] = f(self[i])
}
}
for i in (N - (N % n))..<N {
res[i] = f(self[i])
}
let finalResult = Array<R>(UnsafeBufferPointer(start: res, count: N))
res.deallocate(capacity: N)
DispatchQueue.main.async {
completion(finalResult)
}
}
}
马丁的版本避免了额外的副本,因为他有一个&#34;零&#34;将数组初始化为的值。如果您知道您的类型有一个简单的init()
,则可以避免额外的副本:
protocol TriviallyInitializable {
init()
}
extension Array {
func parallelMap<R>(striding n: Int, f: @escaping (Element) -> R, completion: @escaping ([R]) -> ()) where R: TriviallyInitializable {
let N = self.count
var finalResult = Array<R>(repeating: R(), count: N)
finalResult.withUnsafeMutableBufferPointer { res in
DispatchQueue.concurrentPerform(iterations: N/n) { k in
for i in (k * n)..<((k + 1) * n) {
res[i] = f(self[i])
}
}
}
for i in (N - (N % n))..<N {
finalResult[i] = f(self[i])
}
DispatchQueue.main.async {
completion(finalResult)
}
}
}