2016-08-14 25 views
6

Tôi đã tìm kiếm xung quanh một chút và tôi chưa thực sự đưa ra câu trả lời cho điều này.Một số nguyên tắc tốt để chọn kích thước của các loại số nguyên là gì?

Khi tôi lập trình trên các thiết bị nhúng có bộ nhớ hạn chế, tôi thường có thói quen sử dụng loại điểm nổi/nhỏ nhất sẽ thực hiện công việc, ví dụ, nếu tôi biết rằng bộ đếm sẽ luôn là giữa số không và 255, tôi sẽ khai báo nó là uint8_t.

Tuy nhiên, trong môi trường ít bộ nhớ bị hạn chế, tôi thường chỉ sử dụng int cho mọi thứ, theo số Google C++ Styleguide. Khi tôi nhìn vào mã hiện có, nó thường có xu hướng được thực hiện theo cách này.

Để rõ ràng, tôi nhận được lý do đằng sau việc này, (Google giải thích rất rõ), nhưng tôi không rõ ràng về lý do đằng sau việc đầu tiên. Có vẻ như với tôi rằng việc giảm dung lượng bộ nhớ của chương trình của bạn, ngay cả trên một hệ thống mà bạn không quan tâm đến việc sử dụng bộ nhớ, sẽ tốt cho tốc độ tổng thể, vì dữ liệu tổng thể ít có ý nghĩa hơn có thể phù hợp với bộ nhớ cache CPU.

Vấn đề phức tạp, tuy nhiên, thực tế là các trình biên dịch sẽ tự động đệm dữ liệu và căn chỉnh nó với các ranh giới sao cho nó có thể được tìm nạp trong một chu kỳ xe buýt duy nhất. Tôi đoán, sau đó, nó đi xuống để có hay không trình biên dịch là đủ thông minh để có, nói, hai 32-bit số nguyên và dính chúng lại với nhau trong một khối 64-bit so với cá nhân đệm mỗi một đến 64 bit.

Tôi cho rằng bản thân CPU có thể tận dụng lợi thế của điều này hay không phụ thuộc vào nội bộ chính xác của nó, nhưng ý tưởng tối ưu hóa kích thước bộ nhớ sẽ cải thiện hiệu suất, đặc biệt là trên các bộ vi xử lý mới hơn, được chứng minh trong thực tế là hạt nhân Linux relied for awhile tùy chọn -0s của gcc để tăng hiệu suất tổng thể.

Vì vậy, tôi đoán câu hỏi của tôi là lý do khiến phương pháp của Google dường như phổ biến hơn nhiều trong mã thực. Có một chi phí ẩn ở đây mà tôi đang thiếu?

+0

Nguyên tắc về phong cách của Google không xem xét lập trình nhúng và bộ nhớ bị hạn chế. Hoặc, bộ nhớ bị hạn chế đối với các nguyên tắc của Google chỉ có bộ nhớ gigabyte hoặc hai bộ nhớ. Nếu bạn đang lập trình cho 64 KiB hoặc 1 MiB bộ nhớ, bạn đang làm việc trong một môi trường rất khác với giả định của Google. –

+1

Bạn cũng cần phải xem xét rằng bộ nhớ trên ngăn xếp là nhiều hơn hoặc ít hơn miễn phí với số lượng nhỏ, và tiết kiệm bộ nhớ bằng cách sử dụng một loại hẹp * có thể * yêu cầu trình biên dịch để phát ra các hướng dẫn thêm. Đây là suy nghĩ đằng sau việc sử dụng 'int' trừ khi bạn có lý do để không: chẳng hạn như khi nó là một phần tử mảng, hoặc một cấu trúc hoặc thành viên lớp. – EJP

+0

Đôi khi một kiểu dữ liệu lớn hơn có hiệu suất cao hơn. Ví dụ, 'double' có thể cho hiệu suất tốt hơn bởi vì CPU hiện đại thường được xây dựng để làm việc trên' double' thay vì 'float' (nhưng nếu bạn có một tấn, thì có lẽ 'float' sẽ tốt hơn vì bạn có thể cache nhiều hơn ...). Ngoài ra, '-Os' tối ưu hóa số lượng lệnh ít hơn, không phải kích thước của các kiểu dữ liệu đang được vận hành; cờ đó là trực giao với câu hỏi của bạn. – Cornstalks

Trả lời

2

Lý do thông thường là "phương pháp google" thường được sử dụng là vì int thường đủ tốt và thường là tùy chọn đầu tiên được dạy trong tài liệu của người mới bắt đầu. Nó cũng mất nhiều công sức hơn (giờ của người đàn ông, vv) để tối ưu hóa một mã nontrivial cho "bộ nhớ hạn chế" - nỗ lực đó là vô nghĩa nếu không thực sự cần thiết.

Nếu "mã thực tế" được viết cho tính di động, thì int là lựa chọn mặc định tốt.

