我有一个很大的数组,我想通过将它的片段交给一些异步任务来处理。作为概念证明,我编写了以下代码:
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修改数组是否有关系,如果是的话,如何避免它。
这与@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)
})
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句