Swift Beta performance: การเรียงลำดับอาร์เรย์


929

ฉันใช้อัลกอริทึมใน 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 ใช้เวลา6sถ้าฉันรวบรวมมันด้วยคำสั่งต่อไปนี้:

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

และมันใช้เวลามากถึง88 ปีถ้าฉันรวบรวมมันด้วยคำสั่งต่อไปนี้:

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

การกำหนดเวลาใน Xcode ด้วยบิลด์ "Release" vs. "Debug" จะคล้ายกัน

เกิดอะไรขึ้นที่นี่? ฉันเข้าใจการสูญเสียประสิทธิภาพบ้างเมื่อเปรียบเทียบกับ C ++ แต่ไม่ใช่การชะลอตัว 10 เท่าเมื่อเปรียบเทียบกับ Python บริสุทธิ์


แก้ไข:สภาพอากาศสังเกตว่าการเปลี่ยน-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 ได้อย่างไรโดยไม่สูญเสียตาข่ายนิรภัย?


แก้ไข 2:ฉันทำการเปรียบเทียบมากกว่านี้โดยมีลูปง่าย ๆ ตามแนวของ

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

(นี่คือการดำเนินการของ xor ที่นั่นเพื่อให้ฉันสามารถค้นหาลูปที่เกี่ยวข้องได้ง่ายขึ้นในรหัสแอสเซมบลีฉันพยายามเลือกการดำเนินการที่ง่ายต่อการมองเห็น แต่ยัง "ไม่เป็นอันตราย" ในแง่ที่ว่า ถึงจำนวนเต็มล้น)

อีกครั้งมีความแตกต่างกันมากในการทำงานระหว่างและ-O3 -Ofastดังนั้นฉันได้ดูรหัสการประกอบ:

  • ด้วย-Ofastสิ่งที่ฉันคาดหวัง ส่วนที่เกี่ยวข้องคือลูปที่มี 5 คำแนะนำภาษาเครื่อง

  • เมื่อ-O3ฉันได้รับบางสิ่งที่เกินจินตนาการที่สุดของฉัน วงในมีช่วงยาว 88 บรรทัดของรหัสชุดประกอบ ฉันไม่ได้พยายามทำความเข้าใจทั้งหมด แต่ส่วนที่น่าสงสัยที่สุดคือการเรียก 13 รายการของ "callq _swift_retain" และอีก 13 การเรียกร้องของ "callq _swift_release" นั่นคือการเรียกรูทีนย่อย 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 สูญเสียปัจจัยเกือบ 500 เมื่อเปรียบเทียบกับ -Ofast:

  • C ++ -O3: 0.05 วิ
  • C ++ -O0: 0.4 วิ
  • Java: 0.2 วิ
  • Python กับ PyPy: 0.5 วิ
  • Python: 12 วิ
  • รวดเร็ว - เร็ว: 0.05 วิ
  • Swift -O3: 23 s
  • สวิฟท์ -O0: 443 วิ

(หากคุณกังวลว่าคอมไพเลอร์อาจปรับให้เหมาะสมกับลูปที่ไม่มีจุดหมายทั้งหมดคุณสามารถเปลี่ยนเป็นx[i] ^= x[j]และเพิ่มคำสั่งการพิมพ์ที่ส่งออกx[0]ซึ่งไม่ได้เปลี่ยนแปลงอะไรเลยการกำหนดเวลาจะคล้ายกันมาก)

และใช่ที่นี่การใช้งาน Python เป็นการใช้งาน Python บริสุทธิ์ที่มีรายชื่อของ ints และซ้อนสำหรับลูป มันควรจะเป็นมากช้ากว่าไม่ได้เพิ่มประสิทธิภาพสวิฟท์ ดูเหมือนว่ามีอะไรบางอย่างแตกหักอย่างรุนแรงด้วย Swift และการทำดัชนีอาร์เรย์


แก้ไข 4:ปัญหาเหล่านี้ (รวมถึงปัญหาด้านประสิทธิภาพอื่น ๆ ) ดูเหมือนจะได้รับการแก้ไขใน Xcode 6 เบต้า 5

สำหรับการเรียงลำดับฉันมีเวลาต่อไปนี้:

  • เสียงดังกราว ++ -O3: 0.06 วิ
  • swiftc - รวดเร็ว: 0.1 วิ
  • swiftc -O: 0.1 วิ
  • swiftc: 4 วิ

