2012-01-31 26 views
15

Tôi có một con trỏ int* p và thực hiện một số thao tác trong một vòng lặp. Tôi không sửa đổi bộ nhớ, chỉ cần đọc. Nếu tôi thêm const vào con trỏ (cả hai trường hợp, const int* pint* const p), nó có thể giúp trình biên dịch tối ưu hóa mã không?Có thể thêm 'const' vào con trỏ giúp tối ưu hóa không?

Tôi biết các thành tích khác của const, như an toàn hoặc tự tài liệu, tôi hỏi về trường hợp cụ thể này. Rephrasing câu hỏi: có thể const cung cấp cho trình biên dịch bất kỳ hữu ích (để tối ưu hóa) thông tin, bao giờ?

+3

Bạn có thực sự có nghĩa là 'int const * p'? Hoặc 'int * const p'? Vòng lặp gì? Bạn đang lặp lại cái gì? –

+1

Bạn chỉ có thể thực hiện và so sánh mã được tạo: -? – cnicutar

+1

Cách duy nhất để xác định điều này cho một CPU, trình biên dịch, hệ điều hành, vv là để chuẩn nó, và kết quả sau đó sẽ chỉ hợp lệ cho cấu hình cụ thể của khóa học. Nghe có vẻ như tối ưu hóa sớm với tôi. –

Trả lời

6

Mặc dù điều này rõ ràng là cụ thể cho việc triển khai, rất khó để biết cách thay đổi con trỏ từ int* thành int const* có thể cung cấp bất kỳ thông tin bổ sung nào mà trình biên dịch sẽ không biết.

Trong cả hai trường hợp, giá trị được trỏ tới có thể thay đổi trong khi thực hiện vòng lặp.

Do đó, có thể sẽ không giúp trình biên dịch tối ưu hóa mã.

+0

Điều này đơn giản là sai; 'int const *' tương đương với 'const int *', không * không * trỏ tới bộ nhớ ghi được. (Ý bạn là có lẽ là 'int * const') –

+1

@JoSo: Không, điều này là đúng. Tất cả 'int const *' chỉ ra rằng 'int' có thể không được sửa đổi thông qua con trỏ cụ thể đó. Nếu 'int' ban đầu không phải là const, sau đó nó có thể được sửa đổi bởi một phần khác của mã, hoặc có thể được sửa đổi bởi cùng một phần của mã sau khi một diễn viên. – Mankarse

+0

