使用GCD并行处理阵列 [英] Process Array in parallel using GCD
问题描述
我有一个很大的数组,我想通过将它的片段交给一些异步任务来处理.作为概念证明,我编写了以下代码:
I have a large array that I would like to process by handing slices of it to a few asynchronous tasks. As a proof of concept, I have the written the following code:
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之间的随机整数进行初始化.
After init()
, array
will be initialized with random integers between 0 and 9.
calcSummary
函数分派10个任务,这些任务从array
中取出50000个项目的不连续块并将它们相加,并使用它们在summary
中的相应插槽作为累加器.
The calcSummary
function dispatches 10 tasks that take disjoint chunks of 50000 items from array
and add them up, using their respective slot in summary
as an accummulator.
该程序在self.summary[i] += self.array[x]
行崩溃.错误是:
This program crashes at the self.summary[i] += self.array[x]
line. The error is:
EXC_BAD_INSTRUCTION (code = EXC_I386_INVOP).
我可以看到,在调试器中,它在崩溃之前已经进行了几次迭代,并且在崩溃时变量具有正确范围内的值.
I can see, in the debugger, that it has managed to iterate a few times before crashing, and that the variables, at the time of the crash, have values within correct bounds.
我已经阅读到EXC_I386_INVOP
可能在尝试访问已释放的对象时发生.我想知道这是否与Swift修改数组是否有关,以及是否避免数组复制有关.
I have read that EXC_I386_INVOP
can happen when trying to access an object that has already been released. I wonder if this has anything to do with Swift making a copy of the array if it is modified, and, if so, how to avoid it.
推荐答案
与@Eduardo的答案中的方法稍有不同,使用的是Array
类型的withUnsafeMutableBufferPointer<R>(body: (inout UnsafeMutableBufferPointer<T>) -> R) -> R
方法. 该方法的文档说明:
This is a slightly different take on the approach in @Eduardo's answer, using the Array
type's withUnsafeMutableBufferPointer<R>(body: (inout UnsafeMutableBufferPointer<T>) -> R) -> R
method. That method's documentation states:
调用
body(p)
,其中p
是指向Array
的可变连续存储的指针.如果不存在此类存储,则会首先创建它.
Call
body(p)
, wherep
is a pointer to theArray
's mutable contiguous storage. If no such storage exists, it is first created.
优化器通常可以消除数组算法中的边界检查和唯一性检查,但是当失败时,在body
的参数上调用相同的算法可以让您以安全为代价.
Often, the optimizer can eliminate bounds- and uniqueness-checks within an array algorithm, but when that fails, invoking the same algorithm on body
's argument lets you trade safety for speed.
第二段似乎正是这里发生的情况,因此在Swift中使用此方法可能更惯用",无论这意味着什么:
That second paragraph seems to be exactly what's happening here, so using this method might be more "idiomatic" in Swift, whatever that means:
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)
})
}
这篇关于使用GCD并行处理阵列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!