Phát hiện tràn trong tổng kết


8

Giả sử tôi đưa ra một loạt các cố định chiều rộng số nguyên (tức là họ phù hợp trong một thanh ghi chiều rộng ), một 1 , một 2 , ... một n . Tôi muốn để tính tổng S = một 1 + ... + một n trên một máy với số học bổ sung 2 của, thực hiện bổ sung theo modulo 2 w với ngữ nghĩa bao quanh. Điều đó thật dễ dàng - nhưng tổng có thể vượt quá kích thước đăng ký và nếu có, kết quả sẽ sai.nwmột1,một2,Giáo dụcmộtnS= =một1+Giáo dục+mộtn2w

Nếu tổng không tràn, tôi muốn tính toán và để xác minh rằng không có tràn, càng nhanh càng tốt. Nếu tổng tiền tràn ra, tôi chỉ muốn biết rằng nó có, tôi không quan tâm đến bất kỳ giá trị nào.

Thêm các số theo thứ tự không hoạt động, bởi vì một phần tổng có thể tràn. Ví dụ: với các thanh ghi 8 bit, là hợp lệ và có tổng bằng , mặc dù tổng một phần vượt quá phạm vi thanh ghi .(120,120,-115)125120+120[-128,127]

Rõ ràng tôi có thể sử dụng một thanh ghi lớn hơn như một bộ tích lũy, nhưng hãy giả sử trường hợp thú vị khi tôi đã sử dụng kích thước đăng ký lớn nhất có thể.

Có một kỹ thuật nổi tiếng để thêm các số có dấu ngược lại là tổng một phần hiện tại . Kỹ thuật này tránh tràn ra ở mọi bước, với chi phí không thân thiện với bộ đệm và không tận dụng nhiều lợi thế của dự đoán nhánh và thực hiện đầu cơ.

Có một kỹ thuật nhanh hơn có lẽ tận dụng sự cho phép để vượt qua các khoản tiền một phần, và nhanh hơn trên một máy điển hình với cờ tràn, bộ đệm, bộ dự báo nhánh và thực hiện đầu cơ và tải?

(Đây là phần tiếp theo để tóm tắt an toàn tràn )


Tại sao giải pháp của Dave không hoạt động tốt với bộ nhớ cache và đường ống theo ý kiến ​​của bạn? Nếu bạn làm một cái gì đó tương tự như phân vùng Quicksort tại chỗ với trục ảo , bạn sẽ xử lý bộ nhớ cache tốt trong cả phân vùng và tổng kết sau. Tôi không biết về các dự đoán sai trong quá trình phân vùng, nhưng giai đoạn tổng hợp cũng sẽ làm tốt trong vấn đề đó. 0
Raphael

@Raphael Trong ứng dụng của tôi, tràn là trường hợp đặc biệt. Các điều kiện tương ứng với trên mạng này có tràn không? do đó được phục vụ tốt bởi dự đoán chi nhánh. Điều kiện tương ứng với số này có phải là số dương không? không thể dự đoán được. Hiệu ứng bộ đệm thực sự rất nhẹ khi bạn có hai con trỏ thay vì một.
Gilles 'SO- ngừng trở nên xấu xa'

Câu trả lời:


3

nwđăng nhậpn+w

Nếu dữ liệu không phù hợp với bộ nhớ, yếu tố giới hạn sẽ là IO và mức độ thành công của bạn trong việc chồng chéo IO với tính toán.

đăng nhậpnww-bits số học có thể chỉ là hai hướng dẫn (một để ký mở rộng, một để thêm mang theo) và tăng áp lực đăng ký một chút (nhưng nếu tôi đúng, ngay cả thanh ghi bị bỏ đói x86 cũng có đủ các thanh ghi mà chỉ có quyền truy cập bộ nhớ trong vòng lặp bên trong có thể tìm nạp dữ liệu). Tôi nghĩ có khả năng bộ xử lý OO sẽ có thể lên lịch các hoạt động bổ sung trong thời gian trễ tải bộ nhớ để vòng lặp bên trong sẽ được thực thi ở tốc độ bộ nhớ và do đó bài tập sẽ tối đa hóa việc sử dụng băng thông có sẵn (tìm nạp trước hoặc kỹ thuật xen kẽ có thể giúp tùy thuộc vào kiến ​​trúc bộ nhớ).

Xem xét điểm mới nhất, thật khó để nghĩ về các thuật toán khác với hiệu suất tốt hơn. Các bước nhảy phụ thuộc vào dữ liệu (và do đó không thể dự đoán được) sẽ không còn tồn tại nữa. Ngay cả việc cố gắng sử dụng một số lõi của bộ xử lý ngày nay cũng khó khăn vì băng thông bộ nhớ có thể sẽ bị bão hòa, nhưng nó có thể là một cách dễ dàng để thực hiện truy cập xen kẽ.


