2010-12-27 9 views

Trả lời

1

Caveat: Tôi không có chuyên gia trong lĩnh vực này. Tôi vẫn đang cố gắng tự mình học điều này. Nhưng vì không ai trả lời trong hai ngày qua, có vẻ như các chuyên gia về hướng dẫn hàng rào bộ nhớ không dồi dào. Vì vậy, đây là sự hiểu biết của tôi ...

Intel là hệ thống bộ nhớ weakly-ordered. Điều đó có nghĩa chương trình của bạn có thể thực hiện

array[idx+1] = something 
idx++ 

nhưng sự thay đổi để idx có thể được hiển thị trên toàn cầu (ví dụ như để đề/tiến trình đang chạy trên bộ vi xử lý khác) trước khi thay đổi để mảng. Đặt sfence giữa hai câu lệnh sẽ đảm bảo thứ tự ghi được gửi đến FSB.

Trong khi đó, bộ xử lý khác chạy

newestthing = array[idx] 

có thể lưu trữ bộ nhớ cho mảng và có một bản sao cũ, nhưng được cập nhật idx do bỏ lỡ bộ nhớ cache. Giải pháp là sử dụng lfence trước để đảm bảo tải được đồng bộ hóa.

This article hoặc this article có thể đưa ra thông tin tốt hơn

+0

Không, các cửa hàng x86 được đặt hàng mạnh theo mặc định. Biên dịch sắp xếp lại thời gian có thể tạo ra sắp xếp lại bạn mô tả (nếu bạn không sử dụng 'std :: atomic' với' memory_order_release' hoặc mạnh hơn), nhưng các cửa hàng từ lệnh x86 'mov [array + rcx], eax' /' mov [idx], rcx' sẽ trở thành hiển thị trên toàn cầu với các chuỗi khác theo thứ tự đó. Chỉ các cửa hàng trực tuyến 'MOVNT' được đặt hàng yếu (vì vậy bạn cần' sfence' sau khi lưu trữ trước cờ 'buffer_ready'). Bạn thường không bao giờ cần 'lfence', trừ khi bạn đang sử dụng tải có thứ tự yếu từ bộ nhớ video hoặc thứ gì đó. –

+0

Xem thêm [câu trả lời của tôi về câu hỏi sfence mới hơn] (https://stackoverflow.com/a/44866652/224132). Ngoài ra, các bài báo tuyệt vời của Jeff Preshing, giống như bài đăng [yếu hơn so với mô hình bộ nhớ mạnh mẽ] (http://preshing.com/20120930/weak-vs-strong-memory-models/). (Nó đã được viết 2 năm sau khi bạn đăng này. Tôi không có ý định thô lỗ về một câu trả lời cũ, nhưng nó gần như hoàn toàn sai, xD) –

+0

@PeterCordes Bạn hoàn toàn sai. 1) bạn không cần std :: nguyên tử để đạt được đúng thứ tự. Trong thực tế std :: nguyên tử không tồn tại cho đến khi C++ 11. Vì vậy, nó đã không tồn tại tại thời điểm bài viết đã được thực hiện. 2) lfence được sử dụng để đảm bảo lệnh hướng dẫn chính xác về phía người tiêu dùng. Vì vậy, nếu bạn muốn đọc bộ đệm của bạn sau khi nhìn thấy lá cờ 'buffer_ready', thì bạn sử dụng lfence để đảm bảo rằng đọc từ bộ đệm không xảy ra trước đó. –

3

Đây là hiểu biết của tôi, hy vọng chính xác và đủ đơn giản để có ý nghĩa:

(Itanium) kiến ​​trúc IA64 cho phép bộ nhớ đọc và viết được thực hiện theo thứ tự nào, do đó thứ tự thay đổi bộ nhớ từ quan điểm của bộ xử lý khác không thể dự đoán được trừ khi bạn sử dụng hàng rào để thực thi việc ghi hoàn thành theo thứ tự hợp lý.

Từ đây, tôi đang nói về x86, x86 được sắp xếp mạnh mẽ.

Trên x86, Intel không đảm bảo rằng cửa hàng được thực hiện trên bộ xử lý khác sẽ luôn hiển thị ngay trên bộ xử lý này. Có thể là bộ vi xử lý này đã thực thi việc tải (đọc) chỉ đủ sớm để bỏ lỡ cửa hàng của bộ xử lý khác (ghi).

Lệnh đọc/sửa đổi/ghi bị khóa hoàn toàn tương thích tuần tự, vì vậy bạn hiếm khi thực sự phải sử dụng hàng rào trên x86. Bởi vì điều này, nói chung bạn đã xử lý thiếu các hoạt động bộ nhớ của bộ xử lý khác bởi vì một xchg bị khóa hoặc cmpxchg sẽ đồng bộ hóa tất cả.

Theo như tôi hiểu, lfence thoát hàng đợi tải bộ nhớ và chờ đường ống của đơn vị tải để hoàn tất bất kỳ hoạt động nào đang được tiến hành. mfence đi xa hơn và chờ đợi cho tất cả bộ nhớ đọc và viết, sfence làm tương tự cho chỉ các cửa hàng (và flushes viết combiner).

Về bản chất, lfence loại bỏ bất kỳ tải được thực thi đầu tiên nào.Các tải có thể đã được thực thi trước đó sẽ được cấp lại. sfence là ít nhất cần thiết trong thực tế, thường là không cần thiết trừ khi sử dụng bộ nhớ kết hợp ghi, một cái gì đó bạn hiếm khi làm nếu bạn không phải là nhà phát triển chế độ hạt nhân (trình điều khiển). Vì vậy, để tóm tắt, các thuật toán sử dụng các lệnh bị khóa như xchg, hoặc xadd, hoặc cmpxchg, vv, sẽ hoạt động mà không có hàng rào vì lệnh đã khóa (trong hầu hết các trường hợp) làm mọi thứ để đồng bộ hóa. Bất kỳ mã không có khóa nào khó hiểu (ví dụ) có các đường dẫn mã đầu ra không sử dụng các lệnh khóa đó có thể cần một nơi nào đó để tránh thiếu một cửa hàng được thực hiện bởi một bộ xử lý khác. Mã mà cảm ứng là hiếm và không phải là một thực hành tốt nhưng có thể là cần thiết trong đường dẫn mã cực kỳ nóng.

+0

Bạn thường không cần 'lfence' bao giờ hết. Bạn chỉ cần 'sfence' [sau khi các cửa hàng trực tuyến' movnt' được đặt hàng yếu ớt] (https://stackoverflow.com/a/44866652/224132). Bạn cần 'mfence' (hoặc một hoạt động' khóa') để có được tính nhất quán tuần tự thay vì chỉ phát hành/có được. (Xem [Memory Reordering Caught in the Act] (http://preshing.com/20120515/memory-reordering-caught-in-the-act/) để biết ví dụ.) –

+0

Bạn thường cần 'lfence' vì trình biên dịch C++. –