สำหรับลูปซ้อนกัน:

  • เสียงดังกราว ++ -O3: 0.06 วิ
  • swiftc - รวดเร็ว: 0.3 วิ
  • swiftc -O: 0.4 วิ
  • swiftc: 540 วิ

ดูเหมือนว่าไม่มีเหตุผลอีกต่อไปที่จะใช้สิ่งที่ไม่ปลอดภัย-Ofast(aka -Ounchecked); ล้วน-Oผลิตรหัสที่ดีอย่างเท่าเทียมกัน


20
นี่คือคำถาม "Swift 100 ครั้งช้ากว่า C" อีกครั้ง: stackoverflow.com/questions/24102609/…
Jukka Suomela

16
และนี่คือการอภิปรายเกี่ยวกับสื่อการตลาดของ Apple ที่เกี่ยวข้องกับการเรียงลำดับที่ดีของ Swift: programmers.stackexchange.com/q/242816/913
Jukka Suomela

2
xcrun --sdk macosx swift -O3คุณสามารถรวบรวมด้วย: มันสั้นกว่า
ต้อนรับภาคใต้

3
ลิงค์นี้จะแสดงการดำเนินงานขั้นพื้นฐานอื่น ๆ เมื่อเปรียบเทียบกับ Objective-C
ทุ่ง

4
ด้วย Beta 5 มีการปรับปรุงความเร็วของ Swift อย่างมาก - ดูบทความนี้โดย Jesse Squiresเพื่อดูรายละเอียดเพิ่มเติม
Nate Cook

คำตอบ:


460

tl; dr Swift 1.0 เร็วที่สุดเท่าที่ C ตามเกณฑ์มาตรฐานนี้โดยใช้ระดับการปรับให้เหมาะสมของรีลีสเริ่มต้น [-O]


นี่คือ quicksort แบบแทนที่ใน 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.

เวลาเป็นวินาทีด้วย[-one]สำหรับn = 10_000 :

Swift:            0.895296452
C:                0.001223848

นี่คือการจัดเรียง builtin ของ Swift () สำหรับn = 10_000 :

Swift_builtin:    0.77865783

นี่คือ[-O]สำหรับn = 10_000 :

Swift:            0.045478346
C:                0.000784666
Swift_builtin:    0.032513488

อย่างที่คุณเห็นประสิทธิภาพของ Swift ได้รับการปรับปรุงโดยปัจจัย 20

ตามคำตอบของผู้ที่ mweathersการตั้งค่า[- เร็ว]สร้างความแตกต่างที่แท้จริงส่งผลให้ในเวลานี้สำหรับ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 ที่ไม่มีการเพิ่มประสิทธิภาพจึงช้ากว่า 1,000 เท่าในเกณฑ์มาตรฐานนี้ในขั้นตอนนี้ในการพัฒนา ในขณะที่คอมไพเลอร์ทั้งคู่ตั้งค่าเป็น [-Ofast] Swift ดำเนินการอย่างน้อยเช่นกันหากไม่ดีกว่า C เล็กน้อย

มีการชี้ให้เห็นว่า [- เร็ว] เปลี่ยนความหมายของภาษาทำให้ไม่ปลอดภัย นี่คือสิ่งที่ Apple ระบุไว้ในบันทึกย่อประจำรุ่น Xcode 5.0:

ระดับการปรับให้เหมาะสมใหม่ - รวดเร็วมีให้ใน LLVM เปิดใช้งานการปรับให้เหมาะสมที่สุด - เร็วผ่อนคลายข้อ จำกัด บางอย่างซึ่งส่วนใหญ่สำหรับการดำเนินการจุดลอยตัวที่มีความปลอดภัยสำหรับรหัสมากที่สุด มันสามารถให้ผลลัพธ์ที่มีประสิทธิภาพสูงอย่างมีนัยสำคัญจากคอมไพเลอร์

พวกเขาทั้งหมด แต่สนับสนุนมัน ไม่ว่าจะฉลาดหรือไม่ฉันไม่สามารถพูดได้ แต่จากสิ่งที่ฉันสามารถบอกได้ว่ามันสมเหตุสมผลพอที่จะใช้ [- เร็ว] ในการเปิดตัวหากคุณไม่ได้ทำการคำนวณเลขทศนิยมที่มีความแม่นยำสูงและคุณมั่นใจว่าไม่มีเลขจำนวนเต็มหรือ อาร์เรย์มากเกินความเป็นไปได้ในโปรแกรมของคุณ หากคุณต้องการประสิทธิภาพสูงและตรวจสอบโอเวอร์โฟลว์ / คณิตศาสตร์ที่แม่นยำแล้วเลือกภาษาอื่นสำหรับตอนนี้

