use*_*167 6 parallel-processing macos grand-central-dispatch swift
我试图围绕如何使用GCD来并行化和加速蒙特卡罗模拟.大多数/所有简单示例都是针对Objective C提供的,我真的需要一个Swift的简单示例,因为Swift是我的第一个"真正的"编程语言.
Swift中蒙特卡罗模拟的最小工作版本将是这样的:
import Foundation
import Cocoa
var winner = 0
var j = 0
var i = 0
var chance = 0
var points = 0
for j=1;j<1000001;++j{
var ability = 500
var player1points = 0
for i=1;i<1000;++i{
chance = Int(arc4random_uniform(1001))
if chance<(ability-points) {++points}
else{points = points - 1}
}
if points > 0{++winner}
}
println(winner)
Run Code Online (Sandbox Code Playgroud)
代码可以直接粘贴到xcode 6.1中的命令行程序项目中
最内层的循环不能并行化,因为变量"points"的新值在下一个循环中使用.但最外面的只是运行最里面的模拟1000000次并计算结果,应该是并行化的理想候选者.
所以我的问题是如何使用GCD并行化最外层的for循环?
"多线程迭代"可以通过以下方式完成dispatch_apply():
let outerCount = 100 // # of concurrent block iterations
let innerCount = 10000 // # of iterations within each block
let the_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(UInt(outerCount), the_queue) { outerIdx -> Void in
for innerIdx in 1 ... innerCount {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
(你必须弄清楚外部和内部计数之间的最佳关系.)
有两件事需要注意:
arc4random()使用内部互斥锁,这使得从多个并行线程调用时非常慢,请参阅使用dispatch_group_async执行并发代码的性能比单线程版本慢很多.从那里给出的答案,
rand_r()(每个线程有单独的种子)似乎是更快的替代方案.
winner不能同时从多个线程修改结果变量.您可以使用数组,而不是每个线程更新其自己的元素,然后添加结果./sf/answers/1875301361/中描述了一种线程安全的方法.
然后它大致如下:
let outerCount = 100 // # of concurrent block iterations
let innerCount = 10000 // # of iterations within each block
let the_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
var winners = [Int](count: outerCount, repeatedValue: 0)
winners.withUnsafeMutableBufferPointer { winnersPtr -> Void in
dispatch_apply(UInt(outerCount), the_queue) { outerIdx -> Void in
var seed = arc4random() // seed for rand_r() in this "thread"
for innerIdx in 1 ... innerCount {
var points = 0
var ability = 500
for i in 1 ... 1000 {
let chance = Int(rand_r(&seed) % 1001)
if chance < (ability-points) { ++points }
else {points = points - 1}
}
if points > 0 {
winnersPtr[Int(outerIdx)] += 1
}
}
}
}
// Add results:
let winner = reduce(winners, 0, +)
println(winner)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2609 次 |
| 最近记录: |