Cái nào nhanh hơn: while (1) hay while (2)?

588
Nikole 2014-07-20 21:32.

Đây là một câu hỏi phỏng vấn được hỏi bởi một quản lý cấp cao.

Cái nào nhanh hơn?

while(1) {
    // Some code
}

hoặc là

while(2) {
    //Some code
}

Tôi đã nói rằng cả hai đều có cùng tốc độ thực thi, vì biểu thức bên trong whilecuối cùng sẽ đánh giá là truehoặc false. Trong trường hợp này, cả hai đều đánh giá truevà không có hướng dẫn điều kiện bổ sung bên trong whileđiều kiện. Vì vậy, cả hai sẽ có cùng tốc độ thực thi và tôi thích while (1) hơn.

Nhưng người phỏng vấn nói một cách tự tin: "Kiểm tra những điều cơ bản của bạn. Còn while(1)nhanh hơn while(2)." (Anh ấy không thử lòng tin của tôi)

Điều này có đúng không?

Xem thêm: “For (;;)” có nhanh hơn “while (TRUE)” không? Nếu không, tại sao mọi người sử dụng nó?

22 answers

684
ApproachingDarknessFish 2014-07-20 22:03.

Cả hai vòng đều là vô hạn, nhưng chúng ta có thể thấy cái nào cần nhiều hướng dẫn / tài nguyên hơn cho mỗi lần lặp.

Sử dụng gcc, tôi đã biên dịch hai chương trình sau để lắp ráp ở các mức độ tối ưu hóa khác nhau:

int main(void) {
    while(1) {}
    return 0;
}

int main(void) {
    while(2) {}
    return 0;
}

Ngay cả khi không có tối ưu hóa ( -O0), hợp ngữ được tạo ra giống hệt nhau cho cả hai chương trình . Do đó, không có sự khác biệt về tốc độ giữa hai vòng lặp.

Để tham khảo, đây là assembly được tạo (sử dụng gcc main.c -S -masm=intelvới cờ tối ưu hóa):

Với -O0:

    .file   "main.c"
    .intel_syntax noprefix
    .def    __main; .scl    2;  .type   32; .endef
    .text
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
    push    rbp
    .seh_pushreg    rbp
    mov rbp, rsp
    .seh_setframe   rbp, 0
    sub rsp, 32
    .seh_stackalloc 32
    .seh_endprologue
    call    __main
.L2:
    jmp .L2
    .seh_endproc
    .ident  "GCC: (tdm64-2) 4.8.1"

Với -O1:

    .file   "main.c"
    .intel_syntax noprefix
    .def    __main; .scl    2;  .type   32; .endef
    .text
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
    sub rsp, 40
    .seh_stackalloc 40
    .seh_endprologue
    call    __main
.L2:
    jmp .L2
    .seh_endproc
    .ident  "GCC: (tdm64-2) 4.8.1"

Với -O2-O3(cùng một đầu ra):

    .file   "main.c"
    .intel_syntax noprefix
    .def    __main; .scl    2;  .type   32; .endef
    .section    .text.startup,"x"
    .p2align 4,,15
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
    sub rsp, 40
    .seh_stackalloc 40
    .seh_endprologue
    call    __main
.L2:
    jmp .L2
    .seh_endproc
    .ident  "GCC: (tdm64-2) 4.8.1"

Trên thực tế, hợp ngữ được tạo cho vòng lặp giống hệt nhau cho mọi cấp độ tối ưu hóa:

 .L2:
    jmp .L2
    .seh_endproc
    .ident  "GCC: (tdm64-2) 4.8.1"

Các bit quan trọng là:

.L2:
    jmp .L2

Tôi không thể đọc hợp ngữ rất tốt, nhưng đây rõ ràng là một vòng lặp vô điều kiện. Lệnh này jmpsẽ đặt lại chương trình một cách vô điều kiện về .L2nhãn mà không cần so sánh giá trị với true, và tất nhiên ngay lập tức làm như vậy một lần nữa cho đến khi chương trình kết thúc bằng cách nào đó. Điều này trực tiếp tương ứng với mã C / C ++:

L2:
    goto L2;

Biên tập:

Điều thú vị là, ngay cả khi không có tối ưu hóa , tất cả các vòng sau đều tạo ra cùng một đầu ra chính xác (vô điều kiện jmp) trong quá trình lắp ráp:

while(42) {}

while(1==1) {}