การปรับปรุงเบต้า 3:

n = 10_000ด้วย[-O] :

Swift:            0.019697268
C:                0.000718064
Swift_sort:       0.002094721

Swift โดยทั่วไปเร็วขึ้นเล็กน้อยและดูเหมือนว่าการเรียงลำดับในตัวของ Swift มีการเปลี่ยนแปลงค่อนข้างมาก

การปรับปรุงครั้งสุดท้าย:

[- คนเดียว] :

Swift:   0.678056695
C:       0.000973914

[-O] :

Swift:   0.001158492
C:       0.001192406

[- ตรวจสอบแล้ว] :

Swift:   0.000827764
C:       0.001078914

25
การใช้ -emit-sil เพื่อส่งออกรหัส SIL ระดับกลางจะแสดงสิ่งที่ถูกเก็บไว้ (argh, การล้นสแต็คทำให้การฟอร์แมตเป็นไปไม่ได้) มันเป็นวัตถุบัฟเฟอร์ภายในในอาเรย์ นี่ดูเหมือนจะเป็นจุดบกพร่องของเครื่องมือเพิ่มประสิทธิภาพเครื่องมือเพิ่มประสิทธิภาพ ARC ควรจะสามารถเอาออกโดยไม่ต้อง - รวดเร็ว
Catfish_Man

เพียงแค่ไม่เห็นด้วยที่เราจะต้องใช้ภาษาอื่นหากต้องการใช้การเพิ่มประสิทธิภาพ Ofast มันจะต้องจัดการในทำนองเดียวกันกับคำถามของการตรวจสอบขอบเขตและปัญหาเล็กน้อยอื่น ๆ หากเลือกภาษาอื่นเช่น C. สวิฟท์นั้นเจ๋งอย่างแม่นยำเพราะมันจะปลอดภัยโดยค่าเริ่มต้นและทางเลือกรวดเร็วและไม่ปลอดภัยหากจำเป็น วิธีนี้ช่วยให้โปรแกรมเมอร์สามารถดีบักโค้ดของคุณได้เช่นกันเพื่อให้แน่ใจว่าทุกอย่างโอเคและคอมไพล์โดยใช้ Ofast ความเป็นไปได้ของการใช้มาตรฐานที่ทันสมัยและยังมีพลังของภาษา "ไม่ปลอดภัย" เช่น C นั้นยอดเยี่ยมมาก
Wallacy

2
หากคุณสามารถบอกฉันว่ามันอาจไม่ถูกต้องโปรดทำ ฉันชอบที่จะเรียนรู้เพิ่มเติมเสมอ
Joseph Mark

3
ทำการอัปเดตครั้งสุดท้ายตอนนี้ Swift เร็วเท่ากับ C ตามเกณฑ์มาตรฐานนี้โดยใช้การเพิ่มประสิทธิภาพมาตรฐาน
โจเซฟมาร์ค

4
คำแนะนำ: ทั้งการใช้งาน Swift และ C ของคุณของ quicksort นั้นสามารถปรับปรุงได้หากคุณทำการคืนเงินในพาร์ติชั่นที่เล็กที่สุดก่อน! (แทนการเรียกซ้ำบนพาร์ติชันด้านซ้ายก่อนเสมอ) Quicksort ถูกนำมาใช้กับการเลือกเดือยที่ง่ายที่สุดในกรณีที่เลวร้ายที่สุดใช้เวลา O (n ^ 2) แต่ในกรณีที่เลวร้ายที่สุดนี้คุณต้องใช้พื้นที่สแต็ค O (log n) เท่านั้น บนพาร์ติชันที่เล็กกว่าก่อน
Macneil Shonle

108

TL; DR : ใช่การดำเนินงานภาษาเดียวที่สวิฟท์ช้าในขณะนี้ หากคุณต้องการรหัสที่รวดเร็วตัวเลข (และรหัสประเภทอื่น ๆ น่าจะเป็นไปได้) ให้ไปกับรหัสอื่น ในอนาคตคุณควรประเมินทางเลือกของคุณอีกครั้ง มันอาจจะดีพอสำหรับรหัสแอปพลิเคชันส่วนใหญ่ที่เขียนในระดับที่สูงกว่า