Cho dù được viết cho tính di động hay không, rất nhiều chương trình chỉ chạy trên máy chủ có đủ tài nguyên bộ nhớ và loại int có thể đại diện cho phạm vi giá trị được yêu cầu. Điều này có nghĩa là không cần phải lo lắng về việc sử dụng bộ nhớ (ví dụ: tối ưu hóa kích thước biến dựa trên phạm vi giá trị cụ thể mà chúng cần hỗ trợ) và chương trình hoạt động.

Lập trình cho "bộ nhớ hạn chế" chắc chắn là phổ biến, nhưng không phải thường lý do tại sao hầu hết mã được viết. Khá nhiều hệ thống nhúng hiện đại có quá nhiều bộ nhớ và các tài nguyên khác, vì vậy các kỹ thuật không phải lúc nào cũng cần thiết cho chúng.

Rất nhiều mã được viết cho những gì bạn gọi là "bộ nhớ hạn chế" cũng không thực sự cần thiết. Có một điểm, như các lập trình viên tìm hiểu thêm, rằng một số lượng đáng kể bắt đầu thưởng thức trong tối ưu hóa sớm - lo lắng về hiệu suất hoặc sử dụng bộ nhớ, ngay cả khi không có nhu cầu chứng minh cho họ làm như vậy.Mặc dù chắc chắn có một bộ mã quan trọng được viết cho "bộ nhớ bị giới hạn" vì nhu cầu chính hãng, nhưng có nhiều mã hơn được viết do tối ưu hóa sớm.

2

"thiết bị được nhúng ... truy cập từ 0 đến 255, tôi sẽ khai báo nó là uint8_t"

Điều đó có thể phản tác dụng. Đặc biệt là trên các hệ thống nhúng, tìm nạp 8 bit có thể chậm hơn. Bên cạnh đó, một truy cập có khả năng trong một đăng ký, và không có lợi ích trong việc sử dụng một nửa đăng ký.

Lý do chính để sử dụng uint8_t là khi bạn có một bộ tiếp giáp. Có thể là một mảng, nhưng cũng là thành viên liền kề trong một class.

Như chú thích đã lưu ý, -Os không liên quan - lợi ích của nó là với mã nhỏ hơn, bus nhớ có nhiều băng thông hơn cho dữ liệu.

0

Từ kinh nghiệm của tôi 90% của tất cả các mã trong một dự án lớn hơn không cần tối ưu hóa cụ thể, vì 95% của tất cả bộ nhớ tiêu thụ và tất cả thời gian thực hiện được chi tiêu ít hơn 10% mã bạn viết. Trong phần còn lại của mã, cố gắng nhấn mạnh sự đơn giản và bảo trì. Chủ yếu, điều đó có nghĩa là sử dụng các loại số nguyên là ints hoặc size_t. Thông thường, không cần phải tối ưu hóa kích thước của biến địa phương, nhưng nó có thể là có thể, nếu bạn có nhiều trường hợp loại trong một mảng lớn. Khoản 6 trong tuyệt vời cuốn sách C++ Coding tiêu chuẩn: 101 Quy định, Hướng dẫn và Thực tiễn tốt nhất (C++ In-Depth) của Herb Sutter và Andrei Alexandrescu nói:

"đúng đắn, đơn giản và rõ ràng đến trước."

Quan trọng nhất, hiểu nơi nào dưới 10% mã, thực sự cần tối ưu hóa. Nếu không, hãy giữ các giao diện đơn giản và đồng nhất.

0

Thảo luận hay! Nhưng tôi tự hỏi tại sao không ai nói về kích thước đăng ký cpu, kiến ​​trúc bus bộ nhớ, kiến ​​trúc cpu và vân vân. Nói "int là tốt nhất" không phải là một tổng thể cả. Nếu bạn có các hệ thống nhúng nhỏ như 8 bit avr, int là một lựa chọn rất xấu cho bộ đếm chạy từ 0 .. 255.

Và sử dụng int trên ARM nơi bạn có thể có giao diện bus 16 bit cũng có thể là rất ý tưởng tồi nếu bạn thực sự chỉ cần 16 bit trở xuống.

Đối với tất cả các tối ưu hóa: Tìm trong mã trình biên dịch tạo ra, đo lường thời gian thực hiện hành động và tìm mức tiêu thụ bộ nhớ trên heap/stack nếu cần. Nó làm cho không có ý nghĩa để tay nghề mã unmaintainable để tiết kiệm 8 bit một nơi nào đó nếu phần cứng của bạn vẫn còn có MBytes trái.

Sử dụng các công cụ như valgrind và lược tả được hỗ trợ bởi đích/trình biên dịch cung cấp nhiều ý tưởng hơn như bất kỳ cuộc thảo luận lý thuyết nào tại đây.

Không có "loại số nguyên tốt nhất" chung! Nó phụ thuộc vào kiến ​​trúc CPU, bus bộ nhớ, cache và một số thứ khác.

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