使用GCD并行处理数组

Edu*_*rdo 12 parallel-processing grand-central-dispatch swift

我有一个大型数组,我想通过将它的片段交给几个异步任务来处理.作为概念证明,我编写了以下代码:

class TestParallelArrayProcessing {
    let array: [Int]
    var summary: [Int]

    init() {
        array = Array<Int>(count: 500000, repeatedValue: 0)
        for i in 0 ..< 500000 {
            array[i] = Int(arc4random_uniform(10))
        }
        summary = Array<Int>(count: 10, repeatedValue: 0)
    }

    func calcSummary() {
        let group = dispatch_group_create()
        let queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)

        for i in 0 ..< 10 {
            dispatch_group_async(group, queue, {
                let base = i * 50000
                for x in base ..< base + 50000 {
                    self.summary[i] += self.array[x]
                }
            })
        }
        dispatch_group_notify(group, queue, {
            println(self.summary)
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

之后init(),array将使用0到9之间的随机整数进行初始化.

calcSummary函数调度10个任务,这些任务采用不相交的50000个项目块array并将它们相加,使用它们各自的插槽summary作为累加器.

这个程序崩溃了self.summary[i] += self.array[x].错误是:

 EXC_BAD_INSTRUCTION (code = EXC_I386_INVOP).
Run Code Online (Sandbox Code Playgroud)

我可以在调试器中看到它在崩溃之前已经设法迭代了几次,并且在崩溃时变量的值在正确的范围内.

我已经读过EXC_I386_INVOP在尝试访问已经发布的对象时可能发生的事情.我想知道这是否与Swift制作数组的副本有关,如果它被修改,如果是这样,如何避免它.

Nat*_*ook 5

对于使用Array类型方法的@ Eduardo答案中的方法,这是一个略微不同的看法withUnsafeMutableBufferPointer<R>(body: (inout UnsafeMutableBufferPointer<T>) -> R) -> R.该方法的文档说明:

调用body(p),p指向Array可变连续存储的指针.如果不存在此类存储,则首先创建该存储.

通常,优化器可以消除数组算法中的边界和唯一性检查,但是当失败时,在body参数上调用相同的算法可以让您以速度交换安全性.

第二段似乎正是这里发生的事情,所以使用这种方法在Swift中可能更"惯用",无论这意味着什么:

func calcSummary() {
    let group = dispatch_group_create()
    let queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)

    self.summary.withUnsafeMutableBufferPointer {
        summaryMem -> Void in
        for i in 0 ..< 10 {
            dispatch_group_async(group, queue, {
                let base = i * 50000
                for x in base ..< base + 50000 {
                    summaryMem[i] += self.array[x]
                }
            })
        }
    }

    dispatch_group_notify(group, queue, {
        println(self.summary)
    })
}
Run Code Online (Sandbox Code Playgroud)