当前位置 : 主页 > 手机开发 > 其它 >

Swift 3 Parallel for / map Loop

来源:互联网 收集:自由互联 发布时间:2021-06-11
这上面有很多线程,但 Using Grand Central Dispatch in Swift to parallelize and speed up “for” loops?使用的是Swift 3.0代码,而我无法获得相当于3的代码(参见代码). Process Array in parallel using GCD使用指针,它
这上面有很多线程,但 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:完成永远不会执行!

错误3:错误继续存在,我确信一旦修复上述错误就会发生.

最后:代码为最快的并行(确保它尽可能并行,我不喜欢我的代码中的’并发’)map / for function possible.这是修复我的代码的补充.

马丁最初的方法仍然是正确的方法.将你的方法与他的方法合并并转换为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)
        }
    }
}

Martin的版本避免了额外的副本,因为他有一个“零”值来初始化数组.如果你知道你的类型有一个简单的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)
        }
    }
}
网友评论