while(2==2) {}

while(4<7) {}

while(3==3 && 4==4) {}

while(8-9 < 0) {}

while(4.3 * 3e4 >= 2 << 6) {}

while(-0.1 + 02) {}

Và ngay cả với sự ngạc nhiên của tôi:

#include<math.h>

while(sqrt(7)) {}

while(hypot(3,4)) {}

Mọi thứ trở nên thú vị hơn một chút với các chức năng do người dùng xác định:

int x(void) {
    return 1;
}

while(x()) {}

#include<math.h>

double x(void) {
    return sqrt(7);
}

while(x()) {}

Tại -O0, hai ví dụ này thực sự gọi xvà thực hiện so sánh cho mỗi lần lặp.

Ví dụ đầu tiên (trả về 1):

.L4:
    call    x
    testl   %eax, %eax
    jne .L4
    movl    $0, %eax
    addq    $32, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .ident  "GCC: (tdm64-2) 4.8.1"

Ví dụ thứ hai (quay lại sqrt(7)):

.L4:
    call    x
    xorpd   %xmm1, %xmm1
    ucomisd %xmm1, %xmm0
    jp  .L4
    xorpd   %xmm1, %xmm1
    ucomisd %xmm1, %xmm0
    jne .L4
    movl    $0, %eax
    addq    $32, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .ident  "GCC: (tdm64-2) 4.8.1"

Tuy nhiên, ở cấp độ -O1và ở trên, cả hai đều tạo ra một lắp ráp giống như các ví dụ trước đó ( jmpquay trở lại nhãn trước đó một cách vô điều kiện ).

TL; DR

Theo GCC, các vòng lặp khác nhau được biên dịch thành tập hợp giống hệt nhau. Trình biên dịch đánh giá các giá trị không đổi và không bận tâm thực hiện bất kỳ so sánh thực tế nào.

Đạo đức của câu chuyện là:

  • Tồn tại một lớp biên dịch giữa mã nguồn C ++ và các lệnh CPU, và lớp này có ý nghĩa quan trọng đối với hiệu suất.
  • Do đó, hiệu suất không thể được đánh giá bằng cách chỉ nhìn vào mã nguồn.
  • Trình biên dịch phải đủ thông minh để tối ưu hóa các trường hợp nhỏ nhặt như vậy. Các lập trình viên không nên lãng phí thời gian suy nghĩ về chúng trong phần lớn các trường hợp.
282
Chris Culter 2014-07-22 19:51.

Vâng, while(1)là nhanh hơn nhiều while(2), cho một con người để đọc! Nếu tôi thấy while(1)trong một cơ sở mã không quen thuộc, tôi ngay lập tức biết tác giả dự định gì và nhãn cầu của tôi có thể tiếp tục đến dòng tiếp theo.

Nếu tôi thấy while(2), có lẽ tôi sẽ dừng lại và cố gắng tìm ra lý do tại sao tác giả không viết while(1). Có phải ngón tay của tác giả đã trượt trên bàn phím? Những người bảo trì cơ sở mã này có sử dụng while(n)như một cơ chế nhận xét khó hiểu để làm cho các vòng lặp trông khác không? Đó có phải là một giải pháp thô sơ cho một cảnh báo giả trong một số công cụ phân tích tĩnh bị hỏng không? Hay đây là manh mối cho thấy tôi đang đọc mã được tạo? Đó có phải là một lỗi do tìm-và-thay-thế-tất-cả không được khuyên dùng, hay một sự hợp nhất không tốt, hay một tia vũ trụ? Có thể dòng mã này được cho là làm một điều gì đó khác biệt đáng kể. Có lẽ nó được cho là để đọc while(w)hoặc while(x2). Tốt hơn là tôi nên tìm tác giả trong lịch sử của tệp và gửi cho họ một email "WTF" ... và bây giờ tôi đã phá vỡ bối cảnh tinh thần của mình. Việc này while(2)có thể ngốn vài phút thời gian của tôi, có khi while(1)chỉ mất một phần giây!

Tôi đang phóng đại, nhưng chỉ một chút thôi. Khả năng đọc mã thực sự quan trọng. Và đó là điều đáng nói trong một cuộc phỏng vấn!

152
Keith Thompson 2014-07-21 14:35.

