2012-04-11 22 views
19

Tôi đã đọc lệnh INC của x86 không phải là nguyên tử. Câu hỏi của tôi là thế nào? Giả sử chúng ta đang tăng số nguyên 64 bit trên x86-64, chúng ta có thể làm điều đó với một lệnh, vì lệnh INC làm việc với cả hai biến bộ nhớ và đăng ký. Vì vậy, làm thế nào đến nó không nguyên tử?Làm thế nào đến lệnh INC của x86 không phải là nguyên tử?

+3

Vâng, nó là nguyên tử_, nếu bạn đặt tiền tố nó bằng LOCK. Thường thì đó không phải là điều người ta muốn, bởi vì nó khá đắt. Vì vậy, bạn cần phải làm rõ những gì bạn muốn. – Damon

+0

một từ: đường ống –

+4

Nguyên tử không có nghĩa là đó là một chỉ dẫn, điều đó có nghĩa đó là một hành động không thể tách rời. Và 'inc' với toán hạng bộ nhớ không phải là vậy, không phải theo mặc định. – harold

Trả lời

18

Tại sao lại như vậy? Lõi xử lý vẫn cần phải đọc giá trị được lưu trữ tại vị trí bộ nhớ, tính toán số gia tăng của nó và sau đó lưu trữ lại. Có độ trễ giữa việc đọc và lưu trữ và trong thời gian đó, một hoạt động khác có thể đã ảnh hưởng đến vị trí bộ nhớ đó.

Ngay cả khi thực hiện ngoài đơn đặt hàng, lõi bộ xử lý đủ 'thông minh' không được thực hiện theo hướng dẫn của riêng họ và sẽ không chịu trách nhiệm sửa đổi bộ nhớ này trong khoảng thời gian. Tuy nhiên, một lõi khác có thể đã ban hành một lệnh điều chỉnh vị trí đó, việc chuyển DMA có thể ảnh hưởng đến vị trí đó hoặc phần cứng khác đã chạm vào vị trí bộ nhớ đó bằng cách nào đó.

+2

Bạn nên hiểu rõ hơn về "hoạt động khác" có nghĩa là gì. Chắc chắn không có hoạt động nào khác có thể xảy ra trên cùng một lõi cpu, chỉ trên lõi/cpus khác hoặc phần cứng khác không quan trọng xung quanh trên bus bộ nhớ. –

+1

Đã cập nhật bài đăng. – Kaganar

1

Bạn thực sự không muốn có một hoạt động nguyên tử được bảo đảm, trừ khi bạn cần nó, từ Agner Fog 's Software optimization resources: instruction_tables.pdf (1996 - 2017):

dẫn với một tiền tố KHÓA có một độ trễ dài mà phụ thuộc vào tổ chức bộ nhớ cache và tốc độ RAM có thể. Nếu có nhiều bộ xử lý hoặc lõi hoặc thiết bị truy cập bộ nhớ trực tiếp (DMA) thì tất cả các hướng dẫn bị khóa sẽ khóa một đường bộ nhớ cache để truy cập độc quyền, có thể liên quan đến truy cập RAM. Tiền tố LOCK thường tốn hơn một trăm chu kỳ đồng hồ, ngay cả trên các hệ thống đơn lẻ . Điều này cũng áp dụng cho lệnh XCHG với toán hạng bộ nhớ.

+1

Thông tin này chắc chắn đã lỗi thời; Một chu trình khóa/mở khóa mutex toàn bộ mất ít hơn 90 chu kỳ trên một máy tôi đã thử nghiệm, và liên quan đến nhiều hoạt động có tiền tố khóa và chi phí đầu vào rdtsc. Thử nghiệm với một khóa inc duy nhất hướng dẫn giữa rdtsc, tôi đã không thể thậm chí đo nó lấy bất cứ lúc nào (cùng thời gian như nop). Trên cpus hiện đại, có vẻ như tiền tố khóa không tăng thời gian trừ khi bộ nhớ hiện được chia sẻ với các lõi khác. –

+0

