Tôi nhớ đọc ở đâu đó tốt hơn là sử dụng số nguyên làm biến đếm vòng lặp thay vì char hoặc ngắn. Nếu đúng thì tại sao? Nó có cung cấp bất kỳ lợi ích tối ưu nào không?Có tốt hơn khi sử dụng các số nguyên làm biến số vòng lặp không?
Trả lời
Nói chung, trình biên dịch sẽ làm cho int
trở thành kích thước tốt để đưa vào một trong các thanh ghi mục đích chung của CPU của bạn. Điều đó thường dẫn đến truy cập nhanh.
Tất nhiên không có gì đảm bảo. Trình biên dịch là miễn phí để làm rất nhiều thứ, bao gồm, tôi sẽ đoán, thúc đẩy một số mã của bạn sử dụng char
cho một số loại lớn hơn. Vì vậy, sự khác biệt có thể không quan trọng.
Thực sự, đối với câu trả lời đúng cho trình biên dịch của bạn, bạn nên xem bản lắp ráp mà nó xuất ra.
Trong các hoạt động kiến trúc 32 bit với 4 byte (int) biến thường nhanh hơn. Điều này chủ yếu là do kích thước của thanh ghi và liên kết bộ nhớ. Trong kiến trúc 64 bit, int sẽ được tự động tạo số nguyên 64 bit.
Loại int
thường có thể được mong đợi là loại số nguyên được triển khai nhanh nhất trên nền tảng của bạn và do đó nên là lựa chọn mặc định.
Từ K & R, ấn bản thứ hai, tr. 36:
int
: một số nguyên, thường phản ánh kích thước tự nhiên của số nguyên trên máy chủ.
Ah, không có gì giống như khái quát hóa không chính xác ở đó. Bạn có thể thực hiện các hàm siêu việt bằng cách sử dụng các số nguyên, sẽ không nhanh như một phao có bộ xử lý dấu chấm động. Ngoài ra, một mảng ints trong đó các giá trị trong mảng sẽ phù hợp với một char sẽ đòi hỏi bốn lần băng thông bộ nhớ để xử lý. – Skizz
Thay đổi thành "loại số nguyên được triển khai nhanh nhất". –
Sẽ tốt hơn nếu sử dụng loại size_t
cho bộ đếm vòng lặp. Nó sẽ mở rộng đến 64 bit.
một vòng lặp mà không 2^64-1 sẽ làm tôi sợ: D –
bạn không phải bắt đầu từ 0 và kết thúc bằng giá trị lớn nhất có thể xD – fortran
Chúng ta thường sẽ chạy trên 2^31-1 trong những năm tới. Tốt hơn là mã của chúng tôi được chuẩn bị cho việc này. –
Trong một số trường hợp, sự cố tràn với char
s (hoặc thậm chí short
s) sẽ tạo ra các vòng không kết thúc.
Alexey * là đúng, nó thường là nhanh hơn để sử dụng một loại đó là chiều rộng tương tự như kiến trúc (tức là một int32 cho một hệ thống 32 bit)
Ngoài ra, nếu bạn sử dụng một char tức
for(char i=0;i<max;++i)
có một cơ hội nhỏ mà bạn (hoặc một đồng nghiệp) sẽ quay trở lại các mã trong một tháng thời gian và thay đổi tối đa cho một cái gì đó cao, gây ra một tràn và một lỗi gây phiền nhiễu;)
Sam
* và mọi người khác đã trả lời trong khi tôi đang viết bài này!
Bạn có bao giờ chú ý đến tiêu chuẩn C về kiểu số nguyên kích thước không? Thực tế này thúc đẩy các kỹ sư điều khiển thiết bị và những người làm việc trên các giao thức truyền thông trở nên chóng mặt khi họ tin rằng ngôn ngữ nên xác định rõ ràng kích thước của các đối tượng.
C cho biết rằng int
là kích thước tự nhiên cho kiến trúc triển khai. Điều đó có nghĩa là nó sẽ được xử lý ít nhất hiệu quả như bất kỳ kích thước nào khác. Lấy kiến trúc x86: A short
(số nguyên 16 bit) được sử dụng trong chương trình 32 bit chứa các lệnh thực hiện sửa đổi bổ sung "ghi đè kích thước" bổ sung. Vì vậy, mã có nhiều byte hơn, mặc dù thường không có hình phạt hiệu suất.Trừ khi các byte thừa gây tràn dòng bộ nhớ cache ....
Mã được tạo x86 cho số char
thường bao gồm mặt nạ sau khi tăng để đảm bảo nó vẫn còn 8 bit. Dường như việc sử dụng một biến nhỏ hơn sẽ nhỏ hơn và chặt chẽ hơn, nhưng đó không phải là trường hợp đối với x86 và một số CPU phổ biến khác.
Nó thực sự phụ thuộc vào nền tảng mà bạn đang viết để viết mã. Loại tốt nhất để sử dụng là kết hợp nó với nền tảng của bạn. Tức là, nếu bạn đang viết mã cho một vi 8bit đơn giản, có lẽ sử dụng uint8_t là tốt hơn so với sử dụng uint16_t.
Lo lắng về việc nhận vòng của bạn ngay trước khi lo lắng về công cụ này. Bạn có nhiều khả năng có lỗi off-by-one trong giới hạn vòng lặp của bạn hơn là sự khác biệt có thể đo lường về tốc độ hoặc kích thước mã bằng cách thay đổi loại bộ đếm vòng lặp giữa int
, char
hoặc short
. Vì vậy, lo lắng về sự chính xác đầu tiên.
Điều đó nói rằng, mặc định để sử dụng int
hay unsigned int
trừ khi bạn có lý do để làm khác đi - nhưng tôi nói điều này bởi vì bạn ít có khả năng cần phải lo lắng về tràn hoặc quấn xung quanh với các loại lớn hơn không phải vì nó có thể là nhanh hơn (mặc dù nó có thể).
Nó thực sự phụ thuộc vào vòng lặp của bạn đang làm gì. Thực hiện vòng lặp này ví dụ:
typedef struct _SomeData
{
/* some data here */
} SomeData;
void SomeFunction (SomeData *array_of_data, int number_of_elements)
{
int i;
for (i = 0 ; i < number_of_elements ; ++i)
{
DoSomethingWithData (&array_of_data [i]);
}
}
Một số trình biên dịch sẽ làm tốt công việc tối ưu hóa ở trên. Nhưng một số trình biên dịch, đặc biệt là các trình biên dịch cho các bộ vi xử lý nhúng thích hợp, sẽ tạo ra mã không hiệu quả khủng khiếp. Nó có thể được viết lại như sau:
void SomeFunction (SomeData *array_of_data, int number_of_elements)
{
SomeData *current = array_of_data, *end = &array_of_data [number_of_elements];
while (current < end)
{
DoSomethingWithData (current++);
}
}
mà không sử dụng số nguyên ở tất cả và có nhiều khả năng để tạo ra sản lượng tốt không phụ thuộc vào trình biên dịch (trình biên dịch hiện đại có khả năng tối ưu hóa phiên bản nguyên một cái gì đó giống như trên dù sao).
Vì vậy, các số nguyên không phải lúc nào cũng cần thiết cho các vòng lặp và tối ưu hóa tốt nhất luôn không làm điều gì đó không cần thiết. Tuy nhiên, nếu vòng lặp rõ ràng cần số nguyên thì kiểu int thường sẽ cung cấp kết quả tốt nhất.
Tất nhiên, bạn phải luôn sử dụng một trình hồ sơ để chắc chắn về hiệu suất của mã và có hay không thay đổi loại tạo ra bất kỳ sự khác biệt nào.
Thông thường, int là lựa chọn đúng cho vòng lặp. Có hai lý do có thể không phải là:
- Nó có thể lớn hơn mức cần thiết. SDCC hỗ trợ một số bộ xử lý 8 bit như Z80, cho phép truy cập 8 bit vào thanh ghi, mặc dù sizeof (int) = 2. Nếu bạn không cần nhiều hơn 8 bit cho biến vòng lặp của bạn, sau đó sử dụng ký tự, với sizeof (char) = 1, cho phép trình tối ưu hóa nhồi nhét nhiều hơn vào không gian đăng ký, dẫn đến mã nhanh hơn.
- Nó có thể quá nhỏ. Nếu ints là 16 bit, thì bạn cũng có thể có các vòng chạy nhiều hơn nhiều lần.
Vì vậy, có, bạn có thể phải suy nghĩ về mức độ lớn, tùy thuộc vào kiến trúc của bạn. Nhưng thường thì bạn thì không.
- 1. Vòng lặp bằng cách sử dụng các số nguyên không?
- 2. Tại sao số nguyên luôn được sử dụng làm biến kiểm soát trong vòng lặp for?
- 3. Đối với điều kiện vòng lặp dừng ở 0 khi sử dụng các số nguyên không dấu?
- 4. Có tốt hơn khi sử dụng lại một StringBuilder trong một vòng lặp không?
- 5. Số biến số lồng nhau cho vòng lặp
- 6. Làm thế nào để có được chỉ số vòng lặp hiện tại khi sử dụng Iterator?
- 7. đóng trong vòng lặp for - gọi lại với biến vòng lặp làm tham số
- 8. Làm cách nào để kiểm soát nhiều hơn các gia số vòng lặp trong Python?
- 9. Khi vòng lặp với if-statement nhanh hơn vòng lặp
- 10. Các số ngẫu nhiên giống nhau lặp lại vòng lặp
- 11. Xác định lại biến số let'd trong vòng lặp Clojure
- 12. Lua có sử dụng các số nguyên 64 bit không?
- 13. Sử dụng cin.get để lấy số nguyên
- 14. Mảng hoặc mảng cấu trúc số nguyên - tốt hơn?
- 15. Tại sao vòng lặp trên phạm vi() bằng Python nhanh hơn sử dụng vòng lặp while?
- 16. JMeter - bộ điều khiển vòng lặp với số vòng lặp biến
- 17. Chạy tổng số trong gấu trúc (không có vòng lặp)
- 18. jQuery mỗi vòng lặp - sử dụng các biến
- 19. Số lượng biến được lồng trong vòng lặp
- 20. JSLint - Không làm biến đổi tham số <x> khi sử dụng 'đối số'?
- 21. Có sử dụng thực thi không đúng số nguyên không?
- 22. Sử dụng các số nguyên và số double cho các câu trả lời khác nhau khi chúng không nên
- 23. sử dụng intval & real_escape_string khi vệ sinh các số nguyên
- 24. Có tham số nào tôi có thể sử dụng trong Java hoạt động với tất cả các vòng lặp cho mỗi vòng không?
- 25. Sử dụng biến chuỗi ** kwargs làm đối số có tên
- 26. Sử dụng số nguyên làm khóa băm
- 27. Có lợi thế nào khi sử dụng các số nguyên không cố định (int, long) thay vì các số nguyên cố định (int64_t, int32_t) không?
- 28. Mockito sử dụng đối số đối sánh khi gọi phương thức có số biến đối số
- 29. Vòng lặp trò chơi tốt hơn so với vòng lặp vô tận + khối?
- 30. Ưu điểm của chức năng "áp dụng" là gì? Khi nào thì tốt hơn nên sử dụng hơn là "cho" vòng lặp, và khi nào thì không?
Bạn là chính xác, nhưng có rất nhiều vi điều khiển 8 bit (nhiều hơn so với máy tính và máy chủ với nhau), mà không thể phù hợp với một int trong một đăng ký duy nhất. Có lẽ một 'uint8_fast_t' là tốt nhất cho hiệu suất – 12431234123412341234123