使用GCD并行处理阵列 [英] Process Array in parallel using GCD

查看:87
本文介绍了使用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), 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天全站免登陆