使用 GCD 并行处理数组 [英] Process Array in parallel using GCD

查看:29
本文介绍了使用 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>(正文:(inout UnsafeMutableBufferPointer) -> 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), where p is a pointer to the Array'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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