2011-07-25 34 views
8

Tôi đã viết một số mã không có khóa hoạt động tốt với các lần đọc địa phương , trong hầu hết các điều kiện.Ổ khóa có luôn đòi hỏi một rào cản bộ nhớ không? Quay trên hàng rào bộ nhớ có đắt không?

Hiện tại địa phương quay trên bộ nhớ có nhất thiết phải ngụ ý I phải luôn luôn chèn một rào cản bộ nhớ trước khi quay số đọc?

(Để xác nhận điều này, tôi cố gắng tạo ra một đọc/ghi kết hợp mà kết quả trong một người đọc không bao giờ nhìn thấy những giá trị bằng văn bản, dưới một số điều kiện rất cụ thể - dành riêng CPU, quá trình gắn liền với CPU, ưu hóa tất cả các con đường lên, không có công việc khác được thực hiện trong vòng lặp - vì vậy các mũi tên làm điểm theo hướng đó, nhưng tôi không hoàn toàn chắc chắn về chi phí quay thông qua một bộ nhớ rào)

là gì. chi phí quay vòng qua một rào cản bộ nhớ nếu không có gì bị xóa trong bộ nhớ cache của bộ nhớ cache e đệm? ví dụ, tất cả các quá trình này được thực hiện (trong C) là

while (1) { 
    __sync_synchronize(); 
    v = value; 
    if (v != 0) { 
     ... something ... 
    } 
} 

Tôi thích hợp để giả định rằng nó hoàn toàn miễn phí và nó sẽ không gây trở ngại cho bus bộ nhớ với bất kỳ giao thông?

Một cách khác để đặt này là yêu cầu: không một rào cản bộ nhớ làm bất cứ điều gì hơn: tuôn bộ đệm lưu trữ, áp dụng các invalidations với nó, và ngăn chặn các trình biên dịch từ sắp xếp lại đọc/ghi trên vị trí của nó?


tháo, __sync_synchronize() xuất hiện để dịch sang:

lock orl 

Từ hướng dẫn Intel (tương tự như mơ hồ cho người mới vào nghề):

Volume 3A: System Programming Guide, Part 1 -- 8.1.2 

Bus Locking 

Intel 64 and IA-32 processors provide a LOCK# signal that 
is asserted automatically during certain critical memory 
operations to lock the system bus or equivalent link. 
While this output signal is asserted, requests from other 
processors or bus agents for control of the bus are 
blocked. 

[...] 

For the P6 and more recent processor families, if the 
memory area being accessed is cached internally in the 
processor, the LOCK# signal is generally not asserted; 
instead, locking is only applied to the processor’s caches 
(see Section 8.1.4, “Effects of a LOCK Operation on 
Internal Processor Caches”). 

dịch của tôi: "khi bạn nói KHÓA, điều này sẽ rất tốn kém, nhưng chúng tôi đang chỉ làm việc đó khi cần thiết. "


@BlankXavier:

tôi đã làm bài kiểm tra đó nếu người viết không rõ ràng đẩy ra ghi từ bộ đệm cửa hàng và nó là quá trình chỉ chạy trên CPU đó, người đọc có thể không bao giờ thấy Tác dụng của nhà văn (tôi có thể tái tạo nó với một chương trình thử nghiệm, nhưng như tôi đã đề cập ở trên, nó chỉ xảy ra với một bài kiểm tra cụ thể, với các tùy chọn biên dịch cụ thể và nhiệm vụ cốt lõi chuyên dụng - thuật toán của tôi hoạt động tốt về cách thức hoạt động của nó và viết bài kiểm tra rõ ràng rằng tôi nhận ra rằng nó có khả năng có thể có một vấn đề xuống đường). Tôi nghĩ theo mặc định, viết đơn giản là viết WB (Viết lại), có nghĩa là chúng không bị xóa ngay lập tức, nhưng lần đọc sẽ lấy giá trị gần đây nhất của chúng (tôi nghĩ chúng gọi là "chuyển tiếp lưu trữ"). Vì vậy, tôi sử dụng lệnh CAS cho người viết. Tôi phát hiện ra trong hướng dẫn sử dụng Intel tất cả các kiểu triển khai ghi khác nhau (UC, WC, WT, WB, WP), Intel vol 3A chap 11-10, vẫn học về chúng.

