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制作数组的副本有关,如果它被修改,如果是这样,如何避免它.
对于使用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)
归档时间: |
|
查看次数: |
2158 次 |
最近记录: |