Các câu trả lời hiện có hiển thị mã được tạo bởi một trình biên dịch cụ thể cho một mục tiêu cụ thể với một bộ tùy chọn cụ thể không trả lời đầy đủ câu hỏi - trừ khi câu hỏi được hỏi trong ngữ cảnh cụ thể đó ("Cách nào nhanh hơn bằng cách sử dụng gcc 4.7.2 cho x86_64 với các tùy chọn mặc định? ", chẳng hạn).

Theo như định nghĩa ngôn ngữ có liên quan, trong máy trừu tượng while (1) đánh giá hằng số nguyên 1while (2)đánh giá hằng số nguyên 2; trong cả hai trường hợp, kết quả được so sánh bằng 0. Tiêu chuẩn ngôn ngữ hoàn toàn không nói gì về hiệu suất tương đối của hai cấu trúc.

Tôi có thể tưởng tượng rằng một trình biên dịch cực kỳ ngây thơ có thể tạo mã máy khác nhau cho hai biểu mẫu, ít nhất là khi được biên dịch mà không yêu cầu tối ưu hóa.

Mặt khác, trình biên dịch C hoàn toàn phải đánh giá một số biểu thức hằng số tại thời điểm biên dịch, khi chúng xuất hiện trong các ngữ cảnh yêu cầu biểu thức hằng số. Ví dụ, điều này:

int n = 4;
switch (n) {
    case 2+2: break;
    case 4:   break;
}

yêu cầu chẩn đoán; trình biên dịch lười biếng không có tùy chọn trì hoãn đánh giá 2+2cho đến thời gian thực thi. Vì một trình biên dịch phải có khả năng đánh giá các biểu thức không đổi tại thời điểm biên dịch, không có lý do chính đáng để nó không tận dụng khả năng đó ngay cả khi nó không được yêu cầu.

Tiêu chuẩn C ( N1570 6.8.5p4) nói rằng

Một câu lệnh lặp làm cho một câu lệnh được gọi là phần thân của vòng lặp được thực thi lặp đi lặp lại cho đến khi biểu thức điều khiển so sánh bằng 0.

Vì vậy, các biểu thức hằng số có liên quan là 1 == 02 == 0, cả hai đều được đánh giá theo intgiá trị 0. (Những so sánh này được ngầm hiểu trong ngữ nghĩa của whilevòng lặp; chúng không tồn tại dưới dạng biểu thức C. thực tế.)

Một trình biên dịch ngây thơ có thể tạo ra mã khác nhau cho hai cấu trúc. Ví dụ: đối với lần đầu tiên, nó có thể tạo ra một vòng lặp vô hạn không điều kiện (coi 1như một trường hợp đặc biệt) và đối với lần thứ hai, nó có thể tạo ra một so sánh thời gian chạy rõ ràng tương đương với 2 != 0. Nhưng tôi chưa bao giờ gặp một trình biên dịch C thực sự sẽ hoạt động theo cách đó và tôi thực sự nghi ngờ rằng một trình biên dịch như vậy tồn tại.

Hầu hết các trình biên dịch (tôi muốn nói rằng tất cả các trình biên dịch chất lượng sản xuất) đều có các tùy chọn để yêu cầu tối ưu hóa bổ sung. Theo tùy chọn như vậy, thậm chí ít có khả năng bất kỳ trình biên dịch nào sẽ tạo mã khác nhau cho hai biểu mẫu.

Nếu trình biên dịch của bạn tạo mã khác nhau cho hai cấu trúc, trước tiên hãy kiểm tra xem các chuỗi mã khác nhau có thực sự có hiệu suất khác nhau hay không. Nếu có, hãy thử biên dịch lại với một tùy chọn tối ưu hóa (nếu có). Nếu chúng vẫn khác nhau, hãy gửi báo cáo lỗi cho nhà cung cấp trình biên dịch. Nó không (nhất thiết) là một lỗi theo nghĩa không tuân theo tiêu chuẩn C, nhưng gần như chắc chắn đó là một vấn đề cần được sửa chữa.

Điểm mấu chốt: while (1)while(2) gần như chắc chắn có cùng hiệu suất. Chúng có ngữ nghĩa hoàn toàn giống nhau và không có lý do chính đáng nào để bất kỳ trình biên dịch nào không tạo mã giống hệt nhau.

Và mặc dù nó hoàn toàn hợp pháp cho một trình biên dịch để tạo ra nhanh hơn mã cho while(1)hơn cho while(2), đó là bình đẳng pháp lý cho một trình biên dịch để tạo ra nhanh hơn mã cho while(1)hơn cho người khác xảy ra while(1)trong cùng một chương trình.

