相关疑难解决方法(0)

使用GCD并行处理数组

我有一个大型数组,我想通过将它的片段交给几个异步任务来处理.作为概念证明,我编写了以下代码:

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, …
Run Code Online (Sandbox Code Playgroud)

parallel-processing grand-central-dispatch swift

12
推荐指数
1
解决办法
2158
查看次数

使用dispatch_group_async的并发代码的性能比单线程版本慢很多

我最近在使用大量随机数生成"正态分布"钟形曲线时做了一些实验.

方法很简单:

  • 创建一个整数数组并将其归零.(我使用的是2001整数)
  • 重复计算此数组中的索引并索引该数组中的条目,如下所示
    • 循环999或1000次.在每次迭代时:
      • 使用中心值(1000)对数组索引进行种子设定
      • 生成随机数= + 1/-1.并将其添加到数组索引中
      • 在循环结束时,递增计算的数组索引处的值.

由于随机值0/1倾向于频繁发生,因此来自上方内环的末端索引值倾向于保持接近中心值.比起始值大得多/小的索引值越来越不寻常.

在大量重复之后,阵列中的值呈现正态分布钟形曲线的形状.但是,我使用的高质量随机函数arc4random_uniform()相当慢,并且需要大量迭代才能生成平滑曲线.

我想绘制1,000,000,000(十亿)点.在主线程上运行,大约需要16个小时.

我决定重写计算代码以使用dispatch_async,并在我的8核Mac Pro上运行它.

我最终使用dispatch_group_async()提交了8个块,并使用dispatch_group_notify()在所有块都已完成处理时通知程序.

为了简化第一遍,所有8个块都写入相同的NSUInteger值数组.读取/修改写入其中一个数组条目的可能性很小,但在这种情况下,这只会导致一个值丢失.我打算稍后为数组增量添加一个锁(或者甚至可能在每个块中创建单独的数组,然后在它们之后对它们求和.)

无论如何,我重构了代码以使用dispatch_group_async()并计算每个块中总值的1/8,并将我的代码设置为运行.要我说出befuddlement,并发代码,而它马克塞斯所有我的Mac上的内核,运行MUCH比单线程代码慢.

当在单个线程上运行时,我每秒绘制大约17,800个点.使用dispatch_group_async运行时,性能下降到更接近665点/秒,或大约1/26的速度.我改变了我提交的块数--2,4或8,这没关系.表现很糟糕.我还尝试使用dispatch_async提交所有8个块而没有dispatch_group.这也无关紧要.

目前没有阻塞/锁定:所有块都以全速运行.关于为什么并发代码运行得慢,我完全不知所措.

代码现在有点混乱,因为我重构它可以单线程或同时工作,所以我可以测试.

这是运行计算的代码:

randCount = 2;
#define K_USE_ASYNC 1

#if K_USE_ASYNC
    dispatch_queue_t highQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    //dispatch_group_async

    dispatch_group_t aGroup = dispatch_group_create();
    int totalJobs = 8;
    for (int i = 0; i<totalJobs; i++)
    {
      dispatch_group_async(aGroup,
                           highQ,
                           ^{
                             [self calculateNArrayPoints: KNumberOfEntries /totalJobs
                                          usingRandCount: randCount];
                           });
    }


    dispatch_group_notify(aGroup,
                          dispatch_get_main_queue(),
                          allTasksDoneBlock
                          );
#else
    [self calculateNArrayPoints: KNumberOfEntries
                 usingRandCount: randCount];
    allTasksDoneBlock();
#endif
Run Code Online (Sandbox Code Playgroud)

和常用的计算方法,由单线程和并发版本使用: …

macos concurrency objective-c grand-central-dispatch ios

4
推荐指数
1
解决办法
771
查看次数

Swift 3 Parallel for/map Loop

这里有相当多的线程然而在Swift中使用Grand Central Dispatch来并行化并加速"for"循环?使用Swift <3.0代码而我无法在3中工作(参见代码).并行处理数组使用GCD使用指针并且它有点难看所以我要在这里断言我正在寻找好的Swift 3方法(当然尽可能高效).我也听说组很慢(?也许有人可以证实这一点.我也无法让小组工作.

这是我对跨步并行映射函数的实现(在Array的扩展中).它希望在全局队列上执行,以便不阻止UI.可能是并发位不需要在范围内,只需要余数循环.

extension Array {

    func parallelMap<R>(striding n: Int, f: @escaping (Element) -> R, completion: @escaping ([R]) -> ()) {
        let N = self.count
        var res = [R?](repeating: nil, count: self.count)
        DispatchQueue.global(qos: .userInitiated).async {
            DispatchQueue.concurrentPerform(iterations: N/n) {k in
                for i in (k * n)..<((k + 1) * n) {
                    res[i] = f(self[i]) //Error 1 here
                }
            }
            //remainder loop
            for i in (N - (N % n))..<N {
                res[i] = …
Run Code Online (Sandbox Code Playgroud)

parallel-processing grand-central-dispatch swift

4
推荐指数
1
解决办法
2119
查看次数

长周期块应用

我在我的应用程序中遵循以下周期

var maxIterations: Int = 0

func calculatePoint(cn: Complex) -> Int {

    let threshold: Double = 2
    var z: Complex = .init(re: 0, im: 0)
    var z2: Complex = .init(re: 0, im: 0)
    var iteration: Int = 0

    repeat {
        z2 = self.pow2ForComplex(cn: z)
        z.re = z2.re + cn.re
        z.im = z2.im + cn.im
        iteration += 1
    } while self.absForComplex(cn: z) <= threshold && iteration < self.maxIterations

    return iteration
}
Run Code Online (Sandbox Code Playgroud)

并在循环执行期间显示彩虹轮。如何管理该应用仍在响应UI操作?注意:在循环运行时,我在代码的不同部分更新了NSProgressIndicator,该代码未更新(未显示进度)。我怀疑这与调度有关,但是我对此相当“绿色”。我非常感谢您的帮助。谢谢。

nsprogressindicator dispatch-async swift3

2
推荐指数
1
解决办法
593
查看次数