我有一个大型数组,我想通过将它的片段交给几个异步任务来处理.作为概念证明,我编写了以下代码:
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) 我最近在使用大量随机数生成"正态分布"钟形曲线时做了一些实验.
方法很简单:
由于随机值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)
和常用的计算方法,由单线程和并发版本使用: …
这里有相当多的线程然而在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) 我在我的应用程序中遵循以下周期
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,该代码未更新(未显示进度)。我怀疑这与调度有关,但是我对此相当“绿色”。我非常感谢您的帮助。谢谢。