Tôi đang làm việc trên một dự án cá nhân gần đây khi tôi tình cờ gặp một vấn đề kỳ lạ.
Trong một vòng lặp rất chặt chẽ, tôi có một số nguyên có giá trị từ 0 đến 15. Tôi cần lấy -1 cho các giá trị 0, 1, 8 và 9 và 1 cho các giá trị 4, 5, 12 và 13.
Tôi đã chuyển sang godbolt để kiểm tra một vài tùy chọn và ngạc nhiên rằng dường như trình biên dịch không thể tối ưu hóa một câu lệnh chuyển đổi giống như một chuỗi if.
Liên kết ở đây: https://godbolt.org/z/WYVBFl
Mã này là:
const int lookup[16] = {-1, -1, 0, 0, 1, 1, 0, 0, -1, -1, 0, 0, 1, 1, 0, 0};
int a(int num) {
return lookup[num & 0xF];
}
int b(int num) {
num &= 0xF;
if (num == 0 || num == 1 || num == 8 || num == 9)
return -1;
if (num == 4 || num == 5 || num == 12 || num == 13)
return 1;
return 0;
}
int c(int num) {
num &= 0xF;
switch (num) {
case 0: case 1: case 8: case 9:
return -1;
case 4: case 5: case 12: case 13:
return 1;
default:
return 0;
}
}
Tôi đã nghĩ rằng b và c sẽ mang lại kết quả tương tự, và tôi hy vọng rằng tôi có thể đọc các bản hack bit để tự mình thực hiện một cách hiệu quả vì giải pháp của tôi (câu lệnh chuyển đổi - ở dạng khác) khá chậm.
Điều kỳ lạ, b
được biên dịch thành các bản hack bit trong khi c
gần như không được tối ưu hóa hoặc giảm xuống thành một trường hợp khác a
tùy thuộc vào phần cứng đích.
Bất cứ ai có thể giải thích tại sao có sự khác biệt này? Cách 'chính xác' để tối ưu hóa truy vấn này là gì?
BIÊN TẬP:
Làm rõ
Tôi muốn giải pháp chuyển đổi là nhanh nhất hoặc giải pháp "sạch" tương tự. Tuy nhiên, khi được biên dịch với tối ưu hóa trên máy của tôi, giải pháp if nhanh hơn đáng kể.
Tôi đã viết một chương trình nhanh để chứng minh và TIO có kết quả giống như tôi tìm thấy ở địa phương: Dùng thử trực tuyến!
Với static inline
bảng tra cứu tăng tốc lên một chút: Hãy thử trực tuyến!
if
vẫn đập switch
(tra cứu kỳ lạ thậm chí còn nhanh hơn) [TIO để theo dõi]
-O3
và nó đã biên dịchc
thành một thứ có khả năng tệ hơna
hoặcb
(c
có hai lần nhảy có điều kiện cộng với một vài thao tác bit, so với chỉ một bước nhảy có điều kiện và thao tác bit đơn giản hơnb
), nhưng vẫn tốt hơn so với mục ngây thơ bằng các bài kiểm tra mục. Tôi không chắc chắn những gì bạn thực sự yêu cầu ở đây; thực tế đơn giản là một trình biên dịch tối ưu hóa có thể biến bất kỳ thứ nào trong số này thành bất kỳ cái nào khác nếu nó được chọn, và không có quy tắc cứng và nhanh nào cho những gì nó sẽ hoặc không làm.