一尘不染

使用GCD并行处理阵列

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)
        })
    }
}

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

calcSummary函数array使用它们各自的插槽summary作为累加器,分派10个任务,这些任务从50000个项目的不相交的块中将它们相加并相加。

该程序self.summary[i] += self.array[x]在行崩溃。错误是:

 EXC_BAD_INSTRUCTION (code = EXC_I386_INVOP).

我可以看到,在调试器中,它在崩溃前已经进行了几次迭代,并且在崩溃时变量具有正确范围内的值。

我读过EXC_I386_INVOP尝试访问已发布的对象时可能发生的情况。我想知道这是否与Swift修改数组是否有关系,如果是的话,如何避免它。


阅读 227

收藏
2020-07-07

共1个答案

一尘不染

这与@Eduardo的答案中使用Array类型withUnsafeMutableBufferPointer<R>(body: (inout UnsafeMutableBufferPointer<T>) -> R) -> R方法的方法稍有不同。该方法的文档指出

Call 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)
    })
}
2020-07-07