2010-11-17 32 views
16

Thường có những lúc bạn biết thực tế là vòng lặp của bạn sẽ không bao giờ chạy nhiều hơn x số lần x có thể được biểu diễn bằng byte hoặc ngắn, về cơ bản là kiểu dữ liệu nhỏ hơn int.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?

Tại sao chúng tôi sử dụng int trong đó chiếm 32 bit (với hầu hết các ngôn ngữ) khi một cái gì đó giống như một byte sẽ đủ mà chỉ là 8 bit.

Tôi biết chúng tôi có quy trình 32 bit và 64 bit để chúng tôi có thể dễ dàng tìm nạp giá trị trong một chuyến đi nhưng nó vẫn tiêu thụ nhiều bộ nhớ hơn. Hoặc tôi đang thiếu gì ở đây?

CẬP NHẬT: Chỉ cần làm rõ. Tôi biết rằng tốc độ khôn ngoan không có sự khác biệt. Tôi hỏi về tác động của việc tiêu thụ bộ nhớ.

+0

Thật sao? Hầu hết các mã tôi đã nhìn thấy sử dụng một số hình thức loại unsigned. –

+1

@Billy Oneal: Trên một số vi xử lý nhúng, một loại không dấu có thể cung cấp hiệu suất tốt hơn so với một ký kết, với chi phí yêu cầu chăm sóc lớn hơn với logic chấm dứt vòng lặp. Mặt khác, nếu một bộ xử lý giống như ARM lưu trữ thứ gì đó giống như uint16 trong thanh ghi 32 bit, nó phải thêm mã phụ để 'clip' giá trị thành 16 bit. Không có mã như vậy sẽ là cần thiết với một int16 (vì bất cứ điều gì được phép xảy ra khi một int16 được gán một giá trị ngoài phạm vi -32768..32767, một trình biên dịch có thể chỉ để cho giá trị của nó làm bất cứ điều gì thuận tiện). – supercat

+2

Bạn có tạo các bộ đếm vòng lặp đủ để thay đổi loại của chúng có hiệu ứng * nhìn thấy được trên bộ nhớ tiêu thụ không? Nếu vậy, sau đó tôi gửi cho bạn có vấn đề lớn hơn so với chỉ sử dụng một loại rộng hơn-cần thiết. –

Trả lời

27

Trong C, một "int" được định nghĩa là các loại nguyên hiệu quả nhất cho các máy tính hiện hành.

Nó thường phù hợp với sổ đăng ký của CPU, đó là cách nó hiệu quả nhất.

Sử dụng một loại nhỏ hơn của giá trị số nguyên có thể dẫn đến một số bit chuyển hoặc chút che ở cấp CPU do đó bạn sẽ không nhận được lợi ...

+11

Thực ra, nó được định nghĩa là "kích thước từ tự nhiên", có thể hoặc không phải là loại hiệu quả nhất. Đối với loại hiệu quả nhất, hãy sử dụng fastint_t của C99. –

+1

Điều gì đó về việc làm sáng tỏ các chi tiết về lập trình này thực sự thú vị – sova

+0

Tôi đã hỏi nhiều hơn về mức tiêu thụ bộ nhớ. – uriDium

6

Trong nhiều trường hợp, bộ đếm vòng lặp tiêu thụ chính xác một thanh ghi bộ xử lý. Việc thay đổi kiểu thành số nguyên 8 hoặc 16 bit không thay đổi điều đó, vì thanh ghi có kích thước cố định (32 bit trên nền tảng 32 bit, v.v.).

Đôi khi, bộ đếm vòng lặp có thể được đặt trong RAM, ví dụ: khi bạn đang gọi một hàm từ vòng lặp. Sau đó, có, bạn có thể lãng phí một vài byte, nhưng nói chung là không đủ để lo lắng về. Việc lưu trữ và nạp bộ đếm vòng lặp thực tế có thể chậm hơn khi sử dụng một thứ gì đó khác với int.

8

