programing

Swift Beta 퍼포먼스: 어레이 정렬

showcode 2023. 4. 20. 23:23
반응형

Swift Beta 퍼포먼스: 어레이 정렬

Swift Beta에서 알고리즘을 구현하고 있었는데 성능이 매우 저조하다는 것을 알게 되었습니다.자세히 살펴보니 병목 현상 중 하나가 어레이를 분류하는 것과 같은 간단한 문제라는 것을 깨달았습니다.관련 부품은 다음과 같습니다.

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.06초 걸립니다.

Python에서는 0.6초가 소요됩니다(트릭 없이 정수 목록에 y = 정렬(x)만).

Swift에서는 다음 명령어로 컴파일하면 6초 걸립니다.

xcrun swift -O3 -sdk `xcrun --show-sdk-path --sdk macosx`

그리고 다음 명령어로 컴파일하면 88초 정도 걸립니다.

xcrun swift -O0 -sdk `xcrun --show-sdk-path --sdk macosx`

"Release" 빌드와 "Debug" 빌드의 Xcode 타이밍은 비슷합니다.

여기 뭐가 잘못됐나요?C++와 비교하면 성능 저하를 알 수 있지만 순수 Python과 비교하면 10배 이상 느려지는 것은 아닙니다.


편집: 날씨 변화가 감지됨-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재빠르다물론 안전망이 성능에 어느 정도 영향을 미치긴 하지만 프로그램을 100배 느리게 만들어서는 안 된다.Java는 이미 어레이 경계를 확인하고 있으며, 일반적인 경우 속도가 2배 미만입니다.에는 「Clang」GCC가 .-ftrapv(서명된) 정수 오버플로우를 체크하기 위해 사용됩니다.또, 그리 느리지도 않습니다.

그렇기 때문에 어떻게 하면 안전망을 잃지 않고 Swift에서 합리적인 성능을 얻을 수 있을까요?


Edit 2: 벤치마킹을 몇 가지 더 실시했습니다.또한 매우 심플한 루프가

for i in 0..<n {
    x[i] = x[i] ^ 12345678
}

(여기에서는 조립 코드에서 관련 루프를 쉽게 찾을 수 있도록 xor 연산이 있습니다.검출하기 쉬우면서도 정수 오버플로와 관련된 체크는 불필요하다는 의미에서 '무해'한 조작을 선택하려고 했습니다.)

한 번, again again 、 again 、 again 、 again 、 again 、 again 、 again 、 again 、 again 、 again 、 again again 。-O3 ★★★★★★★★★★★★★★★★★」-Ofast그래서 조립 코드를 살펴봤습니다.

  • ★★★★★★★★★★★★★★★★ -Ofast내가 기대했던 것 거의 다 얻었어.해당 부분은 5개의 기계어 명령이 포함된 루프입니다.

  • ★★★★★★★★★★★★★★★★ -O3상상을 초월하는 걸 얻었어요내부 루프는 어셈블리 코드의 88줄에 걸쳐 있습니다.모든 것을 이해하려고 노력하지는 않았지만, 가장 의심스러운 부분은 "callq_swift_retain" 호출 13건과 "callq_swift_release" 호출 13건입니다., 내부 루프의 서브루틴 콜은 26개입니다.


편집 3: Ferruccio는 코멘트에서 임베디드 기능(예: 정렬)에 의존하지 않는다는 의미에서 공정한 벤치마크를 요구했습니다.저는 다음 프로그램이 꽤 좋은 예라고 생각합니다.

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배 정도 떨어집니다.

  • C++-O3: 0.05초
  • C++-O0: 0.4초
  • 자바: 0.2초
  • PyPy 탑재 Python : 0.5초
  • Python: 12초
  • Swift - Ofast : 0.05초
  • Swift -O3: 23초
  • Swift -O0: 443초

를 완전히 「(」로 할 수 ). x[i] ^= x[j]x[0]이렇게 해도 변경은 없습니다.

여기서 Python 실장은 ints 리스트와 루프용으로 중첩된 멍청한 순수 Python 실장이었습니다.최적화되지 않은 Swift보다 훨씬 느릴 것입니다.Swift와 어레이 인덱싱에 심각한 문제가 있는 것 같습니다.


편집 4: Xcode 6 베타 5에서는 이러한 문제(및 일부 다른 성능 문제)가 해결된 것 같습니다.

정렬을 위해 다음과 같은 타이밍이 지정되었습니다.

  • clang++-O3: 0.06초
  • swiftc - Ofast : 0.1초
  • swiftc - O : 0.1초
  • swiftc: 4초

네스트된 루프의 경우:

  • clang++-O3: 0.06초
  • swiftc - Ofast : 0.3초
  • swiftc - O: 0.4초
  • swiftc: 540초

안전하지 않은 것을 더 이상 사용할 이유가 없어 보인다.-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.

n=10_000에 대해 [-Onone]을 사용하는 시간(초):

Swift:            0.895296452
C:                0.001223848