จากสิ่งที่ฉันเห็นใน SIL และ LLVM IR ดูเหมือนว่าพวกเขาต้องการการเพิ่มประสิทธิภาพจำนวนมากสำหรับการลบโพสต์และการเผยแพร่ซึ่งอาจนำไปใช้ในClang (สำหรับ Objective-C) แต่พวกเขายังไม่ได้แจ้งพวกเขา นั่นคือทฤษฎีที่ฉันใช้ (ตอนนี้…ฉันยังต้องยืนยันว่า Clang ทำอะไรเกี่ยวกับมัน) เนื่องจาก profiler ทำงานในกรณีทดสอบสุดท้ายของคำถามนี้ให้ผลลัพธ์ "สวย" นี้:

การทำโปรไฟล์เวลาบน -O3 การทำโปรไฟล์เวลาบน - รวดเร็ว

ดังที่ถูกกล่าวไว้โดยคนอื่น ๆ ว่า-Ofastไม่ปลอดภัยโดยสิ้นเชิงและเปลี่ยนความหมายของภาษา สำหรับฉันแล้วมันอยู่ในขั้นตอน“ หากคุณกำลังจะใช้สิ่งนั้นเพียงแค่ใช้ภาษาอื่น” ฉันจะประเมินตัวเลือกนั้นอีกครั้งในภายหลังหากมีการเปลี่ยนแปลง

-O3ทำให้เราเป็นกลุ่มswift_retainและswift_releaseเรียกว่าโดยสุจริตไม่ดูเหมือนพวกเขาควรจะมีตัวอย่างนี้ เครื่องมือเพิ่มประสิทธิภาพควรลบ (AFAICT) ส่วนใหญ่เนื่องจากมันรู้จักข้อมูลส่วนใหญ่เกี่ยวกับอาเรย์และรู้ว่ามันมีการอ้างอิงที่ดี (อย่างน้อย)

มันไม่ควรจะเปล่งออกมามากขึ้นเมื่อมันไม่ได้เรียกฟังก์ชั่นที่อาจปล่อยวัตถุ ฉันไม่คิดว่าตัวสร้างอาร์เรย์สามารถส่งคืนอาร์เรย์ที่มีขนาดเล็กกว่าที่ถูกถามซึ่งหมายความว่าเช็คจำนวนมากที่ถูกปล่อยออกมานั้นไร้ประโยชน์ นอกจากนี้ยังรู้ว่าจำนวนเต็มจะไม่เกิน 10k ดังนั้นการตรวจสอบมากเกินไปสามารถปรับให้เหมาะสม (ไม่ใช่เพราะ-Ofastความแปลก แต่เพราะความหมายของภาษา (ไม่มีอะไรเปลี่ยนแปลงที่ var และไม่สามารถเข้าถึงได้และเพิ่มมากถึง 10k ปลอดภัยสำหรับประเภทInt)

คอมไพเลอร์อาจไม่สามารถ unbox อาเรย์หรือองค์ประกอบอาเรย์เนื่องจากพวกมันกำลังถูกส่งผ่านไปsort()ซึ่งเป็นฟังก์ชั่นภายนอกและต้องได้รับการโต้เถียง สิ่งนี้จะทำให้เราต้องใช้Intค่าทางอ้อมซึ่งจะทำให้มันช้าลงเล็กน้อย สิ่งนี้สามารถเปลี่ยนแปลงได้หากsort()ฟังก์ชั่นทั่วไป (ไม่ได้อยู่ในวิธีการหลายวิธี) พร้อมใช้งานสำหรับคอมไพเลอร์และได้รับการอินไลน์

นี่เป็นภาษาใหม่มาก (สาธารณะ) และผ่านสิ่งที่ฉันคิดว่ามีการเปลี่ยนแปลงมากมายเนื่องจากมีคน (มาก) ที่เกี่ยวข้องกับภาษา Swift เพื่อขอคำติชมและพวกเขาทุกคนพูดว่าภาษายังไม่เสร็จและจะเปลี่ยนแปลง

รหัสที่ใช้:

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

PS: ฉันไม่ใช่ผู้เชี่ยวชาญเกี่ยวกับ Objective-C หรือสิ่งอำนวยความสะดวกทั้งหมดจาก Cocoa , Objective-C หรือ runtimes ที่รวดเร็ว ฉันอาจจะสมมติบางสิ่งที่ฉันไม่ได้เขียน


คอมไพเลอร์อาจไม่สามารถ unbox อาเรย์หรือองค์ประกอบอาเรย์ได้เนื่องจากพวกมันถูกส่งผ่านไปยัง sort () ซึ่งเป็นฟังก์ชั่นภายนอกและต้องได้รับอาร์กิวเมนต์ที่ต้องการ นั่นไม่ควรสำคัญกับคอมไพเลอร์ที่ค่อนข้างดี การส่งเมทาดาทา (ในตัวชี้ - 64 บิตมีหลายระดับ) เกี่ยวกับข้อมูลจริงและการแยกในฟังก์ชันที่เรียกว่า
bestsss

3
อะไรทำให้-Ofast"ไม่ปลอดภัยทั้งหมด" สมมติว่าคุณรู้วิธีทดสอบโค้ดของคุณและตัดการโอเวอร์โฟลว์
Joseph Mark

@sjeohp: จริง ๆ แล้วสมมติว่ามีอะไรมากมาย :-) การตรวจสอบรหัสและการพิจารณาว่าโอเวอร์โฟลว์นั้นทำได้ยาก จากประสบการณ์ของผม (ฉันทำผลงานคอมไพเลอร์และมีการตรวจสอบ codebases ใหญ่บาง) และสิ่งที่ผมเคยได้ยินจากคนที่ทำผลงานคอมไพเลอร์ใน บริษัท ขนาดใหญ่ได้รับล้นและอื่น ๆ ที่ไม่ได้กำหนดพฤติกรรมที่เหมาะสมเป็นอย่างหนัก แม้แต่คำแนะนำของ Apple (เพียงแค่ตัวอย่าง) ในการแก้ไข UB นั้นผิดบางครั้ง ( randomascii.wordpress.com/2014/04/17/ … ) -Ofastเปลี่ยนความหมายของภาษาด้วย แต่ฉันไม่สามารถให้เงินกับเอกสารใด ๆ ได้ คุณมั่นใจได้อย่างไรว่าคุณกำลังทำอะไรอยู่
filcab