(Có một câu hỏi ẩn trong câu hỏi mà bạn đã hỏi: Làm thế nào để bạn đối phó với một người phỏng vấn khẳng định một điểm kỹ thuật không chính xác. Đó có thể sẽ là một câu hỏi hay cho trang Workplace ).

141
janos 2014-07-25 08:31.

Đợi tí. Người phỏng vấn, anh ta có giống anh chàng này không?

Thật tệ là chính người phỏng vấn đã thất bại trong cuộc phỏng vấn này, điều gì sẽ xảy ra nếu các lập trình viên khác tại công ty này đã "vượt qua" bài kiểm tra này?

Không. Đánh giá các báo cáo 1 == 02 == 0 phải nhanh như nhau. Chúng ta có thể tưởng tượng việc triển khai trình biên dịch kém nơi cái này có thể nhanh hơn cái kia. Nhưng không lý do chính đáng tại sao cái này phải nhanh hơn cái kia.

Ngay cả khi có một số trường hợp khó hiểu khi tuyên bố là đúng, các lập trình viên không nên được đánh giá dựa trên kiến ​​thức về câu đố khó hiểu (và trong trường hợp này là rùng rợn). Đừng lo lắng về cuộc phỏng vấn này, cách tốt nhất ở đây là bỏ đi.

Tuyên bố từ chối trách nhiệm: Đây KHÔNG phải là một phim hoạt hình gốc của Dilbert. Đây chỉ đơn thuần là một bản mashup .

79
anatolyg 2014-07-20 21:59.

Lời giải thích của bạn là đúng. Đây dường như là một câu hỏi kiểm tra sự tự tin của bạn bên cạnh kiến ​​thức kỹ thuật.

Nhân tiện, nếu bạn trả lời

Cả hai đoạn mã đều nhanh như nhau, vì cả hai đều mất vô hạn thời gian để hoàn thành

người phỏng vấn sẽ nói

Nhưng while (1)có thể thực hiện nhiều lần lặp hơn mỗi giây; bạn có thể giải thích lý do tại sao? (điều này vô nghĩa; hãy kiểm tra lại sự tự tin của bạn)

Vì vậy, bằng cách trả lời như bạn đã làm, bạn đã tiết kiệm được một khoảng thời gian mà nếu không bạn sẽ lãng phí để thảo luận về câu hỏi tồi tệ này.


Đây là mã ví dụ được tạo bởi trình biên dịch trên hệ thống của tôi (MS Visual Studio 2012), với tính năng tối ưu hóa bị tắt:

yyy:
    xor eax, eax
    cmp eax, 1     (or 2, depending on your code)
    je xxx
    jmp yyy
xxx:
    ...

Với tính năng tối ưu hóa được bật:

xxx:
    jmp xxx

Vì vậy, mã được tạo hoàn toàn giống nhau, ít nhất là với một trình biên dịch tối ưu hóa.

60
Ryan Cavanaugh 2014-07-22 04:41.

Lời giải thích có khả năng nhất cho câu hỏi là người phỏng vấn nghĩ rằng bộ xử lý kiểm tra từng bit riêng lẻ của các số, lần lượt cho đến khi nó đạt giá trị khác 0:

1 = 00000001
2 = 00000010

Nếu "bằng 0?" thuật toán bắt đầu từ phía bên phải của số và phải kiểm tra từng bit cho đến khi nó đạt đến bit khác 0, while(1) { }vòng lặp sẽ phải kiểm tra gấp đôi số bit mỗi lần lặp so với while(2) { }vòng lặp.

Điều này đòi hỏi một mô hình tinh thần rất sai lầm về cách máy tính hoạt động, nhưng nó có logic nội tại của riêng nó. Một cách để kiểm tra là hỏi nếu while(-1) { }hoặc while(3) { }sẽ nhanh như nhau, hoặc nếu while(32) { }sẽ chậm hơn .

32
Tõnu Samuel 2014-07-22 17:17.

Tất nhiên tôi không biết ý định thực sự của người quản lý này, nhưng tôi đề xuất một quan điểm hoàn toàn khác: Khi thuê một thành viên mới vào một đội, sẽ rất hữu ích nếu biết anh ta phản ứng như thế nào với các tình huống xung đột.

