Swift Betaでアルゴリズムを実装していましたが、パフォーマンスが非常に悪いことに気付きました。さらに深く掘り下げた後、私はボトルネックの1つが配列のソートと同じくらい簡単なものであることに気付きました。関連部分はここにあります:
let n = 1000000
var x = [Int](repeating: 0, count: n)
for i in 0..<n {
x[i] = random()
}
// start clock here
let y = sort(x)
// stop clock here
C++では、私のコンピュータでも同様の操作が0.06sかかります。
Pythonでは、それは0.6sかかります(トリックなし、整数のリストのためにちょうどy = sorted(x))。
Swiftでは、次のコマンドでコンパイルすると6sがかかります。
xcrun Swift -O3 -sdk `xcrun --show-sdk-path --sdk macosx`
次のコマンドでコンパイルすると、88sほどかかります。
xcrun Swift -O0 -sdk `xcrun --show-sdk-path --sdk macosx`
"Release"ビルドと "Debug"ビルドのXcodeのタイミングは似ています。
ここで何が問題なのですか私は、C++と比較してパフォーマンスの低下をある程度理解することができましたが、純粋なPythonと比較して10倍の減速はしませんでした。
編集:weatherは、-O3
を-Ofast
に変更すると、このコードがC++バージョンとほぼ同じ速度で実行されることに気付きました。しかし、-Ofast
は言語の意味を大きく変えます - 私のテストでは、それは整数オーバーフローと配列インデックスオーバーフローのチェックを無効にしました。たとえば、-Ofast
を指定すると、次のSwiftコードはクラッシュせずにサイレントに実行されます(そしてゴミがプリントされます)。
let n = 10000000
print(n*n*n*n*n)
let x = [Int](repeating: 10, count: n)
print(x[n])
だから-Ofast
は欲しいものではありません。 Swiftのポイントは、セーフティネットが設置されていることです。もちろん、セーフティネットはパフォーマンスにいくらかの影響を与えますが、プログラムを100倍遅くするべきではありません。 Javaはすでに配列の境界をチェックしていることを覚えておいてください、そして典型的なケースでは、減速は2よりずっと小さいファクターによるものです。そしてClangとGCCでは、(符号付き)整数オーバーフローのチェックに-ftrapv
を持っています。 。
それゆえ、問題は、セーフティネットを失うことなくSwiftで合理的なパフォーマンスをどのように得ることができるかということです。
編集2:私はもう少しベンチマークを行いました。
for i in 0..<n {
x[i] = x[i] ^ 12345678
}
(ここでxor演算は、アセンブリコード内の関連するループをより簡単に見つけることができるようにするためのものです。発見しやすいだけでなく、関連するチェックを必要としないという意味で「無害」な演算を選びました。整数オーバーフローへ)
繰り返しますが、-O3
と-Ofast
のパフォーマンスには大きな違いがありました。それで、私はアセンブリコードを見ました:
-Ofast
を使えば、私は期待していたものをほとんど手に入れることができます。関連部分は、5つの機械語命令を含むループです。
-O3
を使えば、私の最も広い想像を超えるものを手に入れることができます。内側のループは88行のアセンブリコードにわたります。すべてを理解しようとはしませんでしたが、最も疑わしい部分は、 "callq _Swift_retain"の13回の呼び出しと "callq _Swift_release"の13回の呼び出しです。つまり、26サブルーチンは内側のループで呼び出します!
編集3:コメントでは、Ferruccioは組み込み関数に依存しないという意味で公平なベンチマークを求めました(例:sort)。次のプログラムはかなり良い例だと思います。
let n = 10000
var x = [Int](repeating: 1, count: n)
for i in 0..<n {
for j in 0..<n {
x[i] = x[j]
}
}
算術演算がないので、整数オーバーフローについて心配する必要はありません。私たちがする唯一のことは、たくさんの配列参照です。そして結果はここにあります - Swift -O3は-Ofastと比較して約500のファクターで失います:
(コンパイラが無意味なループを完全に最適化することを心配しているならば、それを例えばx[i] ^= x[j]
に変更し、x[0]
を出力するprintステートメントを追加することができます。これは何も変更しません。タイミングは非常に似ています。)
そして、はい、ここではPythonの実装はintのリストを持ち、forループを入れ子にしたバカな純粋なPython実装でした。最適化されていないSwiftよりmuch遅いはずです。 Swiftと配列のインデックス付けで何かがひどく壊れているようです。
編集4:これらの問題(および他のいくつかのパフォーマンス問題)はXcode 6 beta 5で修正されたようです。
並べ替えのために、私は今、次のタイミングがあります。
ネストループの場合:
安全でない-Ofast
(a.k.a. -Ounchecked
)を使用する理由はもうないようです。普通の-O
は同じように良いコードを生成します。
tl; dr Swift 1.0は、このベンチマークではデフォルトのリリース最適化レベル[-O]を使ってCと同じ速さになりました。
これがSwift Betaのインプレースクイックソートです。
func quicksort_Swift(inout a:CInt[], start:Int, end:Int) {
if (end - start < 2){
return
}
var p = a[start + (end - start)/2]
var l = start
var r = end - 1
while (l <= r){
if (a[l] < p){
l += 1
continue
}
if (a[r] > p){
r -= 1
continue
}
var t = a[l]
a[l] = a[r]
a[r] = t
l += 1
r -= 1
}
quicksort_Swift(&a, start, r + 1)
quicksort_Swift(&a, r + 1, end)
}
そしてCでも同じです。
void quicksort_c(int *a, int n) {
if (n < 2)
return;
int p = a[n / 2];
int *l = a;
int *r = a + n - 1;
while (l <= r) {
if (*l < p) {
l++;
continue;
}
if (*r > p) {
r--;
continue;
}
int t = *l;
*l++ = *r;
*r-- = t;
}
quicksort_c(a, r - a + 1);
quicksort_c(l, a + n - l);
}
両方ともうまくいきます。
var a_Swift:CInt[] = [0,5,2,8,1234,-1,2]
var a_c:CInt[] = [0,5,2,8,1234,-1,2]
quicksort_Swift(&a_Swift, 0, a_Swift.count)
quicksort_c(&a_c, CInt(a_c.count))
// [-1, 0, 2, 2, 5, 8, 1234]
// [-1, 0, 2, 2, 5, 8, 1234]
両方とも、書かれているのと同じプログラムで呼び出されます。
var x_Swift = CInt[](count: n, repeatedValue: 0)
var x_c = CInt[](count: n, repeatedValue: 0)
for var i = 0; i < n; ++i {
x_Swift[i] = CInt(random())
x_c[i] = CInt(random())
}
let Swift_start:UInt64 = mach_absolute_time();
quicksort_Swift(&x_Swift, 0, x_Swift.count)
let Swift_stop:UInt64 = mach_absolute_time();
let c_start:UInt64 = mach_absolute_time();
quicksort_c(&x_c, CInt(x_c.count))
let c_stop:UInt64 = mach_absolute_time();
これは絶対時間を秒に変換します。
static const uint64_t NANOS_PER_USEC = 1000ULL;
static const uint64_t NANOS_PER_MSEC = 1000ULL * NANOS_PER_USEC;
static const uint64_t NANOS_PER_SEC = 1000ULL * NANOS_PER_MSEC;
mach_timebase_info_data_t timebase_info;
uint64_t abs_to_nanos(uint64_t abs) {
if ( timebase_info.denom == 0 ) {
(void)mach_timebase_info(&timebase_info);
}
return abs * timebase_info.numer / timebase_info.denom;
}
double abs_to_seconds(uint64_t abs) {
return abs_to_nanos(abs) / (double)NANOS_PER_SEC;
}
これがコンパイラの最適化レベルの要約です。
[-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.
[-Onone] が n = 10_000 の場合の秒数
Swift: 0.895296452
C: 0.001223848
これは n = 10_000 に対するSwiftの組み込みsort()です。
Swift_builtin: 0.77865783
これは、 [-O] で、 n = 10_000 の場合です。
Swift: 0.045478346
C: 0.000784666
Swift_builtin: 0.032513488
ご覧のとおり、Swiftのパフォーマンスは20倍に向上しました。
mweathersの答え に従って、 [-Ofast] を設定すると実際の差が生じ、 n = 10_000 の場合は次のようになります。
Swift: 0.000706745
C: 0.000742374
Swift_builtin: 0.000603576
そして n = 1_000_000 の場合:
Swift: 0.107111846
C: 0.114957179
Swift_sort: 0.092688548
比較のために、これは [-Onone] n = 1_000_000 の場合です。
Swift: 142.659763258
C: 0.162065333
Swift_sort: 114.095478272
そのため、このベンチマークでは、開発のこの段階では、最適化なしのSwiftはCの約1000倍遅くなりました。一方、両方のコンパイラが[-Ofast]に設定されていると、Swiftは実際にはCよりわずかに優れていないとしても少なくとも同様に実行しました。
[-Ofast]は言語のセマンティクスを変更し、潜在的に安全ではないと指摘しています。これは、AppleがXcode 5.0リリースノートで述べていることです。
LLVMで利用可能な新しい最適化レベル-Ofastは、積極的な最適化を可能にします。 -Ofastは、ほとんどのコードにとって安全な、主に浮動小数点演算に関する保守的な制限を緩和します。それはコンパイラからかなりの高性能勝を生み出すことができます。
彼らは皆それを主張している。それが賢明であろうとなかろうと私は言うことができませんでした、しかし私が言うことができることからあなたが高精度浮動小数点演算をしていないそして整数でないと確信しているならばプログラムで配列オーバーフローが発生する可能性があります。高性能のandオーバーフローチェック/正確な算術が必要な場合は、今のところ別の言語を選択してください。
ベータ3アップデート:
n = 10_000 with [-O] :
Swift: 0.019697268
C: 0.000718064
Swift_sort: 0.002094721
一般的にSwiftは少し速いですし、Swiftの組み込みソートがかなり変わったようです。
最終更新日:
[-Onone] :
Swift: 0.678056695
C: 0.000973914
[-O] :
Swift: 0.001158492
C: 0.001192406
[ - 未チェック] :
Swift: 0.000827764
C: 0.001078914
TL; DR:はい、唯一のSwift言語実装は低速です今。高速な数値(およびおそらく他のタイプのコード)コードが必要な場合は、別のコードを使用してください。将来的には、選択を再評価する必要があります。ただし、より高いレベルで記述されたほとんどのアプリケーションコードには十分かもしれません。
私がSILとLLVM IRで見ていることから、保持とリリースを削除するための一連の最適化が必要なようです。これは、 Clang (Objective-Cの場合)で実装されますが、まだ移植していません。プロファイラーがこの質問の最後のテストケースで実行すると、この「きれいな」結果が得られるため、これが私がやろうとしている理論です(今のところ... Clangがそれについて何かを確認する必要があります)。
他の多くの人が言ったように、-Ofast
は完全に安全ではなく、言語のセマンティクスを変更します。私にとっては、「それを使用する場合は、別の言語を使用するだけ」の段階です。変更した場合、後でその選択を再評価します。
-O3
は、Swift_retain
およびSwift_release
呼び出しの束を取得しますが、正直なところ、この例ではそれらが存在するようには見えません。オプティマイザは、アレイに関するほとんどの情報を知っており、(少なくとも)強い参照を持っていることを知っているので、(ほとんど)それらを省略します。
オブジェクトを解放する可能性のある関数を呼び出していない場合でも、より多くのリテインを発行しないでください。配列コンストラクターは、要求されたものよりも小さい配列を返すことができるとは思いません。つまり、発行された多くのチェックは役に立たないということです。また、整数が10kを超えることはないことも知っているため、オーバーフローチェックcanが最適化されます(-Ofast
奇妙さのためではなく、言語のセマンティクスのため(他に変更はありません)その変数はアクセスできず、最大10kを追加してもタイプInt
に対して安全です。
ただし、外部関数であり、期待する引数を取得する必要があるsort()
に渡されるため、コンパイラは配列または配列要素をボックス化解除できない場合があります。これにより、Int
値を間接的に使用する必要があり、少し遅くなります。これは、sort()
ジェネリック関数(マルチメソッドの方法ではない)がコンパイラーで使用可能で、インライン化された場合に変更される可能性があります。
これは非常に新しい(公の)言語であり、Swift言語にフィードバックを求めている(重度の)人がいて、全員がその言語を言っているので、多くの変更があると思います。終了していないwill change。
使用されるコード:
import Cocoa
let Swift_start = NSDate.timeIntervalSinceReferenceDate();
let n: Int = 10000
let x = Int[](count: n, repeatedValue: 1)
for i in 0..n {
for j in 0..n {
let tmp: Int = x[j]
x[i] = tmp
}
}
let y: Int[] = sort(x)
let Swift_stop = NSDate.timeIntervalSinceReferenceDate();
println("\(Swift_stop - Swift_start)s")
P.S:私はObjective-Cの専門家でもないし、 Cocoa 、Objective-C、またはSwiftランタイムのすべての機能でもありません。また、私が書いていないことを想定しているかもしれません。
私は楽しみのためにこれを見てみることにしました、そしてここに私が得るタイミングがあります:
Swift 4.0.2 : 0.83s (0.74s with `-Ounchecked`)
C++ (Apple LLVM 8.0.0): 0.74s
// Swift 4.0 code
import Foundation
func doTest() -> Void {
let arraySize = 10000000
var randomNumbers = [UInt32]()
for _ in 0..<arraySize {
randomNumbers.append(arc4random_uniform(UInt32(arraySize)))
}
let start = Date()
randomNumbers.sort()
let end = Date()
print(randomNumbers[0])
print("Elapsed time: \(end.timeIntervalSince(start))")
}
doTest()
結果:
Swift 1.1
xcrun swiftc --version
Swift version 1.1 (Swift-600.0.54.20)
Target: x86_64-Apple-darwin14.0.0
xcrun swiftc -O SwiftSort.Swift
./SwiftSort
Elapsed time: 1.02204304933548
スイフト1.2
xcrun swiftc --version
Apple Swift version 1.2 (swiftlang-602.0.49.6 clang-602.0.49)
Target: x86_64-Apple-darwin14.3.0
xcrun -sdk macosx swiftc -O SwiftSort.Swift
./SwiftSort
Elapsed time: 0.738763988018036
Swift 2.0
xcrun swiftc --version
Apple Swift version 2.0 (swiftlang-700.0.59 clang-700.0.72)
Target: x86_64-Apple-darwin15.0.0
xcrun -sdk macosx swiftc -O SwiftSort.Swift
./SwiftSort
Elapsed time: 0.767306983470917
-Ounchecked
を付けてコンパイルした場合も同じパフォーマンスになります。
Swift 3.0
xcrun swiftc --version
Apple Swift version 3.0 (swiftlang-800.0.46.2 clang-800.0.38)
Target: x86_64-Apple-macosx10.9
xcrun -sdk macosx swiftc -O SwiftSort.Swift
./SwiftSort
Elapsed time: 0.939633965492249
xcrun -sdk macosx swiftc -Ounchecked SwiftSort.Swift
./SwiftSort
Elapsed time: 0.866258025169373
Swift 2.0からSwift 3.0へのパフォーマンスの低下が見られますが、私は-O
と-Ounchecked
の違いも初めて見ました。
Swift 4.0
xcrun swiftc --version
Apple Swift version 4.0.2 (swiftlang-900.0.69.2 clang-900.0.38)
Target: x86_64-Apple-macosx10.9
xcrun -sdk macosx swiftc -O SwiftSort.Swift
./SwiftSort
Elapsed time: 0.834299981594086
xcrun -sdk macosx swiftc -Ounchecked SwiftSort.Swift
./SwiftSort
Elapsed time: 0.742045998573303
Swift 4は-O
と-Ounchecked
の間のギャップを維持しながら、パフォーマンスを再び向上させます。 -O -whole-module-optimization
は違いを生むようには見えませんでした。
#include <chrono>
#include <iostream>
#include <vector>
#include <cstdint>
#include <stdlib.h>
using namespace std;
using namespace std::chrono;
int main(int argc, const char * argv[]) {
const auto arraySize = 10000000;
vector<uint32_t> randomNumbers;
for (int i = 0; i < arraySize; ++i) {
randomNumbers.emplace_back(arc4random_uniform(arraySize));
}
const auto start = high_resolution_clock::now();
sort(begin(randomNumbers), end(randomNumbers));
const auto end = high_resolution_clock::now();
cout << randomNumbers[0] << "\n";
cout << "Elapsed time: " << duration_cast<duration<double>>(end - start).count() << "\n";
return 0;
}
結果:
アップルクラン6.0
clang++ --version
Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn)
Target: x86_64-Apple-darwin14.0.0
Thread model: posix
clang++ -O3 -std=c++11 CppSort.cpp -o CppSort
./CppSort
Elapsed time: 0.688969
Apple Clang 6.1.0
clang++ --version
Apple LLVM version 6.1.0 (clang-602.0.49) (based on LLVM 3.6.0svn)
Target: x86_64-Apple-darwin14.3.0
Thread model: posix
clang++ -O3 -std=c++11 CppSort.cpp -o CppSort
./CppSort
Elapsed time: 0.670652
Apple Clang 7.0.0
clang++ --version
Apple LLVM version 7.0.0 (clang-700.0.72)
Target: x86_64-Apple-darwin15.0.0
Thread model: posix
clang++ -O3 -std=c++11 CppSort.cpp -o CppSort
./CppSort
Elapsed time: 0.690152
Apple Clang 8.0.0
clang++ --version
Apple LLVM version 8.0.0 (clang-800.0.38)
Target: x86_64-Apple-darwin15.6.0
Thread model: posix
clang++ -O3 -std=c++11 CppSort.cpp -o CppSort
./CppSort
Elapsed time: 0.68253
Apple Clang 9.0.0
clang++ --version
Apple LLVM version 9.0.0 (clang-900.0.38)
Target: x86_64-Apple-darwin16.7.0
Thread model: posix
clang++ -O3 -std=c++11 CppSort.cpp -o CppSort
./CppSort
Elapsed time: 0.736784
これを書いている時点では、Swiftのソートは高速ですが、-O
を使ってコンパイルした場合のC++のソートほど高速ではありません。 -Ounchecked
を使用すると、Swift 4.0.2およびApple LLVM 9.0.0のC++と同じくらい高速になります。
The Swift Programming Language
から:
ソート関数Swiftの標準ライブラリにはsortと呼ばれる関数が用意されています。これは、指定されたソートクロージャの出力に基づいて、既知の型の値の配列をソートします。ソート処理が完了すると、sort関数は、要素が正しいソート順になった、古いものと同じタイプとサイズの新しい配列を返します。
sort
関数には2つの宣言があります。
比較クロージャを指定できるデフォルトの宣言:
func sort<T>(array: T[], pred: (T, T) -> Bool) -> T[]
そして2つ目の宣言は1つのパラメータ(配列)のみを取り、「小なり比較を使用するようにハードコードされています」。
func sort<T : Comparable>(array: T[]) -> T[]
Example:
sort( _arrayToSort_ ) { $0 > $1 }
関数をもう少し詳しく監視できるように、遊び場であなたのコードの修正版をテストしました。そして、nを1000に設定して、その閉じが約11,000回呼ばれていることがわかりました。
let n = 1000
let x = Int[](count: n, repeatedValue: 0)
for i in 0..n {
x[i] = random()
}
let y = sort(x) { $0 > $1 }
これは効率的な機能ではありません。より良いソート機能の実装を使用することをお勧めします。
編集:
私はQuicksortのウィキペディアのページを見て、それにSwiftの実装を書きました。これは私が(遊び場で)使用した完全なプログラムです。
import Foundation
func quickSort(inout array: Int[], begin: Int, end: Int) {
if (begin < end) {
let p = partition(&array, begin, end)
quickSort(&array, begin, p - 1)
quickSort(&array, p + 1, end)
}
}
func partition(inout array: Int[], left: Int, right: Int) -> Int {
let numElements = right - left + 1
let pivotIndex = left + numElements / 2
let pivotValue = array[pivotIndex]
swap(&array[pivotIndex], &array[right])
var storeIndex = left
for i in left..right {
let a = 1 // <- Used to see how many comparisons are made
if array[i] <= pivotValue {
swap(&array[i], &array[storeIndex])
storeIndex++
}
}
swap(&array[storeIndex], &array[right]) // Move pivot to its final place
return storeIndex
}
let n = 1000
var x = Int[](count: n, repeatedValue: 0)
for i in 0..n {
x[i] = Int(arc4random())
}
quickSort(&x, 0, x.count - 1) // <- Does the sorting
for i in 0..n {
x[i] // <- Used by the playground to display the results
}
N = 1000でこれを使うと、
組み込みのsortメソッドはクイックソートである(または近い)と思われますが、本当に時間がかかります。
Xcode 7以降、Fast, Whole Module Optimization
をオンにすることができます。これによりすぐにパフォーマンスが向上します。
Swift Arrayのパフォーマンスの見直し:
私はSwiftとC/Objective-Cを比較する私自身のベンチマークを書きました。私のベンチマークは素数を計算します。新しい候補ごとに素因数を探すために以前の素数の配列を使用するので、非常に高速です。しかし、それは配列の読み込みの数が多く、配列への書き込みが少なくなります。
私はもともとSwift 1.2に対してこのベンチマークをしました。私はプロジェクトを更新してSwift 2.0に対して実行することにしました。
このプロジェクトでは、通常のSwift配列を使用するか、配列セマンティクスを使用してSwift安全でないメモリバッファーを使用するかを選択できます。
C/Objective-Cでは、NSArraysを使うか、Cのmallocされた配列を使うことができます。
テスト結果は、最速で最小のコード最適化([-0s])または最速で積極的な([-0fast])最適化とかなり似ているようです。
Swift 2.0のパフォーマンスは、コードの最適化をオフにした状態では依然としてひどいものですが、C/Objective-Cのパフォーマンスはやや遅くなります。
肝心なことに、C mallocによる配列ベースの計算は、適度なマージンで最速です。
安全でないバッファでのSwiftは、最速で最小のコード最適化を使用した場合、C mallocの配列よりも約1.19倍から1.20倍長くなります。高速で積極的な最適化では、違いはわずかに少なく見えます(SwiftはCよりも1.18倍から1.16倍長くかかります)。
通常のSwift配列を使用する場合、Cとの違いはわずかに大きいです。 (Swiftは約1.22から1.23かかります。)
通常のSwift配列はSwift 1.2/Xcode 6よりもDRAMATICALLY
高速です。それらのパフォーマンスはSwiftの安全でないバッファベースの配列に非常に近いため、安全でないメモリバッファを使用することはそれ以上問題にはなりません。
ところで、Objective-C NSArrayのパフォーマンスは悪くなります。両方の言語でネイティブのコンテナオブジェクトを使うつもりなら、Swiftは _劇的に_ 速いです。
Githubの SwiftPerformanceBenchmark で私のプロジェクトをチェックアウトできます。
それは統計を集めることをかなり容易にする簡単なUIを持っています。
SwiftのソートがCよりやや速いように思われるのは興味深いことですが、この素数アルゴリズムはSwiftのほうがまだ速いのです。
他の人によって言及されているが十分に呼び出されていない主な問題は、Swiftで-O3
がまったく何もしない(そして決して持たない)ため、それでコンパイルすると、最適化されない(-Onone
)。
オプション名は時間とともに変化しているため、他の回答にはビルドオプションの古いフラグが付いています。現在の正しいオプション(Swift 2.2)は次のとおりです。
-Onone // Debug - slow
-O // Optimised
-O -whole-module-optimization //Optimised across files
モジュール全体の最適化ではコンパイルが遅くなりますが、モジュール内のファイル間、つまり各フレームワーク内および実際のアプリケーションコード内でファイル間で最適化できますが、ファイル間では最適化できません。これは、パフォーマンスに重大な影響がある場合に使用する必要があります)
安全性チェックを無効にしてさらに高速化することもできますが、すべてのアサーションと前提条件を無効にするだけでなく、それらが正しいことに基づいて最適化します。アサーションにヒットした場合、これは未定義の動作にいることを意味します。 (テストによって)スピードブーストが価値があると判断した場合にのみ、細心の注意を払って使用してください。一部のコードにとって価値があると思う場合は、そのコードを別のフレームワークに分離し、そのモジュールの安全性チェックのみを無効にすることをお勧めします。
func partition(inout list : [Int], low: Int, high : Int) -> Int {
let pivot = list[high]
var j = low
var i = j - 1
while j < high {
if list[j] <= pivot{
i += 1
(list[i], list[j]) = (list[j], list[i])
}
j += 1
}
(list[i+1], list[high]) = (list[high], list[i+1])
return i+1
}
func quikcSort(inout list : [Int] , low : Int , high : Int) {
if low < high {
let pIndex = partition(&list, low: low, high: high)
quikcSort(&list, low: low, high: pIndex-1)
quikcSort(&list, low: pIndex + 1, high: high)
}
}
var list = [7,3,15,10,0,8,2,4]
quikcSort(&list, low: 0, high: list.count-1)
var list2 = [ 10, 0, 3, 9, 2, 14, 26, 27, 1, 5, 8, -1, 8 ]
quikcSort(&list2, low: 0, high: list2.count-1)
var list3 = [1,3,9,8,2,7,5]
quikcSort(&list3, low: 0, high: list3.count-1)
クイックソートについての私のブログです - Githubサンプルクイックソート
Lomutoのパーティショニングアルゴリズムについては、リストのパーティショニングをご覧ください。 Swiftで書かれて
Swift 4.1 は新しい-Osize
最適化モードを導入します。
Swift 4.1では、コンパイラは新しい最適化モードをサポートしています。これにより、専用の最適化によってコードサイズを削減できます。
Swiftコンパイラには強力な最適化機能があります。 -Oでコンパイルすると、コンパイラはコードが最大のパフォーマンスで実行されるようにコードを変換しようとします。ただし、このランタイムパフォーマンスの向上には、コードサイズの増加とのトレードオフが伴うことがあります。新しい-Osize最適化モードでは、ユーザーは最大速度ではなく最小コードサイズでコンパイルすることを選択できます。
コマンドラインでサイズ最適化モードを有効にするには、-Oの代わりに-Osizeを使用します。