Tôi nhận được câu trả lời của bạn sai, và không thể hồi tưởng lại điều này đã xảy ra như thế nào. Xin lỗi vì chuyện đó. Tệ hơn nữa, rõ ràng là không được phép bỏ phiếu (xuống) trừ khi câu trả lời được chỉnh sửa ... :( –

2

Nó có thể giúp hoặc nó có thể làm cho không có sự khác biệt hoặc nó có thể làm cho nó tồi tệ hơn. Cách duy nhất để biết là thử cả hai và kiểm tra mã máy phát ra.

Trình biên dịch hiện đại rất thông minh để chúng có thể suy ra rằng bộ nhớ không thay đổi mà không có bất kỳ vòng loại nào (pr có thể suy ra nhiều tối ưu hóa khác có thể không được viết theo cách dễ dàng hơn để phân tích). rất nhiều thiếu sót và thường không thể tối ưu hóa mọi thứ có thể có ở mọi cơ hội.

+0

Bạn có bất kỳ ví dụ nào khi nó có thể làm cho nó tồi tệ hơn không? –

+0

@Jakub M .: Không phải cho trường hợp cụ thể này, nhưng tôi đã thấy hàng tá trường hợp khi trình biên dịch không phát ra mã tối ưu. – sharptooth

+2

* nó có thể làm cho nó tồi tệ hơn * là một tuyên bố quá mức và quá tổng quát trừ khi được chứng minh bằng một ví dụ, 'const' có thể tạo ra sự khác biệt hoặc * khác biệt *, và sự khác biệt là không đáng kể. , nó chỉ nên được sử dụng để viết một mã duy trì chính xác hơn. –

3

No. Sử dụng const như vậy sẽ không cung cấp trình biên dịch với bất kỳ thông tin nào có thể được sử dụng để tối ưu hóa.

Về mặt lý thuyết, vì nó là trợ giúp cho trình biên dịch của bạn, trình tối ưu hóa phải có khả năng chứng minh rằng không ai sẽ sử dụng const_cast trên con trỏ const của bạn mà không thể chứng minh được biến chưa bao giờ được ghi. Tình huống như vậy rất khó xảy ra.

Herb Sutter bao gồm độ sâu này ở một trong các cột Guru of the Week.

+0

Nếu trình biên dịch * có thể chứng minh tất cả thông tin bổ sung đó, nó không cần trình độ 'const' nữa. thậm chí sau đó 'const' sẽ không giúp tối ưu hóa. – Mankarse

+0

@Mankarse: trừ khi một số lý do cụ thể triển khai ngớ ngẩn, ví dụ:một trình tối ưu hóa cụ thể không bận tâm đến việc phân tích trừ khi con trỏ có đủ điều kiện. Nhưng bạn vẫn chính xác trong những gì bạn nói, bởi vì đối số của tôi * bất cứ điều gì * có thể ảnh hưởng đến sự tối ưu hóa - số nguyên âm trong tên biến của bạn, hoặc cho dù bạn thụt lề với các tab so với dấu cách. Câu hỏi duy nhất là làm thế nào chính đáng nó là người tối ưu hóa bỏ qua một số thông tin có khả năng hữu ích trong một số trường hợp nhưng không phải là những người khác. –

1

Tôi nghĩ trình biên dịch không thể thực hiện được nhiều trong kịch bản của bạn. Thực tế là con trỏ của bạn được khai báo là const int * const p không đảm bảo rằng bộ nhớ không thể thay đổi bên ngoài, ví dụ: bởi một chủ đề khác. Do đó trình biên dịch phải tạo mã đọc giá trị bộ nhớ trên mỗi lần lặp của vòng lặp của bạn.

Nhưng nếu bạn sẽ không viết thư cho vị trí bộ nhớ và bạn biết rằng không có đoạn mã khác sẽ, sau đó bạn có thể tạo một biến địa phương và sử dụng nó tương tự như sau:

const int * p = ... 
... 
int val = *p; 
/* use the value in a loop */ 
for (i = 0; i < BAZILLION; i++) 
{ 
    use_value(val); 
} 

Không chỉ bạn giúp độc giả tiềm năng của mã của bạn để thấy rằng val không thay đổi trong một vòng lặp, nhưng bạn cũng cung cấp cho trình biên dịch một khả năng để tối ưu hóa (tải val trong sổ đăng ký, ví dụ).

+2

Trình biên dịch thường không xem xét các chủ đề khác trừ khi bạn đặc biệt thêm biến động. Bất kỳ cuộc gọi chức năng nào cũng sẽ cản trở. –

+0

@PerJohansson: có lẽ bạn đã đúng. Dù sao, một sợi chỉ là một ví dụ. Tác dụng phụ của bất kỳ cuộc gọi chức năng nào cũng là một ví dụ điển hình. Tôi chỉ muốn chỉ ra rằng bất kỳ tối ưu hóa nào được thực hiện bởi trình biên dịch phải (và không!) Bảo toàn ngữ nghĩa ban đầu của mã, trong khi tối ưu hóa bộ nhớ đọc bên trong một vòng lặp chắc chắn không, và do đó sẽ không được thực hiện. Nhưng vì không có cách nào hợp pháp để thay đổi 'val' bên ngoài (bên ngoài thân hàm), trình biên dịch được tự do tối ưu hóa. –

1

Sử dụng const, như mọi người khác đã nói, không thể giúp trình biên dịch tối ưu hóa vòng lặp của bạn.

Tuy nhiên, nó có thể giúp tối ưu hóa mã bên ngoài vòng lặp hoặc tại vị trí của cuộc gọi đến phương pháp đủ điều kiện hoặc sử dụng hàm tham số const.

Điều này có khả năng phụ thuộc vào việc trình biên dịch có thể chứng minh được phép loại bỏ tải dư thừa, di chuyển chúng xung quanh hoặc bộ nhớ cache được tính toán thay vì tính lại chúng.

Cách duy nhất để chứng minh điều này vẫn là hồ sơ và/hoặc kiểm tra lắp ráp, nhưng đó là nơi bạn có thể nên tìm kiếm.

1

Bạn không nói trình biên dịch bạn đang sử dụng. Nhưng nếu bạn vừa đọc và ghi vào bộ nhớ, bạn có thể hưởng lợi từ việc sử dụng "hạn chế" hoặc tương tự. Trình biên dịch không biết liệu con trỏ của bạn có đang bí danh cùng bộ nhớ hay không vì vậy bất kỳ cửa hàng nào cũng thường buộc tải lại các giá trị khác. "limits" cho trình biên dịch biết rằng không có răng cưa nào của con trỏ đang xảy ra và có thể tiếp tục sử dụng các giá trị được nạp trước khi ghi tiếp theo. Một cách khác để tránh vấn đề bí danh là tải các giá trị của bạn vào các biến cục bộ thì trình biên dịch không bị buộc phải tải lại sau khi ghi.

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