@bestsss: เป็นไปได้ แต่อาจไม่มีประโยชน์ เพิ่มการตรวจสอบทุกการเข้าถึง Int [] ขึ้นอยู่กับว่าอาร์เรย์ของ Int และชนิดดั้งเดิมอื่น ๆ (คุณมีอย่างน้อย 3 บิต) มีการใช้งานจำนวนมาก (โดยเฉพาะอย่างยิ่งเมื่อคุณสามารถลดลงถึง C หากคุณต้องการ) นอกจากนี้ยังใช้บิตบางอย่างที่พวกเขาอาจต้องการใช้หากในที่สุดพวกเขาต้องการเพิ่ม non-ARC GC มันไม่ได้ปรับให้เป็นยาชื่อสามัญที่มีมากกว่าหนึ่งอาร์กิวเมนต์เช่นกัน เนื่องจากพวกเขามีทุกประเภทมันจะง่ายกว่ามากที่จะชำนาญรหัสทั้งหมดที่แตะ Int [] (แต่ไม่ใช่ Int? []) เพื่อใช้ Int แบบอินไลน์ แต่คุณก็มี Obj-C interop มาให้ด้วย
filcab

@filcab ไม่ใช่ ARC (เช่นของจริง) GC จะมีประโยชน์จริง ๆ แต่พวกเขาต้องการบางสิ่งที่ไม่เข้ากันได้กับ C หากพวกเขาต้องการ GC พร้อมกันอย่างแท้จริงไม่ใช่ STW ฉันไม่ต้องกังวลเกี่ยวกับ 'การเข้าถึงทุกครั้งInt[]' เนื่องจากขึ้นอยู่กับระดับที่คอมไพเลอร์สามารถอินไลน์และมันควรจะสามารถอินไลน์ลูปแน่นด้วย / หลังจากคำแนะนำบางอย่าง
bestsss

53

ฉันตัดสินใจที่จะดูสิ่งนี้เพื่อความสนุกสนานและนี่คือเวลาที่ฉันได้รับ:

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

ดูเหมือนว่าจะมีการถดถอยของประสิทธิภาพจาก 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

สวิฟท์ 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;
}

ผล:

Apple Clang 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 นั้นรวดเร็ว แต่ยังไม่เร็วเท่ากับการเรียงลำดับของ C ++ เมื่อถูกคอมไพล์ด้วย-Oคอมไพเลอร์และไลบรารีด้านบน ด้วย-Ouncheckedดูเหมือนว่าจะเร็วเท่ากับ C ++ ใน Swift 4.0.2 และ Apple LLVM 9.0.0