Họ đã đẩy bạn vào xung đột. Nếu điều này là đúng, họ thông minh và câu hỏi rất hay. Đối với một số ngành, chẳng hạn như ngân hàng, việc đăng vấn đề của bạn lên Stack Overflow có thể là một lý do từ chối.

Nhưng tất nhiên tôi không biết, tôi chỉ đề xuất một phương án.

25
OldFrank 2014-07-23 12:30.

Tôi nghĩ rằng manh mối là được tìm thấy trong "yêu cầu của một quản lý cấp cao". Người này rõ ràng đã ngừng lập trình khi trở thành quản lý và sau đó anh ta / cô ta phải mất vài năm để trở thành quản lý cấp cao. Không bao giờ mất hứng thú với lập trình, nhưng chưa bao giờ viết một dòng nào kể từ những ngày đó. Vì vậy, tài liệu tham khảo của anh ấy không phải là "bất kỳ trình biên dịch tử tế nào ngoài kia" như một số câu trả lời đề cập, mà là "trình biên dịch mà người này đã làm việc với 20-30 năm trước".

Vào thời điểm đó, các lập trình viên đã dành một phần trăm thời gian đáng kể để thử các phương pháp khác nhau để làm cho mã của họ nhanh hơn và hiệu quả hơn vì thời gian CPU của 'máy tính mini trung tâm' là rất đáng giá. Những người viết trình biên dịch cũng vậy. Tôi đoán rằng trình biên dịch một và duy nhất mà công ty của anh ấy cung cấp tại thời điểm đó được tối ưu hóa trên cơ sở 'các câu lệnh thường gặp có thể được tối ưu hóa' và sử dụng một chút phím tắt khi gặp một lúc (1) và đánh giá mọi thứ khác, bao gồm một thời gian (2). Trải nghiệm như vậy có thể giải thích vị trí của anh ấy và sự tự tin của anh ấy đối với nó.

Cách tiếp cận tốt nhất để giúp bạn có được thuê có lẽ là một cho phép người quản lý cấp cao để có được mang đi và giảng dạy bạn 2-3 phút về "những ngày tốt đẹp cũ của lập trình" trước khi BẠN trơn tru dẫn anh ấy về phía đối tượng phỏng vấn tiếp theo. (Thời điểm tốt rất quan trọng ở đây - quá nhanh và bạn đang làm gián đoạn câu chuyện - quá chậm và bạn bị gán cho là người không đủ tập trung). Hãy nói với anh ấy vào cuối cuộc phỏng vấn rằng bạn rất muốn tìm hiểu thêm về chủ đề này.

19
Valentin Radu 2014-07-20 22:13.

Bạn nên hỏi anh ta làm thế nào anh ta đi đến kết luận đó. Dưới bất kỳ trình biên dịch tốt nào ngoài đó, cả hai biên dịch theo hướng dẫn asm giống nhau. Vì vậy, anh ấy cũng nên nói với bạn trình biên dịch để bắt đầu. Và ngay cả như vậy, bạn sẽ phải biết rất rõ về trình biên dịch và nền tảng để có thể đưa ra một dự đoán có học về lý thuyết. Và cuối cùng, nó không thực sự quan trọng trong thực tế, vì có những yếu tố bên ngoài khác như phân mảnh bộ nhớ hoặc tải hệ thống sẽ ảnh hưởng đến vòng lặp nhiều hơn chi tiết này.

18
ouah 2014-07-24 01:02.

Vì lợi ích của câu hỏi này, tôi nên nói thêm rằng tôi nhớ Doug Gwyn từ Ủy ban C đã viết rằng một số trình biên dịch C ban đầu mà không có trình tối ưu hóa sẽ tạo ra một bài kiểm tra trong lắp ráp cho while(1)(so sánh với trình biên dịch for(;;)không có nó).

Tôi sẽ trả lời người phỏng vấn bằng cách đưa ra ghi chú lịch sử này và sau đó nói rằng ngay cả khi tôi sẽ rất ngạc nhiên khi bất kỳ trình biên dịch nào làm được điều này, một trình biên dịch có thể có:

  • mà không có trình tối ưu hóa, trình biên dịch sẽ tạo ra một bài kiểm tra cho cả hai while(1)while(2)
  • với trình tối ưu hóa vượt qua trình biên dịch được hướng dẫn để tối ưu hóa (với một bước nhảy không điều kiện) tất cả while(1)vì chúng được coi là thành ngữ. Điều này sẽ để lại while(2)một bài kiểm tra và do đó tạo ra sự khác biệt về hiệu suất giữa cả hai.