다음은 n=10_000에 대한 Swift의 기본 제공 sort()입니다.

Swift_builtin:    0.77865783

다음은 n=10_000 대한 [-O]입니다.

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

비교를 위해 n=1_000_000에 대해 [-Onone]을 사용합니다.

Swift:            142.659763258
C:                0.162065333
Swift_sort:       114.095478272

따라서 Swift는 개발 단계에서 이 벤치마크에서 C보다 거의 1000배 느렸습니다.한편, 양쪽 컴파일러를 [-Ofast]로 설정했을 경우, Swift는 C보다 약간 낫지는 않더라도 적어도 같은 퍼포먼스를 발휘했습니다.

[-Ofast]는 언어의 의미론을 변화시켜 잠재적으로 안전하지 않게 만든다는 지적이 있습니다.Xcode 5.0 릴리즈 노트에 기재되어 있는 것은 다음과 같습니다.

LLVM에서 사용할 수 있는 새로운 최적화 수준 - Ofast는 공격적인 최적화를 가능하게 합니다. - Ofast는 대부분의 코드에 안전한 부동 소수점 연산에 대한 일부 보수적인 제한을 완화합니다.컴파일러로부터 큰 고성능을 얻을 수 있습니다.

그들은 거의 그것을 옹호한다.그것이 현명한지 아닌지는 말할 수 없지만, 내가 보기에 고정밀 부동 소수점 연산을 하지 않고 프로그램에서 정수나 배열 오버플로우가 불가능하다고 확신한다면 릴리스에서 [-Ofast]를 사용하는 것이 충분히 타당할 것 같습니다.하이 퍼포먼스와 오버플로우 체크/정확한 계산이 필요한 경우는, 우선 다른 언어를 선택해 주세요.

베타 3 업데이트:

n=10_000([-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이 이에 대해 뭔가 조치를 취하고 있는지 확인해야 합니다.

O3에서의 타임 프로파일링 시간 프로파일링 - Ofast

다른 많은 사람들이 말했듯이-Ofast전혀 안전하지 않고 언어 의미론도 변화합니다.저는 '그걸 쓰려면 다른 언어를 쓰세요'라는 단계예요.그 선택이 바뀌면 나중에 다시 평가할게요.

-O3 수북이 받다swift_retain ★★★★★★★★★★★★★★★★★」swift_release이 예에 있어서는 안 될 것 같은 전화입니다.옵티마이저는 어레이에 대한 대부분의 정보를 알고 있으며 어레이에 대한 (적어도) 강한 참조가 있음을 알고 있기 때문에 AFAICT를 생략해야 합니다.

오브젝트를 해방시킬 수 있는 함수를 호출하지 않을 때 더 많은 잔류물을 방출해서는 안 됩니다.어레이 컨스트럭터에서는 요청된 것보다 작은 어레이를 반환할 수 없다고 생각합니다.즉, 내보낸 많은 체크는 무용지물입니다.또, 정수가 10k를 넘지 않는 것을 알고 있기 때문에, 오버플로우 체크를 최적화할 수 있습니다(이것이 원인이 아닙니다).-Ofast 때문에( 수 , 합니다).Int를 참조해 주세요.

는 어레이나 엘리먼트가 「」로 에, 그 박스를 할 수 경우가 .sort()이는 외부 함수이며 예상되는 인수를 얻어야 합니다. 되면 ''를 할 것 같아요.Int간접적으로 값을 매기면 속도가 느려질 수 있습니다. 하다, 하다, 하다, 하다, 이렇게 되면 달라질 수 요.sort()범용 함수(멀티 멀티플렉스 방식 아님)를 컴파일러가 사용할 수 있게 되어 인라인을 이룹니다.

이것은 매우 새로운 언어이며, 많은 변화를 겪고 있다고 생각합니다.스위프트 언어에 관련된 사람들이 피드백을 요구하고 있고, 모두 언어가 완성되지 않았고 바뀔 것이라고 말하고 있기 때문입니다.

사용된 코드:

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")

추신: 저는 Objective-C에 대한 전문가도 아니고 코코아, 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()

결과:

스위프트 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

2.3. 것 , Swift 2.0에서 Swift 3.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★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

C++

#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의 , Swift를 C++로 했을 의 C.-O위의 컴파일러와 라이브러리를 사용합니다.★★★★★★★★★★★★★★★★ -OuncheckedSwift 4.0.2 'Apple LLVM 9.0.0' C++'입니다.

송신원:

Sort Function Swift의 표준 라이브러리는 사용자가 제공한 정렬 마감의 출력을 기준으로 알려진 유형의 값 배열을 정렬하는 sort라는 함수를 제공합니다.정렬 프로세스가 완료되면 정렬 함수는 이전 배열과 동일한 유형 및 크기의 새 배열을 올바른 정렬 순서로 반환합니다.

sort2번

비교 마감을 지정할 수 있는 기본 선언:

func sort<T>(array: T[], pred: (T, T) -> Bool) -> T[]

또한 단일 매개 변수(배열)만 사용하고 "보다 작은 비교기를 사용하도록 하드 코딩된" 두 번째 선언입니다.

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과 함께 사용하면

  1. quickSort()는 약 650회 호출되었습니다.
  2. 약 6000건의 교환이 이루어졌습니다.
  3. 그리고 약 10,000개의 비교가 있습니다.

내장된 정렬 방식은 빠른 정렬 방식인 것 같습니다.또한 매우 느립니다.

부터는 Xcode 7을 켤 수 .Fast, Whole Module Optimization그러면 성능이 즉시 향상됩니다.

여기에 이미지 설명 입력

Swift Array 퍼포먼스 재검토:

Swift와 C/Objective-C를 비교하여 나만의 벤치마크를 작성했습니다.내 벤치마크는 소수를 계산한다.이전 소수의 배열을 사용하여 각 새로운 후보에서 소수를 찾기 때문에 속도가 상당히 빠릅니다.그러나 어레이 판독은 수 톤으로, 어레이에의 기입은 적어집니다.

원래 이 벤치마크는 Swift 1.2에 대해 실시했습니다.프로젝트를 업데이트하여 Swift 2.0에 대해 실행하기로 했습니다.

이 프로젝트에서는 일반 Swift 어레이를 사용하는 것과 배열 의미론을 사용하는 Swift 안전하지 않은 메모리 버퍼를 사용하는 것 중 하나를 선택할 수 있습니다.

C/Objective-C의 경우 NSAray 또는 C malloc's 배열 중 하나를 사용할 수 있습니다.

테스트 결과는 가장 빠르고 가장 작은 코드 최적화([-0]) 또는 가장 빠르고 공격적인([-0fast]) 최적화와 거의 비슷합니다.

코드 최적화가 꺼진 상태에서도 Swift 2.0의 퍼포먼스는 여전히 나쁘지만 C/Objective-C의 퍼포먼스는 약간 느립니다.

결론은 C malloc'd 어레이 기반 계산이 가장 빠르다는 것입니다.

안전하지 않은 버퍼를 사용한 스위프트는 가장 빠르고 최소의 코드 최적화를 사용하는 경우 C malloc'd 어레이보다 약 1.19배~1.20배 더 오래 걸립니다.고속으로 적극적인 최적화를 실시하면 그 차이는 약간 작아집니다(Swift는 C보다 1.18배~1.16배 더 오래 걸립니다).

일반 Swift 어레이를 사용하는 경우 C와의 차이가 약간 커집니다.(스위프트는 1.22~1.23 더 오래 걸립니다.)

는 Swift입니다.DRAMATICALLYSwift 1.2/X코드 6이 되다.성능은 Swift 안전하지 않은 버퍼 기반 어레이에 매우 가깝기 때문에 안전하지 않은 메모리 버퍼를 사용하는 것은 더 이상 번거로운 일이 아닙니다.

그나저나, Objective-C NSArray 퍼포먼스는 형편없어네이티브 컨테이너 객체를 양쪽 언어로 사용하는 경우 Swift가 극적으로 더 빠릅니다.

Swift 성능 Benchmark에서 github 프로젝트를 확인할 수 있습니다.

간단한 UI를 통해 통계를 쉽게 수집할 수 있습니다.

흥미로운 점은 현재 C보다 Swift가 약간 빠른 것 같지만, 이 소수 알고리즘은 Swift가 여전히 빠르다는 것입니다.

언급되지 는 ''입니다.-O3Swift에서는 하지 않기 및동작하지 않기 때문에), 되지 않은Swift) 했을 (Swift)는 최적화되어 있지 않습니다(Swift).-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) 

이것은 Quick Sort에 관한 블로그입니다.Github 샘플 Quick-Sort

목록 파티션에서 Lomuto의 파티션 알고리즘을 볼 수 있습니다.Swift로 작성.

Swift 4.1은 새로운 기능을 탑재-Osize최적화 모드

Swift 4.1에서 컴파일러는 코드 크기를 줄이기 위해 전용 최적화를 가능하게 하는 새로운 최적화 모드를 지원합니다.

Swift 컴파일러는 강력한 최적화 기능을 갖추고 있습니다.컴파일러는 -O로 컴파일 할 때 최대한의 퍼포먼스로 실행할 수 있도록 코드를 변환하려고 합니다.그러나 런타임 성능의 이러한 향상으로 인해 코드 크기가 증가할 수 있습니다.새로운 -Osize 최적화 모드에서는 최대 속도가 아닌 최소 코드 크기로 컴파일할 수 있습니다.

명령줄에서 크기 최적화 모드를 사용하려면 -O 대신 -Osize를 사용합니다.

자세한 것은, https://swift.org/blog/osize/ 를 참조해 주세요.

언급URL : https://stackoverflow.com/questions/24101718/swift-beta-performance-sorting-arrays

반응형