2
ในความเป็นจริงคุณไม่ควรเรียกเวกเตอร์ :: Reserve ()ก่อนใส่องค์ประกอบสิบล้านชิ้น
BJovke

บางที! ขณะนี้มีการเรียงลำดับเวลาเท่านั้น
เรียนรู้ OpenGL ES

34

จาก The Swift Programming Language :

ไลบรารีมาตรฐานของ Sort Function Swift มีฟังก์ชันที่เรียกว่า sort ซึ่งเรียงลำดับอาร์เรย์ของค่าของชนิดที่รู้จักตามการแสดงผลของการปิดการเรียงลำดับที่คุณให้ไว้ เมื่อเสร็จสิ้นกระบวนการเรียงลำดับแล้วฟังก์ชัน sort จะส่งคืนอาร์เรย์ใหม่ที่มีขนาดและประเภทเดียวกันกับชุดเก่าพร้อมองค์ประกอบในลำดับการเรียงที่ถูกต้อง

sortฟังก์ชั่นมีสองประกาศ

การประกาศค่าเริ่มต้นซึ่งช่วยให้คุณระบุการปิดการเปรียบเทียบ:

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

และการประกาศครั้งที่สองที่ใช้เพียงพารามิเตอร์เดียว (อาเรย์) และเป็น "hardcoded เพื่อใช้ตัวเปรียบเทียบน้อยกว่า"

func sort<T : Comparable>(array: T[]) -> T[]

Example:
sort( _arrayToSort_ ) { $0 > $1 }

ฉันทดสอบโค้ดที่ดัดแปลงแล้วของคุณในสนามเด็กเล่นโดยมีการปิดเพิ่มเพื่อให้ฉันสามารถตรวจสอบฟังก์ชั่นได้อย่างใกล้ชิดยิ่งขึ้นและฉันพบว่าเมื่อ n ตั้งค่าเป็น 1,000 การปิดจะถูกเรียกประมาณ 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 = 1,000 ฉันพบว่า

  1. quickSort () ถูกเรียกประมาณ 650 ครั้ง
  2. มีการแลกเปลี่ยนประมาณ 6,000 ครั้ง
  3. และมีการเปรียบเทียบประมาณ 10,000 รายการ

ดูเหมือนว่าวิธีการเรียงลำดับแบบบิวด์อินคือ (หรือใกล้เคียง) การเรียงลำดับแบบด่วนและช้ามาก ...


17
บางทีฉันผิดอย่างสมบูรณ์ แต่ตามen.wikipedia.org/wiki/Quicksortจำนวนเฉลี่ยของการเปรียบเทียบใน Quicksort 2*n*log(n)คือ นั่นคือการเปรียบเทียบ 13815 รายการสำหรับการเรียงลำดับ n = 1,000 องค์ประกอบดังนั้นหากฟังก์ชั่นการเปรียบเทียบเรียกว่าประมาณ 11,000 ครั้งซึ่งดูเหมือนจะไม่เลว
Martin R

6
Apple อ้างว่า "การจัดเรียงวัตถุที่ซับซ้อน" (ไม่ว่าจะเป็นอะไรก็ตาม) นั้นเร็วกว่า 3.9 เท่าใน Swython 3.9 เท่า ดังนั้นจึงไม่จำเป็นต้องค้นหา "ฟังก์ชั่นการเรียงลำดับที่ดีกว่า" - แต่สวิฟท์ยังอยู่ระหว่างการพัฒนา ...
Martin R

6
มันไม่อ้างถึงลอการิทึมธรรมชาติ
Martin R

24
log(n)สำหรับอัลกอริทึมที่ซับซ้อนตามอัตภาพหมายถึงบันทึกฐาน -2 เหตุผลที่ไม่ได้ระบุพื้นฐานก็คือกฎการเปลี่ยนแปลงของฐานสำหรับลอการิทึมจะแนะนำตัวคูณคงที่เท่านั้นซึ่งจะถูกทิ้งเพื่อจุดประสงค์ของสัญกรณ์ O
minuteman3

3
เกี่ยวกับการอภิปรายเกี่ยวกับลอการิทึมธรรมชาติ VS 2 ฐานลอการิทึม: คำสั่งได้อย่างแม่นยำจากหน้าวิกิพีเดียที่ค่าเฉลี่ยของจำนวนรถที่จำเป็นสำหรับองค์ประกอบ n C(n) = 2n ln n ≈ 1.39n log₂ nคือ สำหรับ n = 1,000 นี่จะให้ C (n) = 13815 และไม่ใช่ "สัญกรณ์ใหญ่ -O"
Martin R

18

ในฐานะของ Xcode 7 Fast, Whole Module Optimizationคุณสามารถเปิด ควรเพิ่มประสิทธิภาพของคุณทันที

ป้อนคำอธิบายรูปภาพที่นี่


12

Swift Array ปรับปรุงประสิทธิภาพอีกครั้ง:

ฉันเขียนมาตรฐานของตัวเองเปรียบเทียบ Swift กับ C / Objective-C เกณฑ์มาตรฐานของฉันคำนวณจำนวนเฉพาะ มันใช้อาร์เรย์ของหมายเลขเฉพาะก่อนหน้าเพื่อค้นหาปัจจัยสำคัญในผู้สมัครใหม่แต่ละคนดังนั้นจึงค่อนข้างเร็ว อย่างไรก็ตามมันมี TONS ของการอ่านอาเรย์และเขียนให้อาร์เรย์น้อยลง

เดิมทีฉันทำเกณฑ์มาตรฐานนี้กับ Swift 1.2 ฉันตัดสินใจที่จะอัปเดตโครงการและเรียกใช้กับ Swift 2.0

โครงการให้คุณเลือกระหว่างการใช้อาร์เรย์ปกติของ swift และการใช้บัฟเฟอร์หน่วยความจำที่ไม่ปลอดภัยของ Swift โดยใช้ซีแมนทิกส์ของอาร์เรย์

สำหรับ C / Objective-C คุณสามารถเลือกใช้ NSArrays หรืออาร์เรย์ C malloc'ed ก็ได้

ดูเหมือนว่าผลการทดสอบจะค่อนข้างคล้ายคลึงกับการเพิ่มประสิทธิภาพโค้ดที่เล็กที่สุด ([-0s]) หรือการเพิ่มประสิทธิภาพที่เร็วที่สุดก้าวร้าว ([-0fast])

ประสิทธิภาพของ Swift 2.0 นั้นยังคงแย่มากเมื่อปิดการปรับรหัสให้เหมาะสมในขณะที่ประสิทธิภาพของ C / Objective-C นั้นช้ากว่าปานกลางเท่านั้น

บรรทัดล่างคือการคำนวณตามอาเรย์ C malloc'd เป็นวิธีที่เร็วที่สุด

Swift พร้อมบัฟเฟอร์ที่ไม่ปลอดภัยใช้เวลาประมาณ 1.19X - 1.20X ยาวกว่าอาร์เรย์ C malloc'd เมื่อใช้การปรับรหัสให้เร็วที่สุดและเล็กที่สุด ความแตกต่างดูเหมือนน้อยกว่าเล็กน้อยเมื่อใช้การเพิ่มประสิทธิภาพที่รวดเร็วและก้าวร้าว (Swift ใช้เวลานานกว่า 1.18x ถึง 1.16x มากกว่า C.

หากคุณใช้อาร์เรย์ Swift ปกติความแตกต่างกับ C จะยิ่งใหญ่กว่าเล็กน้อย (Swift ใช้เวลานานกว่า 1.22 ถึง 1.23 อีกต่อไป)

อาเรย์ของ Swift แบบปกติคือ DRAMATICALLYเร็วกว่าใน Swift 1.2 / Xcode 6 ประสิทธิภาพของมันอยู่ใกล้กับอาเรย์ของบัฟเฟอร์ที่ไม่ปลอดภัยของ Swift ซึ่งการใช้บัฟเฟอร์หน่วยความจำที่ไม่ปลอดภัยนั้นดูเหมือนจะไม่คุ้มกับปัญหาอีกต่อไป

BTW, Objective-C NSArray มีประสิทธิภาพลดลง หากคุณกำลังจะใช้ออบเจ็กต์คอนเทนเนอร์ดั้งเดิมในทั้งสองภาษา Swift นั้นเร็วกว่าทางดราม่าอย่างมาก

คุณสามารถตรวจสอบโครงการของฉันใน github ที่SwiftPerformanceBenchmark

มันมี UI ที่เรียบง่ายที่ทำให้การเก็บสถิติง่ายมาก

เป็นที่น่าสนใจว่าการเรียงลำดับดูเหมือนจะเร็วกว่าใน Swift เล็กน้อยใน C ตอนนี้ แต่อัลกอริธึมหมายเลขเฉพาะนี้ยังคงเร็วกว่าใน Swift