Sự không chắc chắn của tôi ở bên người đọc: Tôi hiểu từ giấy của McKenney rằng cũng có hàng đợi không hợp lệ, hàng đợi các lần vô hiệu hóa đến từ xe buýt vào bộ nhớ cache. Tôi không chắc làm thế nào phần này hoạt động. Đặc biệt, bạn có vẻ ngụ ý rằng lặp qua một lần đọc bình thường (ví dụ, không LOCK'ed, không có rào cản, và chỉ sử dụng biến động để đảm bảo trình tối ưu hóa để đọc đọc một lần biên dịch) sẽ kiểm tra vào "hàng đợi vô hiệu" mỗi lần (nếu có một thứ như vậy). Nếu đọc đơn giản là không đủ tốt (tức là có thể đọc một dòng cache cũ mà vẫn xuất hiện hợp lệ đang chờ xử lý không hợp lệ (có vẻ hơi không đồng ý với tôi nữa, nhưng hàng đợi vô hiệu hoạt động như thế nào?)), Sau đó đọc nguyên tử sẽ là cần thiết và câu hỏi của tôi là: trong trường hợp này, điều này có ảnh hưởng gì đến xe buýt không? (Tôi nghĩ có thể không.)

Tôi vẫn đang đọc theo hướng dẫn của Intel và trong khi tôi thấy một cuộc thảo luận tuyệt vời về chuyển tiếp cửa hàng, tôi không tìm thấy một cuộc thảo luận tốt về hàng đợi không hợp lệ. Tôi đã quyết định chuyển đổi mã C của mình thành ASM và thử nghiệm, tôi nghĩ đây là cách tốt nhất để thực sự cảm nhận được cách thức hoạt động của nó.

+3

"hoạt động tốt với lần đọc cục bộ, trong hầu hết các điều kiện". - nếu nó không hoạt động 'tốt' luôn, thì không sao đâu ..... –

+0

Về thử nghiệm vòng lặp nhỏ của bạn với tối ưu hóa đầy đủ, có những vấn đề khác, ví dụ: [lỗi Comrix Cyrix] (http://en.wikipedia.org/wiki/Cyrix_coma_bug#Analysis) (mặc dù nó không áp dụng trong trường hợp này), điều đó có thể ảnh hưởng đến các thử nghiệm "giả". –

+0

@Mitch: my, tất nhiên, đây là lý do tại sao tôi hỏi :-) – blais

Trả lời

2

Tôi cũng có thể không hiểu đúng câu hỏi, nhưng ...

Nếu bạn đang quay, một vấn đề là trình biên dịch tối ưu hóa spin của bạn. Dễ bay hơi giải quyết điều này.

Rào cản bộ nhớ, nếu có, sẽ được cấp bởi writer vào khóa quay, chứ không phải trình đọc. Nhà văn không thực sự là để sử dụng một - làm như vậy đảm bảo viết được đẩy ra ngay lập tức, nhưng nó sẽ đi ra khá sớm anyway.

Hàng rào ngăn cản cho chuỗi thực thi mã đặt lại trên vị trí của nó, là chi phí khác của nó.

+0

được trả lời trong bản chỉnh sửa ở trên, SO sẽ không cho phép tôi thêm nhận xét dài. – blais

4

Lệnh "xchg reg, [mem]" sẽ báo hiệu ý định khóa của nó trên chốt LOCK của lõi. Tín hiệu này đi qua các lõi khác và lưu trữ xuống các bus bus (bus, vv), nó sẽ hoàn thành những gì chúng đang làm và cuối cùng chốt LOCKA (thừa nhận) sẽ báo hiệu CPU mà xchg có thể hoàn thành. Sau đó, tín hiệu LOCK bị tắt. Trình tự này có thể mất một thời gian dài (hàng trăm chu kỳ CPU hoặc hơn) để hoàn thành. Sau đó các dòng bộ nhớ cache thích hợp của các lõi khác sẽ bị vô hiệu hóa và bạn sẽ có một trạng thái đã biết, i e có lõi được đồng bộ hóa giữa các lõi.

Lệnh xchg là tất cả những gì cần thiết để thực hiện khóa nguyên tử. Nếu bản thân khóa thành công, bạn có quyền truy cập vào tài nguyên mà bạn đã xác định khóa để kiểm soát quyền truy cập. Một tài nguyên như vậy có thể là một vùng bộ nhớ, một tập tin, một thiết bị, một chức năng hoặc những gì có bạn. Tuy nhiên, nó luôn luôn là lập trình viên để viết mã có sử dụng tài nguyên này khi nó đã bị khóa và không khi nó đã không. Thông thường, trình tự mã sau một khóa thành công nên được thực hiện càng ngắn càng tốt sao cho mã khác sẽ bị cản trở càng ít càng tốt khi có được quyền truy cập vào tài nguyên.

Hãy nhớ rằng nếu khóa không thành công, bạn cần thử lại bằng cách phát hành một xchg mới.

"Khóa tự do" là một khái niệm hấp dẫn nhưng nó yêu cầu loại bỏ tài nguyên được chia sẻ. Nếu ứng dụng của bạn có hai hoặc nhiều lõi đồng thời đọc và ghi vào một địa chỉ bộ nhớ chung "khóa tự do" không phải là một tùy chọn.

0

Hãy nhớ rằng các rào cản thường được sử dụng để đặt hàng các bộ truy cập bộ nhớ, vì vậy mã của bạn rất có thể cũng cần các rào cản ở những nơi khác.Ví dụ, nó sẽ không được phổ biến cho các yêu cầu rào cản để trông giống như thay vì điều này:

while (1) { 

    v = pShared->value; 
    __acquire_barrier() ; 

    if (v != 0) { 
     foo(pShared->something) ; 
    } 
} 

rào cản này sẽ ngăn chặn tải và lưu trữ trong nếu khối (ví dụ: pShared->something) từ thực hiện trước khi tải value hoàn tất . Một ví dụ điển hình là bạn có một số "nhà sản xuất" mà sử dụng một cửa hàng của v != 0 để cờ rằng một số bộ nhớ khác (pShared->something) là trong một số trạng thái dự kiến ​​khác, như trong:

pShared->something = 1 ; // was 0 
__release_barrier() ; 
pShared->value = 1 ; // was 0 

Trong kịch bản của người tiêu dùng sản xuất điển hình này, bạn hầu như luôn cần các rào cản ghép nối, một cho cửa hàng gắn cờ bộ nhớ phụ có thể nhìn thấy được (để các hiệu ứng của kho lưu trữ giá trị không nhìn thấy trước cửa hàng) và một rào cản cho người tiêu dùng (để tải một cái gì đó không được bắt đầu trước khi tải giá trị hoàn tất).

Những rào cản đó cũng là nền tảng cụ thể. Ví dụ: trên powerpc (sử dụng trình biên dịch xlC), bạn sẽ sử dụng tương ứng __isync()__lwsync() cho người tiêu dùng và nhà sản xuất. Những rào cản nào được yêu cầu cũng có thể phụ thuộc vào cơ chế mà bạn sử dụng cho cửa hàng và tải của value. Nếu bạn đã sử dụng một nguyên tử nguyên tử dẫn đến một intel LOCK (có lẽ tiềm ẩn), thì điều này sẽ giới thiệu một rào cản ngầm, vì vậy bạn có thể không cần bất cứ điều gì. Ngoài ra, bạn có thể cũng cần phải sử dụng một cách khôn ngoan dễ bay hơi (hoặc tốt hơn là sử dụng một bản thực thi nguyên tử để làm như vậy dưới các bìa) để trình biên dịch thực hiện những gì bạn muốn.

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