Instantly share code, notes, and snippets.

Embed
What would you like to do?
Swift Array with Dispatch concurrent performance somparison
import Foundation
print("array bench")
print(" -o : output rendered image as \"result.ppm\"")
print(" -w Number : render image width")
print(" -h Number : render image height")
print(" -p Number : number of points")
print("----------")
var width = 4096
var height = 2048
var numPoints = 100
var printPPM = false
var iarg = 1
while iarg < CommandLine.arguments.count {
let a = CommandLine.arguments[iarg]
if a.compare("-o") == .orderedSame {
printPPM = true
} else if a.compare("-w") == .orderedSame {
iarg += 1
let b = CommandLine.arguments[iarg]
width = Int(b)!
} else if a.compare("-h") == .orderedSame {
iarg += 1
let b = CommandLine.arguments[iarg]
height = Int(b)!
} else if a.compare("-p") == .orderedSame {
iarg += 1
let b = CommandLine.arguments[iarg]
numPoints = Int(b)!
} else {
print("unknown option \(a)")
}
iarg += 1
}
print("width:\(width)")
print("height:\(height)")
print("number of points:\(numPoints)")
print("save result:\(printPPM)")
print("----------")
struct Point {
var x = 0.0
var y = 0.0
func distance(_ p:Point) -> Double {
let vx = p.x - x
let vy = p.y - y
return (vx * vx + vy * vy).squareRoot()
}
}
print("initializing...")
var points:[Point] = []
points.reserveCapacity(numPoints)
srand48(time(nil))
for _ in 0..<numPoints {
var p = Point()
p.x = drand48()
p.y = drand48()
points.append(p)
// print("(\(p.x), \(p.y))")
}
class Result {
var d = 0.0
}
var results:[Result] = []
results.reserveCapacity(width * height)
for _ in 0..<(width * height) {
results.append(Result())
}
var startTime:TimeInterval
var finishTime:TimeInterval
// serial
print("start serial with iterator loop")
startTime = Date.timeIntervalSinceReferenceDate
for iy in 0..<height {
for ix in 0..<width {
let i = ix + iy * width
var p = Point()
p.x = Double(ix) / Double(width)
p.y = Double(iy) / Double(height)
var min_d = 1e10
for pnt in points {
let tmp_d = pnt.distance(p)
if min_d > tmp_d {
min_d = tmp_d
}
}
results[i].d = min_d
}
}
finishTime = Date.timeIntervalSinceReferenceDate
print("done:\(finishTime - startTime)[sec]")
// concurrent
print("start concurrent with iterator loop")
startTime = Date.timeIntervalSinceReferenceDate
DispatchQueue.concurrentPerform(iterations: height) { (iy) in
for ix in 0..<width {
let i = ix + iy * width
var p = Point()
p.x = Double(ix) / Double(width)
p.y = Double(iy) / Double(height)
var min_d = 1e10
for pnt in points {
let tmp_d = pnt.distance(p)
if min_d > tmp_d {
min_d = tmp_d
}
}
results[i].d = min_d
}
}
finishTime = Date.timeIntervalSinceReferenceDate
print("done:\(finishTime - startTime)[sec]")
// serial
print("start serial with index loop")
startTime = Date.timeIntervalSinceReferenceDate
for iy in 0..<height {
for ix in 0..<width {
let i = ix + iy * width
var p = Point()
p.x = Double(ix) / Double(width)
p.y = Double(iy) / Double(height)
var min_d = 1e10
for k in 0..<points.count {
let pnt = points[k]
let tmp_d = pnt.distance(p)
if min_d > tmp_d {
min_d = tmp_d
}
}
results[i].d = min_d
}
}
finishTime = Date.timeIntervalSinceReferenceDate
print("done:\(finishTime - startTime)[sec]")
// concurrent
print("start concurrent with index loop")
startTime = Date.timeIntervalSinceReferenceDate
DispatchQueue.concurrentPerform(iterations: height) { (iy) in
for ix in 0..<width {
let i = ix + iy * width
var p = Point()
p.x = Double(ix) / Double(width)
p.y = Double(iy) / Double(height)
var min_d = 1e10
for k in 0..<points.count {
let pnt = points[k]
let tmp_d = pnt.distance(p)
if min_d > tmp_d {
min_d = tmp_d
}
}
results[i].d = min_d
}
}
finishTime = Date.timeIntervalSinceReferenceDate
print("done:\(finishTime - startTime)[sec]")
//
if printPPM {
print("saving result.ppm")
func clampColor(_ x:Double) -> Int {
return Int(min(255.0, pow(max(0.0, x), 1.0 / 2.2) * 255.0))
}
var maxD = 0.0
for r in results {
let d = r.d
if maxD < d {
maxD = d
}
}
if maxD > 1.0 {
maxD = 1.0
}
var resStr = "P3\n\(width) \(height)\n255\n"
for r in results {
let s = 1.0 - (r.d / maxD)
let c = clampColor(s)
resStr += "\(c) \(c) \(c)\n"
}
let url = URL(fileURLWithPath: "result.ppm")
do {
try resStr.write(to: url, atomically: true, encoding: .utf8)
print("result saved to \(url.absoluteString)")
} catch {
print("result save failed to \(url.absoluteString)")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment