Tôi đã tối ưu hóa mã C++ trong đó tôi gặp phải một tình huống có thể được đơn giản hóa như sau.hiệu ứng tối ưu hóa gcc trên các vòng có biến cố định rõ ràng
xem xét mã này:
#include <iostream>
#include <thread>
using namespace std;
bool hit = false;
void F()
{
this_thread::sleep_for(chrono::seconds(1));
hit = true;
}
int main()
{
thread t(F);
while (!hit)
;
cout << "finished" << endl;
t.join();
return 0;
}
này về cơ bản bắt đầu một chủ đề mà sau một giây sẽ thay đổi giá trị của hit
để true
. Đồng thời mã sẽ nhập một vòng trống sẽ tiếp tục cho đến khi giá trị của hit
trở thành true
. Tôi biên soạn điều này với gcc-5.4
sử dụng cờ -g
và mọi thứ đều ổn. Mã sẽ xuất ra finished
và kết thúc. Nhưng sau đó tôi biên dịch nó với cờ -O2
và lần này mã đã bị mắc kẹt trong vòng lặp vô hạn.
Nhìn vào tháo gỡ, trình biên dịch đã được tạo ra sau, đó là nguyên nhân gốc rễ của vòng lặp vô hạn:
jmp 0x6ba6f3! 0x00000000006ba6f3
OK, vì vậy rõ ràng, trình biên dịch đã suy luận rằng giá trị hit
's là false
và nó sẽ không thay đổi trong vòng lặp vậy tại sao không cho rằng nó là một vòng lặp vô hạn mà không xem xét rằng thread khác có thể thay đổi giá trị của nó ! Và chế độ tối ưu hóa này được thêm ở cấp cao hơn (-O2
). Vì tôi không chính xác là chuyên gia về cờ tối ưu hóa, bất cứ ai có thể cho tôi biết ai trong số họ chịu trách nhiệm về kết quả này để tôi có thể tắt nó đi? Và sẽ tắt nó có bất kỳ chi phí hiệu suất lớn cho các phần mã khác? Ý tôi là, mẫu mã này hiếm đến mức nào?
sử dụng 'std :: nguyên tử'. –
Jarod42
Điều gì xảy ra nếu bạn khai báo 'hit' là dễ bay hơi? – Milack27
@ Milack27 có nó giải quyết được vấn đề! Người đàn ông, có rất nhiều điều trong c + + mà tôi vẫn không biết! – Sinapse