Tất nhiên tôi sẽ nói thêm với người phỏng vấn rằng việc không xem xét while(1)while(2)cấu trúc giống nhau là dấu hiệu của việc tối ưu hóa chất lượng thấp vì đây là những cấu trúc tương đương.

10
UncleKing 2014-07-23 15:10.

Một câu hỏi khác được đặt ra là để xem liệu bạn có đủ can đảm để nói với người quản lý của mình rằng anh ấy / cô ấy sai không! Và bạn có thể giao tiếp nó một cách nhẹ nhàng như thế nào.

Bản năng đầu tiên của tôi là tạo đầu ra hợp ngữ để cho người quản lý thấy rằng bất kỳ trình biên dịch tử tế nào cũng nên xử lý nó và nếu nó không làm như vậy, bạn sẽ gửi bản vá tiếp theo cho nó :)

8
Bart Verkoeijen 2014-07-23 21:37.

Để thấy rất nhiều người đi sâu vào vấn đề này, hãy chỉ ra chính xác lý do tại sao đây rất có thể là một bài kiểm tra để xem bạn muốn tối ưu hóa mọi thứ nhanh đến mức nào .

Câu trả lời của tôi sẽ là; điều đó không quan trọng lắm, tôi muốn tập trung vào vấn đề kinh doanh mà chúng tôi đang giải quyết. Rốt cuộc, đó là những gì tôi sẽ được trả cho.

Hơn nữa, tôi sẽ chọn while(1) {}vì nó phổ biến hơn, và các đồng đội khác sẽ không cần phải mất thời gian để tìm hiểu lý do tại sao ai đó lại chọn con số cao hơn 1.

Bây giờ hãy viết một số mã. ;-)

6
Tom Tanner 2016-04-01 04:39.

Nếu lo lắng về việc tối ưu hóa, bạn nên sử dụng

for (;;)

bởi vì điều đó không có thử nghiệm. (chế độ hoài nghi)

5
pacoverflow 2014-07-28 07:32.

Đối với tôi, có vẻ như đây là một trong những câu hỏi phỏng vấn hành vi được che giấu như một câu hỏi kỹ thuật. Một số công ty làm điều này - họ sẽ hỏi một câu hỏi kỹ thuật khá dễ dàng cho bất kỳ lập trình viên có năng lực nào trả lời, nhưng khi người được phỏng vấn đưa ra câu trả lời chính xác, người phỏng vấn sẽ cho họ biết họ đã sai.

Công ty muốn xem bạn sẽ phản ứng như thế nào trong tình huống này. Bạn có ngồi đó yên lặng và không nhấn mạnh rằng câu trả lời của bạn là đúng, do nghi ngờ bản thân hoặc sợ làm mất lòng người phỏng vấn? Hay bạn sẵn sàng thách thức một người có thẩm quyền mà bạn biết là sai? Họ muốn xem bạn có sẵn sàng bảo vệ niềm tin của mình hay không và liệu bạn có thể làm điều đó một cách tế nhị và tôn trọng hay không.

3
Peter Wooster 2014-07-27 11:55.

Tôi đã từng lập trình C và mã Assembly khi loại vô nghĩa này có thể tạo ra sự khác biệt. Khi nó tạo ra sự khác biệt, chúng tôi đã viết nó trong Assembly.

Nếu tôi được hỏi câu hỏi đó, tôi sẽ lặp lại câu nói nổi tiếng năm 1974 của Donald Knuth về việc tối ưu hóa quá sớm và bỏ đi nếu người phỏng vấn không cười và tiếp tục.

3
Rok Kralj 2014-09-18 22:54.

Có thể người phỏng vấn cố tình đặt ra câu hỏi ngớ ngẩn như vậy và muốn bạn đưa ra 3 điểm:

  1. Lý luận cơ bản. Cả hai vòng lặp là vô hạn, rất khó để nói về hiệu suất.
  2. Kiến thức về mức độ tối ưu hóa. Anh ấy muốn nghe ý kiến ​​của bạn nếu bạn để trình biên dịch thực hiện bất kỳ tối ưu hóa nào cho bạn, nó sẽ tối ưu hóa điều kiện, đặc biệt nếu khối không trống.
  3. Kiến thức về kiến ​​trúc vi xử lý. Hầu hết các kiến ​​trúc có một lệnh CPU đặc biệt để so sánh với 0 (trong khi không nhất thiết phải nhanh hơn).