8

ประเด็นหลักที่คนอื่นพูดถึง แต่ไม่ได้รับการเรียกร้องมากพอคือ-O3ไม่ทำอะไรเลยใน Swift (และไม่เคยมี) ดังนั้นเมื่อคอมไพล์ด้วยความที่มันไม่ได้มีประสิทธิภาพที่ดีที่สุด ( -Onone)

ชื่อตัวเลือกมีการเปลี่ยนแปลงเมื่อเวลาผ่านไปดังนั้นคำตอบอื่น ๆ จะมีค่าสถานะล้าสมัยสำหรับตัวเลือกการสร้าง ตัวเลือกปัจจุบันที่ถูกต้อง (Swift 2.2) คือ:

-Onone // Debug - slow
-O     // Optimised
-O -whole-module-optimization //Optimised across files

การออปติไมซ์โมดูลทั้งหมดมีการคอมไพล์ที่ช้าลง แต่สามารถออปติไมซ์ข้ามไฟล์ภายในโมดูลเช่นภายในแต่ละเฟรมเวิร์กและภายในโค้ดแอปพลิเคชันจริง แต่ไม่ใช่ระหว่างกัน คุณควรใช้สิ่งนี้เพื่อประสิทธิภาพที่สำคัญยิ่ง)

คุณสามารถปิดใช้งานการตรวจสอบความปลอดภัยเพื่อความเร็วที่มากขึ้น แต่ด้วยการยืนยันและเงื่อนไขเบื้องต้นทั้งหมดไม่เพียง แต่ปิดการใช้งาน แต่ปรับให้เหมาะสมบนพื้นฐานที่ถูกต้อง หากคุณเคยกดยืนยันซึ่งหมายความว่าคุณมีพฤติกรรมที่ไม่ได้กำหนด ใช้ด้วยความระมัดระวังอย่างยิ่งและเฉพาะในกรณีที่คุณพิจารณาว่าการเพิ่มความเร็วนั้นคุ้มค่าสำหรับคุณ (โดยการทดสอบ) หากคุณพบว่ามีประโยชน์สำหรับรหัสบางอย่างฉันขอแนะนำให้แยกรหัสนั้นออกเป็นกรอบงานที่แยกต่างหากและปิดใช้งานการตรวจสอบความปลอดภัยสำหรับโมดูลนั้นเท่านั้น


คำตอบนี้ล้าสมัยแล้ว ตั้งแต่ Swift 4.1 ตัวเลือกการปรับแต่งโมดูลทั้งหมดนั้นเป็นบูลีนแยกต่างหากที่สามารถใช้ร่วมกับการตั้งค่าอื่น ๆ ได้และขณะนี้มี -Os เพื่อปรับขนาดให้เหมาะสม ฉันอาจอัปเดตเมื่อฉันมีเวลาตรวจสอบสถานะตัวเลือกที่แน่นอน
โจเซฟลอร์ด

7
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 ได้ในการแบ่งพาร์ติชันรายการ เขียนด้วยความรวดเร็ว


4

Swift 4.1เปิดตัว-Osizeโหมดการเพิ่มประสิทธิภาพใหม่

ใน Swift 4.1 คอมไพเลอร์สนับสนุนโหมดการปรับแต่งใหม่ซึ่งเปิดใช้งานการปรับแต่งเฉพาะเพื่อลดขนาดรหัส

คอมไพเลอร์ Swift มาพร้อมกับการปรับแต่งที่มีประสิทธิภาพ เมื่อคอมไพล์ด้วย -O คอมไพเลอร์จะพยายามแปลงรหัสเพื่อให้มันทำงานด้วยประสิทธิภาพสูงสุด อย่างไรก็ตามการปรับปรุงประสิทธิภาพรันไทม์บางครั้งอาจมาพร้อมกับการลดขนาดของรหัสที่เพิ่มขึ้น ด้วยโหมดการปรับให้เหมาะสม -Osize ใหม่ผู้ใช้มีทางเลือกในการรวบรวมสำหรับขนาดรหัสที่น้อยที่สุดแทนที่จะเป็นความเร็วสูงสุด

หากต้องการเปิดใช้งานโหมดการปรับขนาดให้เหมาะสมบนบรรทัดคำสั่งให้ใช้ -Osize แทน -O

อ่านเพิ่มเติม: https://swift.org/blog/osize/

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.