2012-10-15 36 views
37

Tôi đang cố gắng tạo ra một phiên bản câm của khóa quay. Duyệt web, tôi đi qua một hướng dẫn lắp ráp được gọi là "PAUSE" trong x86 được sử dụng để gợi ý cho một bộ xử lý mà một spin-lock hiện đang chạy trên CPU này. Hướng dẫn sử dụng trực tuyến và các thông tin khác có sẵn màMục đích của lệnh "PAUSE" trong x86 là gì?

Bộ vi xử lý sử dụng gợi ý này để giúp cải thiện hiệu suất của bộ xử lý. Đối với lý do này, bạn nên đặt lệnh PAUSE trong tất cả các vòng quay chờ. Tài liệu cũng đề cập rằng "chờ đợi (một số chậm trễ)" là việc thực hiện giả của lệnh.

Dòng cuối cùng của đoạn trên là trực quan. Nếu tôi không thành công trong việc lấy khóa, tôi phải đợi một lúc trước khi lấy lại khóa.

Tuy nhiên, chúng tôi có ý nghĩa gì khi vi phạm thứ tự bộ nhớ trong trường hợp khóa quay? "Vi phạm thứ tự bộ nhớ" có nghĩa là nhập sai đầu cơ tải/lưu trữ hướng dẫn sau khi quay-khóa không?

Câu hỏi spin-lock đã được hỏi về tràn ngăn xếp trước đó nhưng câu hỏi vi phạm thứ tự bộ nhớ vẫn chưa được trả lời (ít nhất là đối với sự hiểu biết của tôi).

Trả lời

58

Chỉ cần tưởng tượng, cách thức xử lý sẽ thực hiện một điển hình vòng spin-wait:

1 Spin_Lock: 
2 CMP lockvar, 0 ; Check if lock is free 
3 JE Get_Lock 
4 JMP Spin_Lock 
5 Get_Lock: 

Sau một vài lần lặp các dự báo chi nhánh sẽ dự đoán rằng chi nhánh có điều kiện (3) sẽ không bao giờ được thực hiện và các đường ống dẫn sẽ điền với hướng dẫn CMP (2). Điều này tiếp tục cho đến khi cuối cùng một bộ xử lý ghi một số không để lockvar. Tại thời điểm này, chúng tôi có đường dẫn đầy đủ của đầu cơ (nghĩa là chưa cam kết) CMP hướng dẫn một số đã đọc lockvar và báo cáo kết quả không đồng bộ (không chính xác) cho nhánh có điều kiện sau (3) (cũng có tính đầu cơ). Đây là khi vi phạm thứ tự bộ nhớ xảy ra. Bất cứ khi nào bộ xử lý "nhìn thấy" một ghi bên ngoài (một ghi từ một bộ xử lý khác), nó tìm kiếm trong đường dẫn của nó để được hướng dẫn truy cập một cách speculatively cùng một vị trí bộ nhớ và vẫn chưa cam kết. Nếu tìm thấy bất kỳ hướng dẫn nào như vậy thì trạng thái đầu cơ của bộ xử lý không hợp lệ và được xóa với một đường ống xả.

Thật không may, kịch bản này sẽ (rất có thể) lặp lại mỗi lần bộ xử lý đang đợi trên khóa quay và làm cho các ổ khóa này chậm hơn nhiều so với chúng phải là.

Nhập lệnh PAUSE:

1 Spin_Lock: 
2 CMP lockvar, 0 ; Check if lock is free 
3 JE Get_Lock 
4 PAUSE   ; Wait for memory pipeline to become empty 
5 JMP Spin_Lock 
6 Get_Lock: 

Các hướng dẫn PAUSE sẽ "de-đường ống" bộ nhớ đọc, do đó các đường ống dẫn không được điền với đầu cơ CMP (2) hướng dẫn như trong ví dụ đầu tiên. Bởi vì các lệnh CMP (2) thực hiện tuần tự nó không chắc (tức là cửa sổ thời gian ngắn hơn nhiều) mà một ghi bên ngoài xảy ra sau khi lệnh CMP (2) đọc lockvar nhưng trước khi CMP được cam kết.

Tất nhiên "de-pipelining" cũng sẽ lãng phí ít năng lượng hơn trong khóa quay và trong trường hợp siêu phân luồng, nó sẽ không lãng phí tài nguyên mà luồng khác có thể sử dụng tốt hơn. Mặt khác, vẫn còn một dự đoán sai chi nhánh chờ đợi xảy ra trước mỗi lần thoát khỏi vòng lặp. Tài liệu của Intel không gợi ý rằng PAUSE loại bỏ đường ống đó, nhưng ai biết được ...

+0

(+1) Cảm ơn bạn đã có câu trả lời tuyệt vời! Những gì tôi không hoàn toàn hiểu là những gì làm cho một đường ống tuôn ra như vậy một chi phí lớn trong tình huống này, cho rằng tất cả những người đọc đầu cơ và speculatively lấy ngành có điều kiện là hoàn toàn vô dụng anyway? Ngoài ra, có cách nào để định lượng chi phí tuôn ra không? – NPE

+4

@NPE Thời gian khôi phục từ tuôn ra phụ thuộc vào kiến ​​trúc vi mô. Các bộ vi xử lý với các đường ống dài hơn (như Core 2) rõ ràng chịu nhiều hơn các đường ống có đường ống ngắn hơn (như Atom). Tuy nhiên, trong trường hợp của một bộ xử lý với siêu phân luồng tất cả các lệnh "vô dụng" thực hiện lấy đi các tài nguyên từ các luồng khác trên cùng một lõi. Hướng dẫn PAUSE về cơ bản cedes cpu đến thread khác. Vì vậy, trong khi chi phí cho các chủ đề bị khóa là "chỉ" hai đường ống xả, chi phí cho các chủ đề khác có thể được nhiều hơn nữa đáng kể (tùy thuộc vào bao nhiêu thời gian được chi tiêu bên trong khóa). –

+0

Bởi vì các lệnh CMP (2) thực thi tuần tự nó không chắc (tức là cửa sổ thời gian ngắn hơn nhiều) một ghi bên ngoài xảy ra sau lệnh CMP (2) đọc lockvar nhưng trước khi CMP được cam kết. Bạn có thể giải thích điều này không? Ý bạn là gì? – KodeWarrior

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