Truy cập kích thước số nguyên có cùng kích thước với kích thước từ gốc sẽ hiệu quả nhất. Sử dụng một byte gần như chắc chắn sẽ đòi hỏi nhiều không gian như kích thước từ gốc và yêu cầu dịch chuyển và mặt nạ để truy cập, vì vậy không có gì để đạt được.

Trong điều khoản thực tế, trừ khi bạn có vòng lặp rất, rất lớn hoặc hạn chế thời gian khắc nghiệt, nó sẽ không tạo ra nhiều khác biệt.

Nhưng như mọi khi, sử dụng bất cứ điều gì là có thể đọc được hầu hết, và benchmark/profile đầu tiên ...

+0

Tôi rất nghi ngờ rằng một trình biên dịch tối ưu hóa sẽ không chỉ đơn giản là phân bổ một 'int' của không gian cho' char' nếu trong thực tế 'int' là hiệu quả hơn. OTOH, trên hầu hết các kiến ​​trúc mà tôi biết không có sự khác biệt về tốc độ giữa 'int' và' char'. –

7

Tôi gần như luôn luôn sử dụng int trừ khi có một lý do rất tốt không, bởi vì mọi người luôn sử dụng nó. Điều này là để tránh các nhà phát triển tiếp theo phải dành thời gian suy nghĩ Tại sao ông không sử dụng một int ở đây, có một số lý do đặc biệt tôi cần phải biết về.

tiêu chuẩn mã của tôi càng dễ đọc trong tương lai.

+1

Điểm tốt. Hầu hết mọi người đều biết và cũng có thể hiểu cú pháp i ++. –

4

Xét về mặt Java Language Specification có một điểm thú vị cần lưu ý về việc sử dụng các longdouble:

Đối với các mục đích của Java lập trình mô hình bộ nhớ ngôn ngữ, một đơn ghi vào một phi Biến động dài hoặc giá trị tăng gấp đôi được coi là hai ghi riêng biệt: một cho mỗi 32-bit một nửa.Điều này có thể dẫn đến tình huống trong đó một chuỗi thấy 32 bit đầu tiên giá trị 64 bit từ một lần ghi và 32 bit thứ hai từ một lần ghi khác. Ghi và đọc các giá trị biến động dài và đôi luôn là nguyên tử. Ghi và đọc tham chiếu là luôn là nguyên tử, bất kể là chúng được triển khai dưới dạng giá trị 32 hoặc 64 bit . Người triển khai máy ảo được khuyến khích để tránh chia tách các giá trị 64 bit của chúng nếu có thể. Các lập trình viên là được khuyến khích khai báo các giá trị được chia sẻ 64 bit như dễ bay hơi hoặc đồng bộ hóa các chương trình của chúng một cách chính xác để tránh các biến chứng có thể xảy ra .

Rõ ràng điều này làm cho sử dụng một long hoặc double trong biến vòng lặp của bạn kém hiệu quả hơn so với một int trong mô hình bộ nhớ Java, nhưng hiện thực có thể thay đổi trong hoạt động.

0

Tôi bị cám dỗ thêm nội dung nào đó vào đây ngay cả khi đó là một chuỗi rất cũ. Tôi không hoàn toàn đồng ý với "Tôi biết rằng tốc độ khôn ngoan không có sự khác biệt". Trên thực tế, rất thường xuyên trong vòng lặp for có mảng lập chỉ mục như trong

for (i=0; i<len; i++) s = A[i] 

Sau đó, ngay cả khi mảng của bạn có kích thước ít mà 128, bạn sẽ thấy một sự khác biệt tốc độ đáng chú ý dù i là một int hay byte. Thật vậy, để thực hiện số học con trỏ trong A[i] bộ vi xử lý phải chuyển đổi số nguyên của bạn thành một số có cùng kích thước với con trỏ. Nếu số nguyên đã có cùng kích thước, thì không có chuyển đổi nào tạo ra mã nhanh hơn. Trên máy 64 bit, tôi có vẻ 20% tăng tốc trên các chương trình bằng cách sử dụng long int cho chỉ mục vòng lặp trên mảng rất nhỏ thay vì char (chương trình C/C++).

+0

Điều đó thật thú vị. Cảm ơn – uriDium

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