2015-05-13 18 views
5

Tôi đang sử dụng cho/trong khi vòng lặp để thực hiện một sự chậm trễ trong mã của tôi. Thời gian trễ là không quan trọng ở đây mặc dù nó đủ lớn để được chú ý. Đây là đoạn mã.cho vòng lặp bị bỏ qua (tối ưu hóa?) Ra

uint32_t i; 

// Do something useful 

for (i = 0; i < 50000000U; ++i) 
{} 

// Do something useful 

Vấn đề tôi quan sát là vòng lặp này sẽ không được thực thi. Nó có thể bị bỏ qua/tối ưu hóa bởi trình biên dịch. Tuy nhiên, nếu tôi đủ điều kiện truy cập vòng lặp i bởi dễ bay hơi, vòng lặp for dường như thực thi và tôi nhận thấy độ trễ mong muốn trong quá trình thực hiện.

Hành vi này có vẻ hơi phản trực giác với sự hiểu biết của tôi về tối ưu hóa trình biên dịch có/không có từ khóa dễ bay hơi.

Ngay cả khi bộ đếm vòng lặp được tối ưu hóa và được lưu trữ trong thanh ghi bộ xử lý, không nên bộ đếm vẫn hoạt động, có lẽ với độ trễ thấp hơn? (Kể từ khi bộ nhớ nạp trên không được thực hiện với.)

Nền tảng tôi đang xây dựng là bộ xử lý Xtensa (bởi Tensilica), và trình biên dịch C là trình biên dịch được cung cấp bởi Tensilica, trình biên dịch Xtensa C/C++ chạy với mức cao nhất tối ưu hóa.

Tôi đã thử cùng với gcc 4.4.7 với -o3 và mức tối ưu hóa của bánh mì nướng. Sự chậm trễ dường như hoạt động trong trường hợp đó.

+0

Trình biên dịch c có thể phát hiện vòng lặp for không làm gì cả, và chỉ có thể loại bỏ toàn bộ vòng lặp khi tôi không biến động. – user1937198

+1

Thành thật mà nói, nếu tôi là một trình biên dịch, tôi sẽ đặt tôi thành 50000000U và được thực hiện, đặc biệt là ở các mức tối ưu hóa cao. Với volatile, nó có thể được thay đổi bên ngoài, vì vậy tôi không thể tối ưu hóa nó ra và đọc nó từ sổ đăng ký/cache/bất cứ nơi nào trong bất kỳ iteration. – martin

+1

Trình biên dịch không quan tâm đến việc bảo tồn các biến hoặc vòng lặp của bạn; nó quan tâm đến việc bảo tồn những thứ như đầu vào và đầu ra. Tách ra một vòng lặp không có gì là hoàn toàn được phép. – user2357112

Trả lời

14

Đây là tất cả về hành vi có thể quan sát. Hành vi quan sát duy nhất của vòng lặp của bạn là i50000000U sau vòng lặp. Trình biên dịch được phép tối ưu hóa và thay thế nó bằng i = 50000000U;. Nhiệm vụ i này cũng sẽ được tối ưu hóa vì giá trị của i không có hậu quả quan sát được.

Từ khóa volatile cho trình biên dịch viết và đọc từ i có hành vi quan sát được, do đó ngăn không cho nó tối ưu hóa.

Trình biên dịch cũng sẽ không tối ưu hóa các cuộc gọi đến chức năng không có quyền truy cập vào mã. Về mặt lý thuyết, nếu một trình biên dịch có quyền truy cập vào toàn bộ mã hệ điều hành, nó có thể tối ưu hóa mọi thứ nhưng các biến dễ bay hơi, thường được đặt trên các hoạt động IO phần cứng.

Các quy tắc tối ưu hóa này tuân thủ tất cả những gì được viết trong tiêu chuẩn C (xem nhận xét cho tài liệu tham khảo).

Ngoài ra, nếu bạn muốn trì hoãn, hãy sử dụng chức năng chuyên biệt (ví dụ: OS API), chúng đáng tin cậy và không tiêu thụ CPU, không giống như độ trễ của máy quay.

+4

Tôi nghĩ rằng điều này được đề cập trong N1570 §5.1.2.3, đặc biệt trong đoạn 4: * Trong máy trừu tượng, tất cả các biểu thức được đánh giá theo quy định của ngữ nghĩa. An thực hiện thực tế không cần đánh giá một phần của một biểu thức nếu nó có thể suy ra rằng giá trị của nó không được sử dụng và không có tác dụng phụ cần thiết được sản xuất (bao gồm bất kỳ gây ra bằng cách gọi một chức năng hoặc truy cập một đối tượng dễ bay hơi) * – user694733

+1

hiểu biết sâu sắc ElderBug. Đây là những gì tôi đã thực sự tìm kiếm; một số báo trước trong tiêu chuẩn C chống lại điều này. Theo như sử dụng các API hệ điều hành cho sự chậm trễ, tôi đang làm việc trên một bộ xử lý đơn lẻ, phần cứng kim loại trần và độ chính xác/độ chính xác của độ trễ là không đáng kể ở đây. Tôi chỉ cần chắc chắn rằng nó là nhiều hơn một giá trị ngưỡng nhất định. – LoneWolf

+0

@ user694733 Cảm ơn bạn đã chỉ ra. Nó chắc chắn giảm bớt rắc rối. :) – LoneWolf

Các vấn đề liên quan