apo*_*che 35 performance primes swift
当我正在玩一个快速的教程时,我开始编写一个自定义isPrime方法来检查给定Int是否为素数.
在写完之后,我意识到它工作正常,但发现它isPrime在某些相当大的数字上执行有点慢(当时仍然低得多Int.max).
所以我在objc中编写了相同的代码片段,代码执行得更快(66倍).
这是快速代码:
class Swift {
class func isPrime(n:Int) -> Bool {
let sqr : Int = Int(sqrt(Double(n))) + 1
for i in 2...sqr {
if n % i == 0 {
return false
}
}
return true;
}
class func primesInRange(start:Int, end:Int) -> Int[] {
var primes:Int[] = Int[]()
for n in start...end {
if self.isPrime(n) {
primes.append(n)
}
}
return primes;
}
}
Run Code Online (Sandbox Code Playgroud)
和objc代码:
@implementation Utils
+ (BOOL)isPrime:(NSUInteger)n {
NSInteger sqr = (NSUInteger)(sqrt(n))+1;
for (NSUInteger i = 2; i < sqr; ++i) {
if (n % i == 0) {
return false;
}
}
return YES;
}
+ (NSArray*)primesInRange:(NSUInteger)start end:(NSUInteger)end {
NSMutableArray* primes = [NSMutableArray array];
for (NSUInteger i = start; i <= end; ++i) {
if ([self isPrime:i])
[primes addObject:@(i)];
}
return primes.copy;
}
@end
Run Code Online (Sandbox Code Playgroud)
并在main.swift:
let startDateSwift = NSDate.date()
let swiftPrimes = Swift.primesInRange(1_040_101_022_000, end: 1_040_101_022_200)
let elapsedSwift = NSDate.date().timeIntervalSinceDate(startDateSwift)*1000
let startDateObjc = NSDate.date()
let objcPrimes = Utils.primesInRange(1_040_101_022_000, end: 1_040_101_022_200)
let elapsedObjc = NSDate.date().timeIntervalSinceDate(startDateObjc)*1000
println("\(swiftPrimes) took: \(elapsedSwift)ms");
println("\(objcPrimes) took: \(elapsedObjc)ms");
Run Code Online (Sandbox Code Playgroud)
这会产生:
[1040101022027, 1040101022039, 1040101022057, 1040101022099, 1040101022153] took: 3953.82004976273ms
[1040101022027, 1040101022039, 1040101022057, 1040101022099, 1040101022153] took: 66.4250254631042ms
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用extensionon Int来检查数字是否为素数,但我希望两个代码非常相似.
任何人都可以告诉我为什么这个快速的代码是如此之慢?66倍因素非常可怕,只是随着我增加范围而变得更糟.
Jos*_*ark 27
以下是Swift编译器代码生成的优化级别(您可以在Build Settings中找到它们):
[-Onone] no optimizations, the default for debug.
[-O] perform optimizations, the default for release.
[-Ofast] perform optimizations and disable runtime overflow checks and runtime type checks.
Run Code Online (Sandbox Code Playgroud)
使用您的代码我在不同的优化级别获得了这些时间:
[-在一个]
Swift: 6110.98903417587ms
Objc: 134.006023406982ms
Run Code Online (Sandbox Code Playgroud)
[-O]
Swift: 89.8249745368958ms
Objc: 85.5680108070374ms
Run Code Online (Sandbox Code Playgroud)
[-Ofast]
Swift: 77.1470069885254ms
Objc: 76.3399600982666ms
Run Code Online (Sandbox Code Playgroud)
请记住,-Ofast带有风险.例如,它会默默地忽略整数和数组溢出,产生无意义的结果,因此如果您选择使用它,您必须保证自己在程序中无法进行溢出.
归功于@sjeohp的评论,这基本上就是问题的答案.
我尝试以最积极的方式优化代码以Release进行LLVM和Swift优化:


编译项目Release并得到:
[1040101022027, 1040101022039, 1040101022057, 1040101022099, 1040101022153] took: 63.211977481842ms
[1040101022027, 1040101022039, 1040101022057, 1040101022099, 1040101022153] took: 60.0320100784302ms
Run Code Online (Sandbox Code Playgroud)
再次感谢@sjeohp抓住这个!
| 归档时间: |
|
| 查看次数: |
4691 次 |
| 最近记录: |