Tôi không thể tăng kích thước của các thanh ghi trên máy của mình. Giả sử tôi đã sử dụng kích thước đăng ký lớn nhất có thể.
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles, bộ xử lý Tôi biết có cờ tràn mà bạn muốn chúng tôi tận dụng cũng có một carry và add với hướng dẫn carry . Ngay cả đối với những người không (ngoài MIPS?), Số học đa số sẽ là một ứng cử viên nặng ký (nó chỉ có một lần truyền dữ liệu - tốt cho bộ đệm -, truy cập tuần tự - tốt cho trình điền trước bộ đệm - -, và có thể được thực hiện mà không có bước nhảy phụ thuộc dữ liệu - tốt cho người dự đoán bước nhảy).
AProgrammer

Bạn có ý nghĩa gì với số học đa số của người Hồi giáo? Tôi nghĩ bạn có nghĩa là điểm nổi. Nhưng nhiều kiến ​​trúc không có các thanh ghi dấu phẩy động đủ lớn, nếu có. Giả sử tôi đang thêm số nguyên 64 bit trên amd64 hoặc số nguyên 32 bit trên ARM mà không có VFP.
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles, ý tôi là những gì được mô tả trong phần 4.3 của TAOCP: việc sử dụng một số từ để biểu thị các giá trị không thể giữ trong một từ. Bignum là một biến thể trong đó số lượng từ được điều chỉnh động, tôi đoán là ở đây bạn có thể xác định giới hạn tối đa cho số lượng từ cần thiết (nghĩa là 2 nếu dữ liệu của bạn nằm trong bộ nhớ; nếu không, nó hoạt động chồng chéo IO với tính toán sẽ là điểm hành động đầu tiên, bạn sẽ bị ràng buộc IO) và chỉ cần sử dụng nó, nó sẽ đủ thấp để xử lý một số lượng từ khác nhau sẽ tốn kém hơn.
AProgrammer

À, được rồi Bạn có thể làm rõ điều này trong câu trả lời của bạn? Bạn có tài liệu tham khảo với thời gian và so sánh với các phương pháp khác?
Gilles 'SO- ngừng trở nên xấu xa'

1

Trên một máy mà các kiểu số nguyên hoạt động như một vòng đại số trừu tượng [về cơ bản có nghĩa là chúng bao bọc], người ta có thể tính tổng của vật phẩm [i] và (vật phẩm [i] >> 16) cho tối đa khoảng 32767 vật phẩm. Giá trị đầu tiên sẽ cho 32 bit thấp hơn của tổng chính xác. Giá trị sau sẽ mang lại các bit 16-47 của một số gần với tổng chính xác và bằng cách sử dụng giá trị cũ, nó có thể dễ dàng được điều chỉnh để mang lại các bit 16-47 của tổng chính xác.

Mã giả sẽ là một cái gì đó như:

Sum1=0 : Sum2 = 0
For up to 32768 items L[i] in list
  Sum1 = Sum1 +L[i]
  Sum2 = Sum2 +(L[i] >> 16) ' Use sign-extending shift
Loop
Sum1MSB = Sum1 >> 16 ' Cannot use division of numbers can be negative--see below
Sum2Mid = Sum2 and 65535
Sum2Adj = Sum1MSB - Sum2Mid
If Sum2Adj >= 32768 then Sum2Adj = Sum2Adj - 65536
Sum2 += Sum2Adj

Sau đoạn mã trên, Sum2 và Sum1 cùng nhau sẽ mang lại tổng chính xác, bất kể sự can thiệp tràn. Nếu cần tổng cộng hơn 32768 số, chúng có thể được chia thành các nhóm 32768 và sau khi tính Sum2 cho mỗi nhóm, người ta có thể thêm nó vào một "tổng lớn" hai biến cho tất cả các nhóm nói chung.

Trong một số ngôn ngữ, toán tử quyền dịch chuyển có thể được thay thế bằng một phép chia bằng 65536. Điều đó thường hoạt động khi tính toán Sum2, nhưng không phải khi trích xuất Sum1MSB. Vấn đề là một số ngôn ngữ làm tròn các phân chia về 0 trong khi ở đây cần thiết để thực hiện phân chia làm tròn đến số thấp hơn tiếp theo (về vô cực âm). Lỗi tính toán Sum2 sẽ được sửa chữa sau này, nhưng lỗi tính toán Sum2LSB sẽ ảnh hưởng đến kết quả cuối cùng.

Lưu ý rằng không có gì trong kết quả cuối cùng sẽ cho biết liệu bất kỳ tính toán nào liên quan đến Sum1 có "tràn" hay không, nhưng nếu các giá trị được đảm bảo bọc mã sạch thì không cần quan tâm đến việc có xảy ra tràn không.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.