├── .gitignore ├── GeekbenchSwift.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── GeekbenchSwift ├── complex.swift ├── fft.swift ├── fibonacci.swift ├── gemm.swift ├── main.swift ├── mandelbrot.swift ├── timer.swift ├── workload.swift ├── workloadResult.swift └── workloadUnits.swift ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | # Pods/ 27 | -------------------------------------------------------------------------------- /GeekbenchSwift.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0002395719D5FE4B000B3387 /* complex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0002395619D5FE4B000B3387 /* complex.swift */; }; 11 | 0005077D1A2E182400AF55C1 /* fibonacci.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0005077C1A2E182400AF55C1 /* fibonacci.swift */; }; 12 | 004F806419D0BF1F0054E320 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004F806319D0BF1F0054E320 /* main.swift */; }; 13 | 004F806D19D0BFB40054E320 /* mandelbrot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004F806C19D0BFB40054E320 /* mandelbrot.swift */; }; 14 | 004F806F19D0C10A0054E320 /* workload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004F806E19D0C10A0054E320 /* workload.swift */; }; 15 | 004F807119D0CB3B0054E320 /* workloadResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004F807019D0CB3B0054E320 /* workloadResult.swift */; }; 16 | 00633B8419D32504002A1388 /* timer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00633B8319D32504002A1388 /* timer.swift */; }; 17 | 00D6F5C819D20652007A19E5 /* workloadUnits.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00D6F5C719D20652007A19E5 /* workloadUnits.swift */; }; 18 | 00D6F5CA19D2194F007A19E5 /* gemm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00D6F5C919D2194F007A19E5 /* gemm.swift */; }; 19 | 00DB67E11A2E741200A986DD /* fft.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00DB67E01A2E741200A986DD /* fft.swift */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXCopyFilesBuildPhase section */ 23 | 004F805E19D0BF1F0054E320 /* CopyFiles */ = { 24 | isa = PBXCopyFilesBuildPhase; 25 | buildActionMask = 2147483647; 26 | dstPath = /usr/share/man/man1/; 27 | dstSubfolderSpec = 0; 28 | files = ( 29 | ); 30 | runOnlyForDeploymentPostprocessing = 1; 31 | }; 32 | /* End PBXCopyFilesBuildPhase section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | 0002395619D5FE4B000B3387 /* complex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = complex.swift; sourceTree = ""; }; 36 | 0005077C1A2E182400AF55C1 /* fibonacci.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = fibonacci.swift; sourceTree = ""; }; 37 | 004F806019D0BF1F0054E320 /* GeekbenchSwift */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = GeekbenchSwift; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 004F806319D0BF1F0054E320 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 39 | 004F806C19D0BFB40054E320 /* mandelbrot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = mandelbrot.swift; sourceTree = ""; }; 40 | 004F806E19D0C10A0054E320 /* workload.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = workload.swift; sourceTree = ""; }; 41 | 004F807019D0CB3B0054E320 /* workloadResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = workloadResult.swift; sourceTree = ""; }; 42 | 00633B8319D32504002A1388 /* timer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = timer.swift; sourceTree = ""; }; 43 | 00D6F5C719D20652007A19E5 /* workloadUnits.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = workloadUnits.swift; sourceTree = ""; }; 44 | 00D6F5C919D2194F007A19E5 /* gemm.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = gemm.swift; sourceTree = ""; }; 45 | 00DB67E01A2E741200A986DD /* fft.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = fft.swift; sourceTree = ""; }; 46 | 189F37C81BE1A4D1007874EC /* ReadMe */ = {isa = PBXFileReference; lastKnownFileType = text; path = ReadMe; sourceTree = ""; }; 47 | /* End PBXFileReference section */ 48 | 49 | /* Begin PBXFrameworksBuildPhase section */ 50 | 004F805D19D0BF1F0054E320 /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | /* End PBXFrameworksBuildPhase section */ 58 | 59 | /* Begin PBXGroup section */ 60 | 004F805719D0BF1F0054E320 = { 61 | isa = PBXGroup; 62 | children = ( 63 | 189F37C81BE1A4D1007874EC /* ReadMe */, 64 | 004F806219D0BF1F0054E320 /* GeekbenchSwift */, 65 | 004F806119D0BF1F0054E320 /* Products */, 66 | ); 67 | sourceTree = ""; 68 | }; 69 | 004F806119D0BF1F0054E320 /* Products */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | 004F806019D0BF1F0054E320 /* GeekbenchSwift */, 73 | ); 74 | name = Products; 75 | sourceTree = ""; 76 | }; 77 | 004F806219D0BF1F0054E320 /* GeekbenchSwift */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 004F806319D0BF1F0054E320 /* main.swift */, 81 | 004F806C19D0BFB40054E320 /* mandelbrot.swift */, 82 | 004F806E19D0C10A0054E320 /* workload.swift */, 83 | 004F807019D0CB3B0054E320 /* workloadResult.swift */, 84 | 00DB67E01A2E741200A986DD /* fft.swift */, 85 | 00D6F5C719D20652007A19E5 /* workloadUnits.swift */, 86 | 00D6F5C919D2194F007A19E5 /* gemm.swift */, 87 | 00633B8319D32504002A1388 /* timer.swift */, 88 | 0002395619D5FE4B000B3387 /* complex.swift */, 89 | 0005077C1A2E182400AF55C1 /* fibonacci.swift */, 90 | ); 91 | path = GeekbenchSwift; 92 | sourceTree = ""; 93 | }; 94 | /* End PBXGroup section */ 95 | 96 | /* Begin PBXNativeTarget section */ 97 | 004F805F19D0BF1F0054E320 /* GeekbenchSwift */ = { 98 | isa = PBXNativeTarget; 99 | buildConfigurationList = 004F806719D0BF1F0054E320 /* Build configuration list for PBXNativeTarget "GeekbenchSwift" */; 100 | buildPhases = ( 101 | 004F805C19D0BF1F0054E320 /* Sources */, 102 | 004F805D19D0BF1F0054E320 /* Frameworks */, 103 | 004F805E19D0BF1F0054E320 /* CopyFiles */, 104 | ); 105 | buildRules = ( 106 | ); 107 | dependencies = ( 108 | ); 109 | name = GeekbenchSwift; 110 | productName = GeekbenchSwift; 111 | productReference = 004F806019D0BF1F0054E320 /* GeekbenchSwift */; 112 | productType = "com.apple.product-type.tool"; 113 | }; 114 | /* End PBXNativeTarget section */ 115 | 116 | /* Begin PBXProject section */ 117 | 004F805819D0BF1F0054E320 /* Project object */ = { 118 | isa = PBXProject; 119 | attributes = { 120 | LastSwiftMigration = 0710; 121 | LastSwiftUpdateCheck = 0710; 122 | LastUpgradeCheck = 0710; 123 | ORGANIZATIONNAME = "Primate Labs"; 124 | TargetAttributes = { 125 | 004F805F19D0BF1F0054E320 = { 126 | CreatedOnToolsVersion = 6.1; 127 | }; 128 | }; 129 | }; 130 | buildConfigurationList = 004F805B19D0BF1F0054E320 /* Build configuration list for PBXProject "GeekbenchSwift" */; 131 | compatibilityVersion = "Xcode 3.2"; 132 | developmentRegion = English; 133 | hasScannedForEncodings = 0; 134 | knownRegions = ( 135 | en, 136 | ); 137 | mainGroup = 004F805719D0BF1F0054E320; 138 | productRefGroup = 004F806119D0BF1F0054E320 /* Products */; 139 | projectDirPath = ""; 140 | projectRoot = ""; 141 | targets = ( 142 | 004F805F19D0BF1F0054E320 /* GeekbenchSwift */, 143 | ); 144 | }; 145 | /* End PBXProject section */ 146 | 147 | /* Begin PBXSourcesBuildPhase section */ 148 | 004F805C19D0BF1F0054E320 /* Sources */ = { 149 | isa = PBXSourcesBuildPhase; 150 | buildActionMask = 2147483647; 151 | files = ( 152 | 00DB67E11A2E741200A986DD /* fft.swift in Sources */, 153 | 004F806419D0BF1F0054E320 /* main.swift in Sources */, 154 | 00D6F5CA19D2194F007A19E5 /* gemm.swift in Sources */, 155 | 004F807119D0CB3B0054E320 /* workloadResult.swift in Sources */, 156 | 0002395719D5FE4B000B3387 /* complex.swift in Sources */, 157 | 004F806F19D0C10A0054E320 /* workload.swift in Sources */, 158 | 00D6F5C819D20652007A19E5 /* workloadUnits.swift in Sources */, 159 | 00633B8419D32504002A1388 /* timer.swift in Sources */, 160 | 004F806D19D0BFB40054E320 /* mandelbrot.swift in Sources */, 161 | 0005077D1A2E182400AF55C1 /* fibonacci.swift in Sources */, 162 | ); 163 | runOnlyForDeploymentPostprocessing = 0; 164 | }; 165 | /* End PBXSourcesBuildPhase section */ 166 | 167 | /* Begin XCBuildConfiguration section */ 168 | 004F806519D0BF1F0054E320 /* Debug */ = { 169 | isa = XCBuildConfiguration; 170 | buildSettings = { 171 | ALWAYS_SEARCH_USER_PATHS = NO; 172 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 173 | CLANG_CXX_LIBRARY = "libc++"; 174 | CLANG_ENABLE_MODULES = YES; 175 | CLANG_ENABLE_OBJC_ARC = YES; 176 | CLANG_WARN_BOOL_CONVERSION = YES; 177 | CLANG_WARN_CONSTANT_CONVERSION = YES; 178 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 179 | CLANG_WARN_EMPTY_BODY = YES; 180 | CLANG_WARN_ENUM_CONVERSION = YES; 181 | CLANG_WARN_INT_CONVERSION = YES; 182 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 183 | CLANG_WARN_UNREACHABLE_CODE = YES; 184 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 185 | CLANG_X86_VECTOR_INSTRUCTIONS = sse4.2; 186 | COPY_PHASE_STRIP = NO; 187 | ENABLE_STRICT_OBJC_MSGSEND = YES; 188 | GCC_C_LANGUAGE_STANDARD = gnu99; 189 | GCC_DYNAMIC_NO_PIC = NO; 190 | GCC_OPTIMIZATION_LEVEL = 0; 191 | GCC_PREPROCESSOR_DEFINITIONS = ( 192 | "DEBUG=1", 193 | "$(inherited)", 194 | ); 195 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 196 | GCC_UNROLL_LOOPS = YES; 197 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 198 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 199 | GCC_WARN_UNDECLARED_SELECTOR = YES; 200 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 201 | GCC_WARN_UNUSED_FUNCTION = YES; 202 | GCC_WARN_UNUSED_VARIABLE = YES; 203 | LLVM_LTO = NO; 204 | MACOSX_DEPLOYMENT_TARGET = 10.9; 205 | MTL_ENABLE_DEBUG_INFO = YES; 206 | ONLY_ACTIVE_ARCH = YES; 207 | SDKROOT = macosx; 208 | SWIFT_OPTIMIZATION_LEVEL = "-Ounchecked"; 209 | }; 210 | name = Debug; 211 | }; 212 | 004F806619D0BF1F0054E320 /* Release */ = { 213 | isa = XCBuildConfiguration; 214 | buildSettings = { 215 | ALWAYS_SEARCH_USER_PATHS = NO; 216 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 217 | CLANG_CXX_LIBRARY = "libc++"; 218 | CLANG_ENABLE_MODULES = YES; 219 | CLANG_ENABLE_OBJC_ARC = YES; 220 | CLANG_WARN_BOOL_CONVERSION = YES; 221 | CLANG_WARN_CONSTANT_CONVERSION = YES; 222 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 223 | CLANG_WARN_EMPTY_BODY = YES; 224 | CLANG_WARN_ENUM_CONVERSION = YES; 225 | CLANG_WARN_INT_CONVERSION = YES; 226 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 227 | CLANG_WARN_UNREACHABLE_CODE = YES; 228 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 229 | CLANG_X86_VECTOR_INSTRUCTIONS = sse4.2; 230 | COPY_PHASE_STRIP = YES; 231 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 232 | ENABLE_NS_ASSERTIONS = NO; 233 | ENABLE_STRICT_OBJC_MSGSEND = YES; 234 | GCC_C_LANGUAGE_STANDARD = gnu99; 235 | GCC_OPTIMIZATION_LEVEL = fast; 236 | GCC_UNROLL_LOOPS = YES; 237 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 238 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 239 | GCC_WARN_UNDECLARED_SELECTOR = YES; 240 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 241 | GCC_WARN_UNUSED_FUNCTION = YES; 242 | GCC_WARN_UNUSED_VARIABLE = YES; 243 | LLVM_LTO = NO; 244 | MACOSX_DEPLOYMENT_TARGET = 10.9; 245 | MTL_ENABLE_DEBUG_INFO = NO; 246 | ONLY_ACTIVE_ARCH = YES; 247 | SDKROOT = macosx; 248 | SWIFT_OPTIMIZATION_LEVEL = "-Ounchecked"; 249 | }; 250 | name = Release; 251 | }; 252 | 004F806819D0BF1F0054E320 /* Debug */ = { 253 | isa = XCBuildConfiguration; 254 | buildSettings = { 255 | CLANG_USE_OPTIMIZATION_PROFILE = YES; 256 | PRODUCT_NAME = "$(TARGET_NAME)"; 257 | }; 258 | name = Debug; 259 | }; 260 | 004F806919D0BF1F0054E320 /* Release */ = { 261 | isa = XCBuildConfiguration; 262 | buildSettings = { 263 | CLANG_USE_OPTIMIZATION_PROFILE = YES; 264 | PRODUCT_NAME = "$(TARGET_NAME)"; 265 | }; 266 | name = Release; 267 | }; 268 | /* End XCBuildConfiguration section */ 269 | 270 | /* Begin XCConfigurationList section */ 271 | 004F805B19D0BF1F0054E320 /* Build configuration list for PBXProject "GeekbenchSwift" */ = { 272 | isa = XCConfigurationList; 273 | buildConfigurations = ( 274 | 004F806519D0BF1F0054E320 /* Debug */, 275 | 004F806619D0BF1F0054E320 /* Release */, 276 | ); 277 | defaultConfigurationIsVisible = 0; 278 | defaultConfigurationName = Release; 279 | }; 280 | 004F806719D0BF1F0054E320 /* Build configuration list for PBXNativeTarget "GeekbenchSwift" */ = { 281 | isa = XCConfigurationList; 282 | buildConfigurations = ( 283 | 004F806819D0BF1F0054E320 /* Debug */, 284 | 004F806919D0BF1F0054E320 /* Release */, 285 | ); 286 | defaultConfigurationIsVisible = 0; 287 | defaultConfigurationName = Release; 288 | }; 289 | /* End XCConfigurationList section */ 290 | }; 291 | rootObject = 004F805819D0BF1F0054E320 /* Project object */; 292 | } 293 | -------------------------------------------------------------------------------- /GeekbenchSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GeekbenchSwift/complex.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Primate Labs Inc. 2 | // Use of this source code is governed by the 2-clause BSD license that 3 | // can be found in the LICENSE file. 4 | 5 | // Content has been moved into fft.swift for performance. 6 | -------------------------------------------------------------------------------- /GeekbenchSwift/fft.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Primate Labs Inc. 2 | // Use of this source code is governed by the 2-clause BSD license that 3 | // can be found in the LICENSE file. 4 | import Foundation 5 | 6 | struct Complex : CustomStringConvertible { 7 | internal var real : Float32 8 | internal var imaginary : Float32 9 | var description: String { 10 | return String(format: "(%.5f, %.5fi)", real, imaginary) 11 | } 12 | 13 | init() { 14 | self.real = 0 15 | self.imaginary = 0 16 | } 17 | 18 | init(real : Float32, imaginary : Float32) { 19 | self.real = real 20 | self.imaginary = imaginary 21 | } 22 | 23 | mutating func assign(real : Float32, imaginary : Float32) { 24 | self.real = real 25 | self.imaginary = imaginary 26 | } 27 | 28 | mutating func assign(rhs : Complex) { 29 | self.real = rhs.real 30 | self.imaginary = rhs.imaginary 31 | } 32 | 33 | mutating func add(rhs : Complex) { 34 | self.real += rhs.real 35 | self.imaginary += rhs.imaginary 36 | } 37 | 38 | mutating func subtract(rhs : Complex) { 39 | self.real -= rhs.real 40 | self.imaginary -= rhs.imaginary 41 | } 42 | } 43 | 44 | func * (left : Complex, right : Complex) -> Complex { 45 | return Complex(real: left.real * right.real - left.imaginary * right.imaginary, 46 | imaginary: left.real * right.imaginary + left.imaginary * right.real) 47 | } 48 | 49 | func + (left : Complex, right : Complex) -> Complex { 50 | return Complex(real: left.real + right.real, imaginary: left.imaginary + right.imaginary) 51 | } 52 | 53 | func - (left : Complex, right : Complex) -> Complex { 54 | return Complex(real: left.real - right.real, imaginary: left.imaginary - right.imaginary) 55 | } 56 | 57 | 58 | final class SFFTWorkload : Workload { 59 | let pi = Float32(acos(-1.0)) 60 | 61 | let size : Int 62 | let chunkSize : Int 63 | var input : [Complex] 64 | var output : UnsafeMutablePointer 65 | var wFactors : [Complex] = [] 66 | 67 | init(size : Int, chunkSize : Int) { 68 | self.size = size 69 | self.chunkSize = chunkSize 70 | 71 | self.input = [Complex](count: size, repeatedValue: Complex()) 72 | self.output = UnsafeMutablePointer.alloc(chunkSize) 73 | 74 | 75 | 76 | // Precompute w factors 77 | self.wFactors.reserveCapacity(chunkSize) 78 | var theta : Float32 = 0 79 | let mult : Float32 = -2.0 * self.pi / Float32(chunkSize) 80 | for _ in 0..> 1 108 | o = (o & 0x33333333) << 2 | (o & 0xCCCCCCCC) >> 2 109 | o = (o & 0x0F0F0F0F) << 4 | (o & 0xF0F0F0F0) >> 4 110 | o = (o & 0x00FF00FF) << 8 | (o & 0xFF00FF00) >> 8 111 | o = (o & 0x0000FFFF) << 16 | (o & 0xFFFF0000) >> 16 112 | 113 | o >>= shiftCorrection 114 | 115 | self.output[Int(o)].assign(self.input[chunkOrigin + Int(i)]) 116 | } 117 | } 118 | 119 | func executeInplaceFFTOnOutput(chunkOrigin : Int) { 120 | self.fftWithOrigin(0, size: self.chunkSize, wStep: 1) 121 | } 122 | 123 | func fftWithOrigin(origin : Int, size : Int, wStep : Int) { 124 | 125 | if size == 4 { 126 | fft4WithOrigin(origin) 127 | return 128 | } 129 | 130 | let m = size / 2 131 | fftWithOrigin(origin, size: m, wStep: 2 * wStep) 132 | fftWithOrigin(origin + m, size: m, wStep: 2 * wStep) 133 | 134 | var wIndex = 0 135 | for offset in 0.. UInt32 { 182 | // This algorithm is from Hacker's Delight: http://www.hackersdelight.org/hdcodetxt/nlz.c.txt 183 | var nlz : UInt32 = 0 184 | var x = value 185 | 186 | if x == 0 { 187 | return 32 188 | } 189 | 190 | if x <= 0x0000FFFF { 191 | nlz += 16 192 | x <<= 16 193 | } 194 | if x <= 0x00FFFFFF { 195 | nlz += 8 196 | x <<= 8 197 | } 198 | if x <= 0x0FFFFFFF { 199 | nlz += 4 200 | x <<= 4 201 | } 202 | if x <= 0x3FFFFFFF { 203 | nlz += 2 204 | x <<= 2 205 | } 206 | if x <= 0x7FFFFFFF { 207 | ++nlz 208 | } 209 | return nlz 210 | } 211 | 212 | override func reset() { 213 | for i in 0.. UInt64 { 221 | let chunks = size / chunkSize 222 | 223 | let lc = log(Float32(self.chunkSize)) 224 | let l2 = log(Float32(2.0)) 225 | let floatOps = Float32(chunks * 5 * self.chunkSize) * lc / l2 226 | 227 | return UInt64(floatOps) 228 | } 229 | 230 | override func units() -> WorkloadUnits { 231 | return WorkloadUnits.Flops 232 | } 233 | 234 | override func name() -> String { 235 | return "FFT" 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /GeekbenchSwift/fibonacci.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Primate Labs Inc. 2 | // Use of this source code is governed by the 2-clause BSD license that 3 | // can be found in the LICENSE file. 4 | 5 | import Foundation 6 | 7 | final class FibonacciWorkload : Workload { 8 | var n : UInt 9 | var output : UInt 10 | var nodes : UInt 11 | 12 | init(n : UInt) { 13 | self.n = n 14 | self.output = 0 15 | self.nodes = 0 16 | } 17 | 18 | override func worker() { 19 | let tmp = FibonacciWorkload.fibonacci(self.n) 20 | self.output = tmp.f 21 | self.nodes = tmp.nodes 22 | } 23 | 24 | class func fibonacci(n : UInt) -> (f : UInt, nodes : UInt) { 25 | if n == 0 { 26 | return (0, 1); 27 | } else if n == 1 { 28 | return (0, 1); 29 | } else { 30 | let left = fibonacci(n - 1) 31 | let right = fibonacci(n - 2) 32 | return (left.f + right.f, left.nodes + right.nodes + 1) 33 | } 34 | } 35 | 36 | override func reset() { 37 | self.nodes = 0 38 | } 39 | 40 | override func work() -> UInt64 { 41 | return UInt64(self.nodes) 42 | } 43 | 44 | override func units() -> WorkloadUnits { 45 | return WorkloadUnits.NodesSecond 46 | } 47 | 48 | override func name() -> String { 49 | return "Fibonacci" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /GeekbenchSwift/gemm.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Primate Labs Inc. 2 | // Use of this source code is governed by the 2-clause BSD license that 3 | // can be found in the LICENSE file. 4 | 5 | import Foundation 6 | 7 | struct Matrix { 8 | var N : Int 9 | var M : [Float32] 10 | 11 | init(matrixSize : Int) { 12 | self.N = matrixSize 13 | self.M = [Float32](count: matrixSize * matrixSize, repeatedValue: 0) 14 | } 15 | 16 | subscript(i1: Int, i2: Int) -> Float32 { 17 | get { 18 | return M[i1 * N + i2] 19 | } 20 | 21 | set(newValue) { 22 | M[i1 * N + i2] = newValue 23 | } 24 | } 25 | } 26 | 27 | final class SGEMMWorkload : Workload { 28 | var matrixSize : Int = 0 29 | var blockSize : Int = 0 30 | final var A : Matrix 31 | final var B : Matrix 32 | final var C : Matrix 33 | 34 | init(matrixSize : Int, blockSize : Int) { 35 | self.matrixSize = matrixSize 36 | self.blockSize = blockSize 37 | 38 | A = Matrix(matrixSize: matrixSize) 39 | B = Matrix(matrixSize: matrixSize) 40 | C = Matrix(matrixSize: matrixSize) 41 | } 42 | 43 | override func worker() { 44 | for var i = 0; i < matrixSize; i += blockSize { 45 | for var j = 0; j < matrixSize; j += blockSize { 46 | for var k = 0; k < matrixSize; k += blockSize { 47 | 48 | let ib = min(matrixSize, i + blockSize) 49 | let jb = min(matrixSize, j + blockSize) 50 | let kb = min(matrixSize, k + blockSize) 51 | 52 | for var i0 = i; i0 < ib; ++i0 { 53 | for var j0 = j; j0 < jb; ++j0 { 54 | 55 | let c = C[i0, j0] 56 | 57 | var scratch = c 58 | 59 | for var k0 = k; k0 < kb; ++k0 { 60 | 61 | let a = A[i0, k0] 62 | let b = B[j0, k0] 63 | 64 | scratch += a * b 65 | } 66 | 67 | // C[i0, j0] = scratch 68 | } 69 | } 70 | 71 | } 72 | } 73 | } 74 | } 75 | 76 | override func reset() { 77 | for i in 0.. UInt64 { 89 | let N = UInt64(matrixSize) 90 | return 2 * N * N * N 91 | } 92 | 93 | override func units() -> WorkloadUnits { 94 | return WorkloadUnits.Flops 95 | } 96 | 97 | override func name() -> String { 98 | return "SGEMM" 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /GeekbenchSwift/main.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Primate Labs Inc. 2 | // Use of this source code is governed by the 2-clause BSD license that 3 | // can be found in the LICENSE file. 4 | 5 | import Foundation 6 | 7 | 8 | let workloadFactories = [ 9 | {() -> Workload in return MandelbrotWorkload(width: 800, height: 800) }, 10 | // {() -> Workload in return SGEMMWorkload(matrixSize: 896, blockSize: 512 / sizeof(Float32)) }, 11 | {() -> Workload in return SFFTWorkload(size: 8 * 1024 * 1024, chunkSize: 4096)}, 12 | {() -> Workload in return FibonacciWorkload(n: 36)}, 13 | ] 14 | 15 | 16 | func printResult(result : WorkloadResult) { 17 | print(result.workloadName) 18 | for (rate, runtime) in Zip2Sequence(result.rates, result.runtimes) { 19 | let rateString = result.workloadUnits.stringFromRate(rate) 20 | print(" \(rateString) (\(runtime) seconds)") 21 | } 22 | 23 | let minRate = result.rates.reduce(Double.infinity) { min($0, $1) } 24 | let maxRate = result.rates.reduce(0) { max($0, $1) } 25 | let avgRate = result.rates.reduce(0) { $0 + $1 } / Double(result.rates.count) 26 | 27 | let minString = result.workloadUnits.stringFromRate(minRate) 28 | let maxString = result.workloadUnits.stringFromRate(maxRate) 29 | let avgString = result.workloadUnits.stringFromRate(avgRate) 30 | 31 | print("") 32 | print(" Min rate: \(minString)") 33 | print(" Max rate: \(maxString)") 34 | print(" Avg rate: \(avgString)") 35 | print("") 36 | } 37 | 38 | func main() { 39 | for workloadFactory in workloadFactories { 40 | let workload = workloadFactory() 41 | let result = workload.run() 42 | printResult(result) 43 | } 44 | } 45 | 46 | main() 47 | -------------------------------------------------------------------------------- /GeekbenchSwift/mandelbrot.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Primate Labs Inc. 2 | // Use of this source code is governed by the 2-clause BSD license that 3 | // can be found in the LICENSE file. 4 | 5 | import Foundation 6 | 7 | final class MandelbrotWorkload : Workload { 8 | var width : UInt 9 | var height : UInt 10 | var output : [UInt8]? = nil 11 | 12 | init(width : UInt, height : UInt) { 13 | self.width = width 14 | self.height = height 15 | } 16 | 17 | override func worker() { 18 | self.output = [UInt8](count: Int(self.width * self.height), repeatedValue: 0) 19 | 20 | // Origin 21 | let ro : Float = -1.5 22 | let co : Float = 1.0 23 | 24 | // Stride 25 | let sr = 2.0 / Float(self.width) 26 | let sc = -2.0 / Float(self.height) 27 | 28 | // let w = Int(self.width) 29 | // let h = Int(self.height) 30 | 31 | for x : UInt in 0..= 4.0 { 45 | break 46 | } 47 | 48 | zr += zr0 49 | zc += zc0 50 | 51 | k++ 52 | } 53 | 54 | let index = Int(self.width * y + x) 55 | let value = UInt8(min(max(k, 0), 255)) 56 | 57 | self.output![index] = value 58 | } 59 | } 60 | } 61 | 62 | override func reset() { 63 | } 64 | 65 | override func work() -> UInt64 { 66 | var work : UInt64 = 0 67 | for element in self.output! { 68 | work += UInt64(11) * UInt64(element) 69 | } 70 | return work 71 | } 72 | 73 | override func units() -> WorkloadUnits { 74 | return WorkloadUnits.Flops 75 | } 76 | 77 | override func name() -> String { 78 | return "Mandelbrot" 79 | } 80 | } -------------------------------------------------------------------------------- /GeekbenchSwift/timer.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Primate Labs Inc. 2 | // Use of this source code is governed by the 2-clause BSD license that 3 | // can be found in the LICENSE file. 4 | 5 | import Foundation 6 | 7 | struct Timer { 8 | var startTime = NSDate() 9 | 10 | mutating func restart() { 11 | startTime = NSDate() 12 | } 13 | 14 | func elapsed() -> Double { 15 | return -startTime.timeIntervalSinceNow 16 | } 17 | } -------------------------------------------------------------------------------- /GeekbenchSwift/workload.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Primate Labs Inc. 2 | // Use of this source code is governed by the 2-clause BSD license that 3 | // can be found in the LICENSE file. 4 | 5 | import Foundation 6 | 7 | class Workload { 8 | func worker() { 9 | fatalError("Implementer must override") 10 | } 11 | 12 | func reset() { 13 | fatalError("Implementer must override") 14 | } 15 | 16 | func work() -> UInt64 { 17 | fatalError("Implementer must override") 18 | } 19 | 20 | func units() -> WorkloadUnits { 21 | fatalError("Implementer must override") 22 | } 23 | 24 | func name() -> String { 25 | fatalError("Implementer must override") 26 | } 27 | 28 | func run() -> WorkloadResult { 29 | var result = WorkloadResult() 30 | result.workloadName = self.name() 31 | result.workloadUnits = self.units() 32 | 33 | for _ in 1...8 { 34 | self.reset() 35 | 36 | let timer = Timer() 37 | self.worker() 38 | let elapsed = timer.elapsed() 39 | 40 | result.runtimes.append(elapsed) 41 | result.rates.append(Double(self.work()) / elapsed) 42 | } 43 | 44 | return result 45 | } 46 | } -------------------------------------------------------------------------------- /GeekbenchSwift/workloadResult.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Primate Labs Inc. 2 | // Use of this source code is governed by the 2-clause BSD license that 3 | // can be found in the LICENSE file. 4 | 5 | import Foundation 6 | 7 | struct WorkloadResult { 8 | var workloadName = "" 9 | var runtimes : [Double] = [] 10 | var rates : [Double] = [] 11 | var workloadUnits = WorkloadUnits.BytesSecond 12 | } -------------------------------------------------------------------------------- /GeekbenchSwift/workloadUnits.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Primate Labs Inc. 2 | // Use of this source code is governed by the 2-clause BSD license that 3 | // can be found in the LICENSE file. 4 | 5 | import Foundation 6 | 7 | enum WorkloadUnits { 8 | case BytesSecond, PixelsSecond, Flops, NodesSecond 9 | 10 | func string() -> String { 11 | switch self { 12 | case .BytesSecond: 13 | return "Bytes/Second" 14 | case .PixelsSecond: 15 | return "Pixels/Second" 16 | case .Flops: 17 | return "Flops" 18 | case .NodesSecond: 19 | return "Nodes/Second" 20 | } 21 | } 22 | 23 | func stringFromRate(rate : Double) -> String { 24 | var outRate = rate 25 | var divisor : Double = 1000.0 26 | 27 | if self == .BytesSecond { 28 | divisor = 1024.0 29 | } 30 | 31 | let prefixes = ["", "K", "M", "G", "T"] 32 | var prefix = prefixes[0] 33 | 34 | for var i = 0; i < prefixes.count; ++i { 35 | prefix = prefixes[i] 36 | 37 | if outRate < divisor { 38 | break 39 | } 40 | 41 | outRate /= divisor 42 | } 43 | 44 | let outRateString = NSString(format: "%.2f", outRate) 45 | let units = self.string() 46 | return "\(outRateString) \(prefix)\(units)" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Primate Labs Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | swift-performance 2 | ================= 3 | --------------------------------------------------------------------------------