2
gnasher729 2014-07-21 14:34.

Đây là một vấn đề: Nếu bạn thực sự viết một chương trình và đo tốc độ của nó, tốc độ của cả hai vòng lặp có thể khác nhau! Để có một số so sánh hợp lý:

unsigned long i = 0;
while (1) { if (++i == 1000000000) break; }

unsigned long i = 0;
while (2) { if (++i == 1000000000) break; }

với một số mã được thêm vào để in thời gian, một số hiệu ứng ngẫu nhiên như cách định vị vòng lặp trong một hoặc hai dòng bộ nhớ cache có thể tạo ra sự khác biệt. Một vòng lặp có thể hoàn toàn nằm trong một dòng bộ nhớ cache hoặc ở đầu dòng bộ nhớ cache, hoặc nó có thể nằm giữa hai dòng bộ nhớ cache. Và kết quả là, bất cứ điều gì người phỏng vấn tuyên bố là nhanh nhất có thể là nhanh nhất - một cách trùng hợp.

Trường hợp xấu nhất: Một trình biên dịch tối ưu hóa không tìm ra những gì vòng lặp thực hiện, nhưng chỉ ra rằng các giá trị được tạo ra khi vòng lặp thứ hai được thực thi giống như những giá trị được tạo ra bởi vòng lặp đầu tiên. Và tạo mã đầy đủ cho vòng lặp đầu tiên, nhưng không tạo cho vòng lặp thứ hai.

2
Nikolay Ivanchev 2014-07-22 02:49.

Cả hai đều bằng nhau - giống nhau.

Theo các thông số kỹ thuật, bất kỳ điều gì không phải là 0 đều được coi là đúng, vì vậy ngay cả khi không có bất kỳ tối ưu hóa nào, và một trình biên dịch tốt sẽ không tạo ra bất kỳ mã nào trong khi (1) hoặc trong khi (2). Trình biên dịch sẽ tạo ra một kiểm tra đơn giản cho != 0.

2
ekerner 2014-07-25 18:43.

Đánh giá về lượng thời gian và nỗ lực mà mọi người đã bỏ ra để thử nghiệm, chứng minh và trả lời câu hỏi rất đơn giản này Tôi nói rằng cả hai đều được thực hiện rất chậm khi đặt câu hỏi.

Và vì vậy để dành nhiều thời gian hơn cho nó ...

"while (2)" là vô lý, bởi vì,

"while (1)" và "while (true)" trong lịch sử được sử dụng để tạo một vòng lặp vô hạn mong đợi "break" được gọi ở một số giai đoạn bên trong vòng lặp dựa trên một điều kiện chắc chắn sẽ xảy ra.

"1" chỉ đơn giản là ở đó để luôn đánh giá là true và do đó, nói "while (2)" cũng ngớ ngẩn như nói "while (1 + 1 == 2)" cũng sẽ đánh giá là true.

Và nếu bạn muốn hoàn toàn ngớ ngẩn chỉ cần sử dụng: -

while (1 + 5 - 2 - (1 * 3) == 0.5 - 4 + ((9 * 2) / 4)) {
    if (succeed())
        break;
}

Tôi muốn nghĩ rằng người lập trình của bạn đã mắc lỗi đánh máy không ảnh hưởng đến việc chạy mã, nhưng nếu anh ta cố tình sử dụng "2" chỉ để kỳ lạ thì hãy sa thải anh ta trước khi anh ta đặt tất cả lỗi kỳ lạ vào mã của bạn, gây khó khăn đọc và làm việc với.

1
user143522 2014-07-23 20:51.

Điều đó phụ thuộc vào trình biên dịch.

Nếu nó tối ưu hóa mã, hoặc nếu nó đánh giá 1 và 2 là true với cùng một số lệnh cho một tập lệnh cụ thể, thì tốc độ thực thi sẽ giống nhau.

Trong trường hợp thực tế, nó sẽ luôn nhanh như nhau, nhưng có thể hình dung một trình biên dịch cụ thể và một hệ thống cụ thể khi điều này sẽ được đánh giá khác nhau.

Ý tôi là: đây không thực sự là một câu hỏi liên quan đến ngôn ngữ (C).

0
Antonin GAVREL 2018-01-28 03:58.