@R .. - x86-64 đã có sẵn từ năm 2003, do đó, nó có thể là một tuyên bố chăn. Tôi tự hỏi làm thế nào nó sẽ ảnh hưởng đến một chuyển đổi tạm dừng/ctx đang chờ giải quyết. –

+3

@R .. Vâng, ít hơn 90 và hơn 100 không phải là xa nhau :-) – hirschhornsalz

18

Bộ vi xử lý x86 hiện đại là một phần của hướng dẫn thực hiện "biên dịch" x86 hướng dẫn của họ thành một nhóm hoạt động cấp thấp hơn; Intel gọi các uOps này, AMD rOps, nhưng những gì nó chỉ là một loại hướng dẫn x86 đơn được thực thi bởi các đơn vị chức năng thực tế trong CPU là một vài bước.
Điều đó có nghĩa, ví dụ, rằng:

INC EAX 

được thi hành dưới dạng đĩa đơn "mini-op" như uOp.inc eax (hãy để tôi gọi nó đó - họ không tiếp xúc).
Đối với toán hạng thứ khác sẽ tìm cách khác nhau, như:

INC DWORD PTR [ EAX ] 

quá trình phân hủy ở mức độ thấp mặc dù sẽ trông giống như:

uOp.load tmp_reg, [ EAX ] 
uOp.inc tmp_reg 
uOp.store [ EAX ], tmp_reg 

và do đó không thực hiện nguyên tử. Mặt khác, nếu bạn tiền tố bằng cách nói LOCK INC [ EAX ], điều đó sẽ cho giai đoạn "biên dịch" của đường ống phân hủy theo cách khác để đảm bảo yêu cầu về nguyên tử được đáp ứng.

Lý do cho điều này tất nhiên là được đề cập bởi những người khác - tốc độ; tại sao làm một cái gì đó nguyên tử và nhất thiết phải chậm hơn nếu không phải luôn luôn yêu cầu?

+2

Phân tích "mini-op" không liên quan đến nguyên tử, vì một lõi cpu đơn lẻ không thể bị gián đoạn giữa lệnh. Trong thực tế, không có tiền tố khóa là hoàn toàn nguyên tử trên các máy đơn lõi. Chỉ khi các lõi khác (hoặc nhiều phần cứng hơn, phần cứng khác trên bus) có thể truy cập vào bộ nhớ mà tiền tố khóa quan trọng. –

+1

@R ..: Gợi ý như vậy, _any_ sửa đổi-mem cpu op trên lõi đơn là nguyên tử không có vấn đề làm thế nào thực hiện. Nhưng ngay cả các máy đơn lõi cũng không phải là "đơn" ngày nay bởi vì bus busing DMA/bus bus được chia sẻ với các thiết bị ngoại vi đảm bảo sự hiện diện của sự kết hợp bộ nhớ cache và các vấn đề nguyên tử. Luôn có nhiều hơn một ứng dụng bus bộ nhớ. Do đó, tải/cửa hàng là, trên mức độ bus bộ nhớ, _always_ bị phân tách ngay cả khi chúng xảy ra như là một phần của lệnh cpu "đơn". Nguyên tử phải được khẳng định (truy cập bus bộ nhớ độc quyền); CPU không thể thực hiện một sửa đổi-mem như tải/thay đổi/lưu trữ nhưng phải đóng khung với khóa/mở khóa bus. Ví dụ: –

+0

@R ..: CPU ARM, hiển thị rõ ràng khóa buýt cần cho atomixity ở cấp bộ lệnh thông qua 'LDREX' /' STREX'. Chỉ cần từ thực tế x86 không có hướng dẫn mem-sửa đổi người ta không thể kết luận sự cần thiết cho nhân chứng không có. Ngoài ra, câu hỏi không phải là gián đoạn giữa hướng dẫn - điều đó không giống như nguyên tử. Sự phân tách có ý nghĩa mạnh mẽ theo nghĩa đó bởi vì các truy cập bộ nhớ của lệnh _single_ có thể _race_ với các CPU khác. Lệnh hoàn thành (không có bẫy yêu cầu khởi động lại) nhưng kết quả (không có 'khóa') không phải là duy nhất/xác định. –

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