source code
/* The Computer Language Benchmarks Game
https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
direct transliteration of Greg Buchholz's C program
contributed by Isaac Gouy, fix by David Turnbull
dispatching to multiple cores, use SIMD operationn, early break
depending on previous depth by Patrick Stein
*/
import Foundation
#if os(Linux)
import Dispatch
#endif
guard CommandLine.argc > 1,
let width = Int(CommandLine.arguments[1]), width > 0
else {
print("usage: \(CommandLine.arguments[0]) <size>")
exit(EXIT_FAILURE)
}
let height = width
let iterations = 50
let depth = 4.0
let startPoint = (x:-1.5, i:-1.0)
let endPoint = (x:0.5, i:1.0)
let linecount = height
let linesize = (width + 7) / 8
let pixelheight = abs(endPoint.x-startPoint.x) / Double(height)
let pixelwidth = abs(endPoint.i-startPoint.i) / Double(width)
let pixelwidth8 = pixelwidth * 8.0
let outputsize = linecount * linesize
let pixelBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: outputsize)
var Ci0 = startPoint.i
let Cr0 = (SIMD8<Double>(0,1,2,3,4,5,6,7) * pixelwidth) + startPoint.x
let Cr0Array = ContiguousArray<SIMD8<Double>>.init(unsafeUninitializedCapacity: linesize)
{
buffer, initializedCount in
let safeBuffer = buffer
DispatchQueue.concurrentPerform(iterations: linesize)
{
x in
safeBuffer[x] = Cr0 + ( Double(x) * pixelwidth8 )
}
initializedCount = linesize
}
DispatchQueue.concurrentPerform(iterations: linecount)
{
y in
let lineaddress = pixelBuffer + (y * linesize)
let Ci = Ci0 + (Double(y) * pixelheight)
var pixel:UInt8 = 0
for x in 0..<linesize
{
mandelbrot(Cr: Cr0Array[x],Ci: Ci,pixel:&pixel)
lineaddress[x] = pixel
}
}
let stdout = FileHandle.standardOutput
stdout.write("P4\n\(width) \(height)\n".data(using:.utf8)!)
stdout.write(Data(bytesNoCopy: pixelBuffer,
count: outputsize,
deallocator: .none))
// SIMD mandelbrot calculation for 8 points in parallel
@inline(__always) func onepixel(Cr:SIMD8<Double>,Ci:Double,
Zr:inout SIMD8<Double>,Zi:inout SIMD8<Double>,
Tr:inout SIMD8<Double>,Ti:inout SIMD8<Double>)
{
Zi = 2.0 * Zr * Zi + Ci
Zr = Tr - Ti + Cr
Tr = Zr * Zr
Ti = Zi * Zi
}
// one pixel calculation stepping 8 points at a time
@inline(__always)
func mandelbrot(Cr:SIMD8<Double>,Ci:Double, pixel:inout UInt8)
{
var Zr:SIMD8<Double> = .zero
var Zi:SIMD8<Double> = .zero
var Tr:SIMD8<Double> = .zero
var Ti:SIMD8<Double> = .zero
let thresholds = SIMD8<Double>(repeating:depth)
let isFalse = SIMDMask<SIMD8<Double.SIMDMaskScalar>>(repeating: false)
let ramp = SIMD8<Int64>([128,64,32,16,8,4,2,1])
if pixel == 0
{
for _ in 0..<iterations/5
{
for _ in 0..<5
{
onepixel(Cr:Cr,Ci:Ci,Zr:&Zr,Zi:&Zi,Tr:&Tr,Ti:&Ti)
}
let result = Tr + Ti .< thresholds
if result == isFalse
{
return
}
}
}
else
{
for _ in 0..<iterations
{
onepixel(Cr:Cr,Ci:Ci,Zr:&Zr,Zi:&Zi,Tr:&Tr,Ti:&Ti)
}
}
let cmpresult = Tr + Ti .< thresholds
let reduced: SIMD8<Int64> = unsafeBitCast(cmpresult,to: SIMD8<Int64>.self)
let summask: SIMD8<Int64> = ramp & reduced
pixel = UInt8(summask.wrappedSum())
}
notes, command-line, and program output
NOTES:
64-bit Ubuntu quad core
Swift version 6.0
(swift-6.0-RELEASE)
Target: x86_64-unknown-linux-gnu
Wed, 18 Sep 2024 23:22:09 GMT
MAKE:
/opt/src/swift-6.0-RELEASE/usr/bin/swiftc mandelbrot.swift-7.swift -Ounchecked -wmo -o mandelbrot.swift-7.swift_run
15.25s to complete and log all make actions
COMMAND LINE:
./mandelbrot.swift-7.swift_run 16000
(BINARY) PROGRAM OUTPUT NOT SHOWN