Vì mọi người muốn trả lời câu hỏi này muốn vòng lặp nhanh nhất, tôi đã trả lời rằng cả hai đều biên dịch như nhau thành cùng một mã lắp ráp, như đã nêu trong các câu trả lời khác. Tuy nhiên, bạn có thể đề xuất với người phỏng vấn bằng cách sử dụng 'loop unrolling'; một do {} vòng lặp while thay vì vòng lặp while.

Thận trọng: Bạn cần đảm bảo rằng vòng lặp ít nhất sẽ luôn chạy một lần .

Vòng lặp nên có một điều kiện ngắt bên trong.

Ngoài ra đối với loại vòng lặp đó, cá nhân tôi thích sử dụng do {} while (42) vì bất kỳ số nguyên nào, ngoại trừ 0, sẽ thực hiện công việc.

0
chqrlie 2019-02-22 09:29.

Câu trả lời rõ ràng là: như đã đăng, cả hai đoạn sẽ chạy một vòng lặp vô hạn bận rộn như nhau, điều này làm cho chương trình chậm vô hạn .

Mặc dù việc xác định lại các từ khóa C dưới dạng macro về mặt kỹ thuật sẽ có hành vi không xác định, nhưng đó là cách duy nhất tôi có thể nghĩ ra để làm cho một trong hai đoạn mã trở nên nhanh chóng: bạn có thể thêm dòng này phía trên 2 đoạn:

#define while(x) sleep(x);

nó thực sự sẽ while(1)nhanh hơn gấp đôi (hoặc chậm hơn một nửa) while(2).

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

DRM của Ubisoft Denies Assassin's Creed Origins đang tấn công CPU của bạn

DRM của Ubisoft Denies Assassin's Creed Origins đang tấn công CPU của bạn

Kể từ khi phát hành Assassin's Creed Origins trên PC, một số người dùng đã phàn nàn rằng việc sử dụng CPU của trò chơi là rất lớn, đôi khi tăng đến 90-100%. Điều đó không bình thường, và dẫn đến cáo buộc rằng DRM mới của trò chơi là thủ phạm.

Hãy hỏi Tiến sĩ NerdLove: Tôi lo lắng bạn gái của tôi sẽ tự sát nếu chúng tôi chia tay

Hãy hỏi Tiến sĩ NerdLove: Tôi lo lắng bạn gái của tôi sẽ tự sát nếu chúng tôi chia tay

Xin chào, tất cả các bạn Những con thú tình dục trên Internet. Chào mừng bạn đến với Ask Dr.

Những hình dán này cho bạn biết nếu con bạn bị sốt để bạn không phải đánh thức chúng

Những hình dán này cho bạn biết nếu con bạn bị sốt để bạn không phải đánh thức chúng

Ảnh: Fever-Bugz Đã có vài lần tôi và chồng nhìn chằm chằm vào đứa con gái bốn tuổi của mình khi nó đang ngủ, đưa tay sờ lên trán nó một cách bối rối. “Cô ấy có cảm thấy nóng không? Tôi nghĩ cô ấy cảm thấy nóng.

Đây có phải là sự khởi đầu cho sự kết thúc của việc giam giữ Brittney Griner?

Đây có phải là sự khởi đầu cho sự kết thúc của việc giam giữ Brittney Griner?

Brittney Griner (r.) Ngay từ đầu, thân phận của Brittney Griner đã là tình huống con tin Mỹ độc nhất trong lịch sử hiện đại.

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.

Tầm nhìn đám mây phi tập trung của DFINITY Blockchain

Lưu ý của người biên tập: Bạn đang xem tài liệu lỗi thời từ blog DFINITY đang được bảo quản cho mục đích lưu trữ.

Tầm nhìn đám mây phi tập trung của DFINITY Blockchain

Bài đăng này khám phá tầm nhìn về đám mây phi tập trung của nhóm DFINITY và cách nó liên quan đến các nhà cung cấp blockchain truyền thống và đám mây hiện có như Amazon Web Services. Các minh chứng về công nghệ DFINITY được áp dụng bởi một mạng lưới quy mô lớn sẽ được thực hiện vào mùa thu năm 2017, sau đó sẽ được gây quỹ Chính cho quỹ hỗ trợ phi lợi nhuận, với mạng “đám mây mở” dự kiến ​​sẽ ra mắt vào đầu mùa hè năm 2018 .

Language