Câu hỏi

Tôi đang đọc một cuốn sách mà tác giả nói rằng if( a < 901 ) nhanh hơn if( a <= 900 ).

Không chính xác như trong ví dụ đơn giản này, nhưng có những thay đổi nhỏ về hiệu suất trên mã phức tạp vòng lặp. Tôi cho rằng điều này đã làm điều gì đó với mã máy được tạo ra trong trường hợp nó thậm chí còn đúng.


1372
2017-08-27 02:10


gốc


Tôi không thấy lý do tại sao câu hỏi này nên được đóng lại (và đặc biệt là không bị xóa, vì các phiếu bầu hiện đang hiển thị) vì ý nghĩa lịch sử, chất lượng câu trả lời và thực tế là các câu hỏi hàng đầu khác trong hiệu suất vẫn mở. Tối đa nó sẽ bị khóa. Ngoài ra, ngay cả khi câu hỏi được hiểu sai / ngây thơ, thực tế là nó xuất hiện trong một cuốn sách có nghĩa là thông tin sai lệch ban đầu tồn tại trong các nguồn "đáng tin cậy" ở đâu đó, và câu hỏi này được xây dựng ở chỗ nó giúp làm rõ điều đó. - Jason C
Bạn chưa bao giờ nói với chúng tôi cuốn sách nào bạn đang đề cập đến. - Jonathon Reinhart
Đánh máy < nhanh gấp hai lần nhập <=. - Deqing
Đó là sự thật trên 8086. - Joshua
Số lượng upvotes rõ ràng cho thấy rằng có hàng trăm người đã vượt quá mức tối đa. - m93a


Các câu trả lời:


Không, nó sẽ không nhanh hơn trên hầu hết các kiến ​​trúc. Bạn đã không chỉ định, nhưng trên x86, tất cả các so sánh tách rời sẽ thường được thực hiện trong hai hướng dẫn máy:

  • A test hoặc là cmp hướng dẫn, bộ nào EFLAGS
  • Và một Jcc (nhảy) hướng dẫn, tùy thuộc vào loại so sánh (và bố cục mã):
    • jne - Nhảy nếu không bằng -> ZF = 0
    • jz - Nhảy nếu số không (bằng) -> ZF = 1
    • jg - Nhảy nếu lớn hơn -> ZF = 0 and SF = OF
    • (v.v ...)

Thí dụ (Đã chỉnh sửa cho ngắn gọn) Biên soạn với $ gcc -m32 -S -masm=intel test.c

    if (a < b) {
        // Do something 1
    }

Biên dịch thành:

    mov     eax, DWORD PTR [esp+24]      ; a
    cmp     eax, DWORD PTR [esp+28]      ; b
    jge     .L2                          ; jump if a is >= b
    ; Do something 1
.L2:

    if (a <= b) {
        // Do something 2
    }

Biên dịch thành:

    mov     eax, DWORD PTR [esp+24]      ; a
    cmp     eax, DWORD PTR [esp+28]      ; b
    jg      .L5                          ; jump if a is > b
    ; Do something 2
.L5:

Vì vậy, sự khác biệt duy nhất giữa hai jg so với một jge chỉ dẫn. Cả hai sẽ mất cùng một lượng thời gian.


Tôi muốn giải quyết các bình luận rằng không có gì chỉ ra rằng các hướng dẫn nhảy khác nhau có cùng một lượng thời gian. Điều này là một chút khó khăn để trả lời, nhưng đây là những gì tôi có thể cung cấp cho: Trong Tham chiếu tập lệnh Intel, tất cả chúng đều được nhóm lại với nhau theo một hướng dẫn chung, Jcc (Nhảy nếu điều kiện được đáp ứng). Cùng một nhóm được thực hiện cùng nhau dưới Hướng dẫn tham khảo tối ưu hóa, trong Phụ lục C. Độ trễ và Thông lượng.

Độ trễ - Số chu kỳ đồng hồ được yêu cầu cho   lõi thực thi để hoàn thành việc thực hiện tất cả các biểu mẫu   một hướng dẫn.

Thông lượng - Số chu kỳ đồng hồ cần thiết cho   đợi trước khi cổng sự cố được tự do chấp nhận cùng một lệnh   lần nữa. Đối với nhiều hướng dẫn, thông lượng của lệnh có thể là   thấp hơn đáng kể so với độ trễ của nó

Các giá trị cho Jcc là:

      Latency   Throughput
Jcc     N/A        0.5

với chú thích sau trên Jcc:

7) Lựa chọn các hướng dẫn nhảy có điều kiện phải dựa trên khuyến nghị của phần Mục 3.4.1, “Dự báo tối ưu hóa nhánh” để cải thiện khả năng dự đoán của các nhánh. Khi các nhánh được dự đoán thành công, độ trễ của jcc có hiệu quả bằng không.

Vì vậy, không có gì trong tài liệu của Intel từng xử lý Jcc hướng dẫn bất kỳ cách nào khác với những người khác.

Nếu người ta nghĩ về mạch thực tế được sử dụng để thực hiện các hướng dẫn, người ta có thể giả định rằng sẽ có các cổng AND / OR đơn giản trên các bit khác nhau trong EFLAGS, để xác định xem các điều kiện có được đáp ứng hay không. Sau đó, không có lý do gì mà một lệnh kiểm tra hai bit sẽ mất nhiều thời gian hơn hoặc ít hơn một lần thử nghiệm duy nhất (Bỏ qua sự chậm trễ lan truyền cổng, ít hơn nhiều so với thời gian đồng hồ.)


Chỉnh sửa: Floating Point

Điều này cũng đúng với điểm nổi x87: (Khá nhiều mã như trên, nhưng với double thay vì int.)

        fld     QWORD PTR [esp+32]
        fld     QWORD PTR [esp+40]
        fucomip st, st(1)              ; Compare ST(0) and ST(1), and set CF, PF, ZF in EFLAGS
        fstp    st(0)
        seta    al                     ; Set al if above (CF=0 and ZF=0).
        test    al, al
        je      .L2
        ; Do something 1
.L2:

        fld     QWORD PTR [esp+32]
        fld     QWORD PTR [esp+40]
        fucomip st, st(1)              ; (same thing as above)
        fstp    st(0)
        setae   al                     ; Set al if above or equal (CF=0).
        test    al, al
        je      .L5
        ; Do something 2
.L5:
        leave
        ret

1571
2017-08-27 02:13



@Dyppl thực sự jg và jnle là cùng một hướng dẫn, 7F :-) - Jonathon Reinhart
Chưa kể rằng trình tối ưu hóa có thể sửa đổi mã nếu thực sự một tùy chọn nhanh hơn tùy chọn kia. - Elazar Leibovich
chỉ vì một số kết quả trong cùng một lượng hướng dẫn không nhất thiết có nghĩa là tổng thời gian thực hiện tất cả các hướng dẫn đó sẽ giống nhau. Trên thực tế, nhiều hướng dẫn hơn có thể được thực hiện nhanh hơn. Hướng dẫn trên mỗi chu kỳ không phải là số cố định, nó thay đổi tùy theo hướng dẫn. - jontejj
@jontejj Tôi rất ý thức về điều đó. Bạn thậm chí có đọc câu trả lời của tôi? Tôi đã không nói bất cứ điều gì về cùng con số hướng dẫn, tôi đã nói rằng chúng được biên dịch về cơ bản giống hệt nhau instrutcions, ngoại trừ một lệnh nhảy đang xem một lá cờ và lệnh nhảy khác đang xem xét hai cờ. Tôi tin rằng tôi đã đưa ra nhiều bằng chứng đầy đủ để chứng minh rằng chúng giống hệt nhau về mặt ngữ nghĩa. - Jonathon Reinhart
@jontejj Bạn thực hiện một điểm rất tốt. Đối với nhiều khả năng hiển thị như câu trả lời này được, tôi có lẽ nên cung cấp cho nó một chút của một dọn dẹp. Cảm ơn vì bạn đã phản hồi. - Jonathon Reinhart


Trong lịch sử (chúng ta đang nói những năm 1980 và đầu những năm 1990), đã có một số các kiến ​​trúc trong đó điều này là đúng sự thật. Vấn đề gốc là so sánh số nguyên vốn đã được thực hiện thông qua phép trừ số nguyên. Điều này dẫn đến các trường hợp sau đây.

Comparison     Subtraction
----------     -----------
A < B      --> A - B < 0
A = B      --> A - B = 0
A > B      --> A - B > 0

Bây giờ thì ở đâu A < B phép trừ phải mượn một bit cao cho phép trừ là chính xác, giống như bạn mang và mượn khi cộng và trừ bằng tay. Bit "mượn" này thường được gọi là mang theo chút và có thể kiểm chứng bằng lệnh chi nhánh. Một bit thứ hai được gọi là không bit sẽ được thiết lập nếu phép trừ được nhận dạng bằng 0, ngụ ý sự bình đẳng.

Thường có ít nhất hai lệnh chi nhánh có điều kiện, một đến nhánh trên bit mang và một trên bit số không.

Bây giờ, để có được ở trung tâm của vấn đề, chúng ta hãy mở rộng bảng trước để bao gồm các kết quả mang và không bit.

Comparison     Subtraction  Carry Bit  Zero Bit
----------     -----------  ---------  --------
A < B      --> A - B < 0    0          0
A = B      --> A - B = 0    1          1
A > B      --> A - B > 0    1          0

Vì vậy, triển khai chi nhánh cho A < B có thể được thực hiện trong một hướng dẫn, bởi vì bit mang theo là rõ ràng chỉ có trong trường hợp này, có nghĩa là,

;; Implementation of "if (A < B) goto address;"
cmp  A, B          ;; compare A to B
bcz  address       ;; Branch if Carry is Zero to the new address

Nhưng, nếu chúng ta muốn so sánh ít hơn hoặc bằng nhau, chúng ta cần thực hiện kiểm tra bổ sung cờ số 0 để nắm bắt trường hợp bình đẳng.

;; Implementation of "if (A <= B) goto address;"
cmp A, B           ;; compare A to B
bcz address        ;; branch if A < B
bzs address        ;; also, Branch if the Zero bit is Set

Vì vậy, trên một số máy, sử dụng so sánh "ít hơn" có thể tiết kiệm một máy hướng dẫn. Điều này có liên quan trong thời đại của tốc độ xử lý phụ megahertz và tỷ lệ tốc độ CPU-bộ nhớ 1: 1, nhưng nó gần như hoàn toàn không liên quan đến ngày hôm nay.


554
2017-08-27 17:53



Ngoài ra, các kiến ​​trúc như x86 thực hiện các lệnh như jge, kiểm tra cả cờ số 0 và ký / mang. - greyfade
+1 cho viễn cảnh lịch sử. - sbi
Điều này là đúng trên 8080. Nó có hướng dẫn để nhảy vào số không và nhảy vào trừ, nhưng không ai có thể kiểm tra cả hai cùng một lúc.
+1 Đây là câu trả lời duy nhất giải thích tại sao tác giả có thể đã viết những gì ông đã làm. - Leo
Ngay cả trên 8080 <= kiểm tra có thể được thực hiện trong một chỉ dẫn với hoán đổi các toán hạng và thử nghiệm cho not < (tương đương với >=) Đây là mong muốn <=với toán hạng hoán đổi: cmp B,A; bcs addr. Đó là lý do mà thử nghiệm này bị Intel loại bỏ, họ coi nó là không cần thiết và bạn không thể đủ khả năng cho những chỉ dẫn dư thừa vào những lúc đó :-) - Gunther Piez


Giả sử chúng ta đang nói về các kiểu số nguyên bên trong, không có cách nào có thể có thể nhanh hơn số nguyên kia. Chúng rõ ràng giống hệt về mặt ngữ nghĩa. Cả hai đều yêu cầu trình biên dịch thực hiện chính xác điều tương tự. Chỉ có một trình biên dịch bị hỏng nặng nề sẽ tạo ra mã kém hơn cho một trong số này.

Nếu có một số nền tảng < nhanh hơn <= đối với các loại số nguyên đơn giản, trình biên dịch nên luôn luôn đổi <= đến < cho hằng số. Bất kỳ trình biên dịch nào không chỉ là trình biên dịch xấu (cho nền tảng đó).


84
2017-08-27 02:31



+1 Tôi đồng ý. Cũng không < cũng không <= có tốc độ cho đến khi trình biên dịch quyết định tốc độ nào họ sẽ có. Đây là một tối ưu hóa rất đơn giản cho trình biên dịch khi bạn xem xét rằng họ thường đã thực hiện tối ưu hóa mã chết, tối ưu hóa cuộc gọi đuôi, loop hoisting (và unrolling, vào những dịp), parallelisation tự động của các vòng khác nhau, vv ... Tại sao lãng phí thời gian cân nhắc tối ưu hóa sớm? Nhận một mẫu thử nghiệm chạy, cấu hình nó để xác định nơi tối ưu hóa quan trọng nhất nằm, thực hiện những tối ưu hóa theo thứ tự ý nghĩa và hồ sơ một lần nữa trên đường đi để đo lường sự tiến bộ ... - autistic
Vẫn còn một số trường hợp cạnh mà so sánh có một giá trị không đổi có thể chậm hơn dưới <=, ví dụ: khi chuyển đổi từ (a < C) đến (a <= C-1) (đối với một số hằng số C) nguyên nhân C khó mã hóa hơn trong tập lệnh. Ví dụ, một tập lệnh có thể biểu diễn các hằng số đã ký từ -127 đến 128 theo dạng nhỏ gọn so sánh, nhưng các hằng số ngoài phạm vi đó phải được nạp bằng cách sử dụng mã hóa dài hơn, chậm hơn hoặc một lệnh khác hoàn toàn. So sánh như (a < -127) có thể không có sự chuyển đổi đơn giản. - BeeOnRope
@BeeOnRope Vấn đề không phải là liệu việc thực hiện các hoạt động có khác biệt do có các hằng số khác nhau trong chúng có thể ảnh hưởng đến hiệu suất hay không bày tỏ các tương tự hoạt động bằng cách sử dụng các hằng số khác nhau có thể ảnh hưởng đến hiệu suất. Vì vậy, chúng tôi không so sánh a > 127 đến a > 128 bởi vì bạn không có sự lựa chọn ở đó, bạn sử dụng cái bạn cần. Chúng tôi đang so sánh a > 127 đến a >= 128, không thể yêu cầu mã hóa khác nhau hoặc các hướng dẫn khác nhau vì chúng có cùng bảng chân lý. Bất kỳ mã hóa nào của một mã hóa đều bằng nhau. - David Schwartz
Tôi đã trả lời một cách chung chung để tuyên bố của bạn rằng "Nếu có một số nền tảng nơi [<= chậm hơn] trình biên dịch nên luôn luôn chuyển đổi <= đến < Đối với các hằng số ". Theo như tôi biết, phép biến đổi đó liên quan đến việc thay đổi hằng số. Ví dụ: a <= 42 được biên dịch thành a < 43 bởi vì < nhanh hơn. Trong một số trường hợp cạnh, việc chuyển đổi như vậy sẽ không hiệu quả vì hằng số mới có thể yêu cầu hướng dẫn nhiều hơn hoặc chậm hơn. Tất nhiên a > 127 và a >= 128 tương đương và trình biên dịch nên mã hóa cả hai biểu mẫu theo cách nhanh nhất (tương tự), nhưng điều đó không phù hợp với những gì tôi đã nói. - BeeOnRope


Tôi thấy rằng không phải là nhanh hơn. Trình biên dịch tạo ra cùng một mã máy trong mỗi điều kiện với một giá trị khác nhau.

if(a < 901)
cmpl  $900, -4(%rbp)
jg .L2

if(a <=901)
cmpl  $901, -4(%rbp)
jg .L3

Ví dụ của tôi if là từ GCC trên nền tảng x86_64 trên Linux.

Các nhà văn biên dịch là những người khá thông minh, và họ nghĩ về những điều này và nhiều thứ khác mà hầu hết chúng ta đều nhận được.

Tôi nhận thấy rằng nếu nó không phải là một hằng số, thì cùng một mã máy được tạo ra trong cả hai trường hợp.

int b;
if(a < b)
cmpl  -4(%rbp), %eax
jge   .L2

if(a <=b)
cmpl  -4(%rbp), %eax
jg .L3

66
2017-08-27 02:16



Lưu ý rằng điều này là dành riêng cho x86. - Michael Petrotta
Tôi nghĩ bạn nên sử dụng if(a <=900) để chứng minh rằng nó tạo ra chính xác cùng một asm :) - Lipis
@AdrianCornish Xin lỗi .. Tôi đã chỉnh sửa nó .. nó nhiều hơn hoặc ít hơn giống nhau .. nhưng nếu bạn thay đổi thứ hai nếu thành <= 900 thì mã asm sẽ giống y như cũ :) Bây giờ nó cũng giống như vậy .. nhưng bạn biết .. cho OCD :) - Lipis
@Boann Điều đó có thể bị giảm xuống nếu (đúng) và bị loại bỏ hoàn toàn. - Qsario
Không ai chỉ ra rằng tối ưu hóa này chỉ áp dụng cho các so sánh liên tục. Tôi có thể đảm bảo nó sẽ không phải được thực hiện như thế này để so sánh hai biến. - Jonathon Reinhart


Đối với mã dấu chấm động, <= so sánh có thể thực sự chậm hơn (bởi một lệnh) ngay cả trên các kiến ​​trúc hiện đại. Đây là chức năng đầu tiên:

int compare_strict(double a, double b) { return a < b; }

Trên PowerPC, trước tiên, điều này thực hiện so sánh dấu chấm động (cập nhật cr, thanh ghi điều kiện), sau đó di chuyển thanh ghi điều kiện sang GPR, thay đổi bit "so sánh nhỏ hơn" thành vị trí và sau đó trả về. Phải mất bốn hướng dẫn.

Bây giờ hãy xem xét hàm này thay vào đó:

int compare_loose(double a, double b) { return a <= b; }

Điều này đòi hỏi công việc tương tự như compare_strict ở trên, nhưng bây giờ có hai bit quan tâm: "nhỏ hơn" và "bằng". Điều này đòi hỏi một hướng dẫn thêm (cror- điều kiện đăng ký bitwise OR) để kết hợp hai bit này thành một. Vì thế compare_loose yêu cầu năm hướng dẫn, trong khi compare_strict yêu cầu bốn.

Bạn có thể nghĩ rằng trình biên dịch có thể tối ưu hóa hàm thứ hai như sau:

int compare_loose(double a, double b) { return ! (a > b); }

Tuy nhiên điều này sẽ xử lý sai các NaN. NaN1 <= NaN2 và NaN1 > NaN2 cần cả hai đánh giá sai.


48
2017-08-27 18:32



May mắn thay nó không hoạt động như thế này trên x86 (x87). fucomip đặt ZF và CF. - Jonathon Reinhart
@ JonathonReinhart: Tôi nghĩ bạn đang hiểu nhầm PowerPC đang làm gì - đăng ký điều kiện cr  Là tương đương với cờ như ZF và CF trên x86. (Mặc dù CR là linh hoạt hơn.) Những gì các poster đang nói về là di chuyển kết quả đến một GPR: mà có hai hướng dẫn về PowerPC, nhưng x86 có một hướng dẫn di chuyển có điều kiện. - Dietrich Epp
@DietrichEpp Những gì tôi có nghĩa là để thêm sau khi tuyên bố của tôi là: Mà bạn có thể ngay lập tức nhảy dựa trên giá trị của EFLAGS. Xin lỗi vì không được rõ ràng. - Jonathon Reinhart
@ JonathonReinhart: Có, và bạn cũng có thể ngay lập tức nhảy dựa trên giá trị của CR. Câu trả lời là không nói về nhảy, đó là nơi mà các hướng dẫn thêm đến từ. - Dietrich Epp


Có lẽ tác giả của cuốn sách chưa được đặt tên đó đã đọc a > 0 chạy nhanh hơn a >= 1 và nghĩ rằng đó là sự thật phổ biến.

Nhưng đó là vì một 0 có liên quan (vì CMP có thể, tùy thuộc vào kiến ​​trúc, được thay thế, ví dụ: với OR) và không phải vì <.


34
2017-08-27 13:05



Chắc chắn, trong quá trình xây dựng "gỡ lỗi", nhưng sẽ mất một trình biên dịch xấu cho (a >= 1) chạy chậm hơn (a > 0), vì trước đây có thể được chuyển đổi một cách trivially thành thứ hai bởi trình tối ưu hóa .. - BeeOnRope
@BeeOnRope Đôi khi tôi ngạc nhiên về những điều phức tạp mà một trình tối ưu hóa có thể tối ưu hóa và những thứ dễ dàng mà nó không thực hiện được. - glglgl
Thật vậy, và nó luôn luôn có giá trị kiểm tra đầu ra asm cho rất ít chức năng mà nó sẽ quan trọng. Điều đó nói rằng, việc chuyển đổi trên là rất cơ bản và đã được thực hiện ngay cả trong các trình biên dịch đơn giản trong nhiều thập kỷ. - BeeOnRope


Ít nhất, nếu điều này đúng, một trình biên dịch có thể tối ưu hóa một cách tối ưu một <= b đến! (A> b), và vì vậy ngay cả khi so sánh chính nó thực sự chậm hơn, với tất cả, nhưng trình biên dịch ngây thơ nhất bạn sẽ không nhận thấy sự khác biệt .


29
2017-08-27 09:23



(A> b) là phiên bản được tối ưu hóa của một <= b. (A> b) 2 hoạt động trong một? - Abhishek Singh
@AbhishekSingh NOT chỉ được thực hiện bởi hướng dẫn khác (je so với jne) - Pavel Gatnar


Họ có cùng tốc độ. Có lẽ trong một số kiến ​​trúc đặc biệt những gì anh / cô ấy nói là đúng, nhưng trong gia đình x86 ít nhất tôi biết họ là như nhau. Bởi vì để làm điều này CPU sẽ làm một chất nền (a - b) và sau đó kiểm tra các lá cờ của thanh ghi cờ. Hai bit của thanh ghi đó được gọi là ZF (zero Flag) và SF (sign flag), và nó được thực hiện trong một chu kỳ, bởi vì nó sẽ làm điều đó với một hoạt động mặt nạ.


15
2017-08-27 08:25





Điều này sẽ phụ thuộc nhiều vào kiến ​​trúc cơ bản mà C được biên dịch. Một số bộ vi xử lý và kiến ​​trúc có thể có các lệnh rõ ràng bằng hoặc nhỏ hơn và bằng, thực thi theo các số chu kỳ khác nhau.

Đó sẽ là khá bất thường mặc dù, như trình biên dịch có thể làm việc xung quanh nó, làm cho nó không liên quan.


13
2017-08-27 02:15



NẾU có sự khác biệt trong các ô. 1) nó sẽ không được phát hiện. 2) Bất kỳ trình biên dịch nào có giá trị muối của nó đã có thể biến đổi từ dạng chậm sang dạng nhanh hơn mà không làm thay đổi ý nghĩa của mã. Vì vậy, các hướng dẫn kết quả trồng sẽ giống hệt nhau. - Martin York
Đồng ý hoàn toàn, nó sẽ là một sự khác biệt khá nhỏ và ngớ ngẩn trong mọi trường hợp. Chắc chắn không có gì để đề cập đến trong một cuốn sách mà nên được nền tảng thuyết bất khả tri. - Telgin
@ lttlrck: Tôi hiểu rồi. Đã cho tôi một lúc (ngớ ngẩn tôi). Không có chúng không thể phát hiện được vì có quá nhiều thứ khác xảy ra khiến cho phép đo của chúng không thể xảy ra. Xử lý quầy hàng / bộ nhớ cache nhớ / tín hiệu / quá trình trao đổi. Vì vậy, trong một tình huống hệ điều hành bình thường, mọi thứ ở cấp độ chu kỳ đơn lẻ không thể đo lường được. Nếu bạn có thể loại bỏ tất cả sự can thiệp từ các phép đo của bạn (chạy nó trên chip với bộ nhớ on-board và không có hệ điều hành) thì bạn vẫn có độ chi tiết của bộ đếm thời gian để lo lắng nhưng về mặt lý thuyết nếu bạn chạy nó đủ lâu bạn có thể thấy điều gì đó. - Martin York


Các câu trả lời khác đã tập trung vào x86 kiến trúc và tôi không biết CÁNH TAY kiến trúc (mà trình biên dịch ví dụ của bạn có vẻ là đủ) để bình luận cụ thể về mã được tạo ra, nhưng đây là một ví dụ về tối ưu hóa vi mô cái nào  rất cụ thể về kiến ​​trúc và có khả năng là chống tối ưu hóa vì nó là một tối ưu hóa.

Như vậy, tôi sẽ gợi ý rằng loại tối ưu hóa vi mô là một ví dụ về hàng hóa giáo phái lập trình thay vì thực hành kỹ thuật phần mềm tốt nhất.

Có lẽ có một số kiến trúc nơi đây là một tối ưu hóa, nhưng tôi biết ít nhất một kiến ​​trúc mà ngược lại có thể đúng. Đáng kính Transputer kiến trúc chỉ có hướng dẫn mã máy cho tương đương với và lớn hơn hoặc bằng, vì vậy tất cả các so sánh phải được xây dựng từ những nguyên thủy này.

Thậm chí sau đó, trong hầu hết các trường hợp, trình biên dịch có thể ra lệnh cho các hướng dẫn đánh giá theo cách mà trong thực tế, không có so sánh nào có lợi thế hơn bất kỳ trường hợp nào khác. Trường hợp xấu nhất mặc dù, nó có thể cần phải thêm một lệnh đảo ngược (REV) để trao đổi hai mục hàng đầu trên toán hạng. Đây là một hướng dẫn byte đơn mà chỉ mất một chu kỳ duy nhất để chạy, vì vậy có thể có chi phí nhỏ nhất có thể.

Có hay không một tối ưu hóa vi mô như thế này là một tối ưu hóa hoặc một chống tối ưu hóa phụ thuộc vào kiến ​​trúc cụ thể bạn đang sử dụng, vì vậy thường là một ý tưởng tồi để có thói quen sử dụng kiến ​​trúc tối ưu hóa vi mô cụ thể, nếu không bạn có thể sử dụng một cách bản năng khi không thích hợp. những gì cuốn sách bạn đang đọc là ủng hộ.


10
2017-08-31 18:33