2009-07-07 31 views
35

Tôi biết rằng ghi vào một biến volatile tuôn ra nó từ bộ nhớ của tất cả các cpus, tuy nhiên tôi muốn biết nếu đọc cho một biến dễ bay hơi là nhanh như bình thường đọc?Biến biến động 'đọc' nhanh như bình thường đọc?

Các biến số volatile có thể được đặt trong bộ nhớ cache cpu hay không luôn luôn được lấy từ bộ nhớ chính?

+1

Bạn có thể thêm "java" vào một nơi nào đó trong câu hỏi không? Đã có sự nhầm lẫn với C - chỉ cần thiết lập các từ khóa dường như không đủ. –

+0

có vẻ như bây giờ là – pdeva

Trả lời

-3

dễ bay hơi ngụ ý rằng trình biên dịch không thể tối ưu hóa biến bằng cách đặt giá trị của nó trong thanh ghi CPU. Nó phải được truy cập từ bộ nhớ chính. Nó có thể, tuy nhiên, được đặt trong một bộ nhớ cache CPU. Cache sẽ bảo đảm sự nhất quán giữa các CPU/lõi khác trong hệ thống. Nếu bộ nhớ được ánh xạ tới IO, thì mọi thứ phức tạp hơn một chút. Nếu nó được thiết kế như vậy, phần cứng sẽ ngăn không gian địa chỉ đó được lưu trữ và tất cả các truy cập vào bộ nhớ đó sẽ đi tới phần cứng. Nếu không có thiết kế như vậy, nhà thiết kế phần cứng có thể yêu cầu thêm hướng dẫn CPU để đảm bảo rằng đọc/ghi đi qua bộ đệm, v.v.

Thông thường, từ khóa 'dễ bay hơi' chỉ được sử dụng cho trình điều khiển thiết bị đang hoạt động hệ thống.

+6

Đó có thể là những gì có nghĩa là dễ bay hơi trong C, nhưng nó không phải là ý nghĩa của nó trong Java. Trong Java, sự biến động là về việc liệu một luồng thực hiện một lần đọc sẽ "thấy" các thay đổi được thực hiện bởi một luồng khác hay không. Nó đơn giản hơn là giá trị có thể nằm trong thanh ghi CPU hay không. Từ khóa dễ bay hơi cũng ngăn chặn những loại sắp xếp lại mà JVM có thể thực hiện trên mã sử dụng biến. – NamshubWriter

+0

Đây là bài viết của Tiến sĩ Dobb, chi tiết hơn một chút giữa các điểm khác nhau: http://www.ddj.com/hpc-high-performance-computing/212701484 –

+0

Người đọc không nói java và được đề cập cụ thể đến cấp 2 cache, vì vậy tôi cho rằng kịch bản phổ biến nhất ... C. – drudru

13

Câu trả lời có phần phụ thuộc vào kiến ​​trúc. Trên x86, không có thêm chi phí nào liên quan đến việc đọc biến động cụ thể, mặc dù có những hàm ý cho các tối ưu hóa khác.

JMM cookbook from Doug Lea, see architecture table near the bottom.

Để làm rõ: Không có bất kỳ chi phí thêm liên quan đến việc đọc chính nó. Các rào cản bộ nhớ được sử dụng để đảm bảo trật tự phù hợp. JSR-133 phân loại bốn rào cản "LoadLoad, LoadStore, StoreLoad và StoreStore". Tùy thuộc vào kiến ​​trúc, một số rào cản này tương ứng với "không có op", nghĩa là không có hành động nào được thực hiện, những người khác yêu cầu một hàng rào. Không có chi phí tiềm ẩn liên quan đến bản thân tải, mặc dù có thể xảy ra nếu hàng rào được đặt đúng vị trí. Trong trường hợp x86, chỉ có một rào cản StoreLoad dẫn đến hàng rào.

Như được chỉ ra trong bài đăng trên blog, thực tế biến là dễ bay hơi có nghĩa là có các giả định về bản chất của biến không thể thực hiện được nữa và tối ưu hóa một số trình biên dịch sẽ không được áp dụng cho biến động.

Dễ bay hơi không phải là thứ nên được sử dụng một cách rõ ràng, nhưng cũng không nên lo sợ. Có rất nhiều trường hợp, nơi dễ bay hơi sẽ đủ chỗ thay cho khóa tay nặng hơn.

+2

Làm thế nào điều này có thể? Điều gì về bộ vi xử lý đa lõi? (Nếu không đọc toàn bộ liên kết bạn đã đăng) – ripper234

+6

Không có gì là "không có", trừ khi nó có thể được loại bỏ hoàn toàn khỏi chương trình của bạn. Đọc linh hoạt là giá rẻ, nhưng không miễn phí và ức chế tối ưu hóa theo cách đọc đồng bằng không (ví dụ: đọc linh hoạt không thể được kéo ra khỏi vòng lặp hoặc đọc từ sổ đăng ký). Chữ "no-op" trong trường hợp này đề cập đến việc thiếu hướng dẫn hàng rào tương ứng, nhưng chính bản thân nó có ngữ nghĩa và những cái có chi phí. –

+2

Chính xác. Tuy nhiên, đó là những ngữ nghĩa tối ưu hóa nằm ngoài những ngữ nghĩa được áp đặt một cách rõ ràng. Câu trả lời chính cho câu hỏi là "Nó phụ thuộc vào kiến ​​trúc". Bây giờ bình luận là sự thật. Rất nhiều người lo sợ dễ bay hơi và điều đó hơi ngớ ngẩn. Mặc dù tôi cũng sẽ không bao giờ khuyên bạn nên sử dụng dễ bay hơi trên mọi thứ. –

0

Đọc linh hoạt không thể nhanh chóng, đặc biệt là trên CPU đa lõi (nhưng cũng chỉ có một lõi). Lõi thực thi phải lấy từ địa chỉ bộ nhớ thực để đảm bảo nó nhận được giá trị hiện tại - biến thực sự không thể được lưu trữ.

Ngược lại với một câu trả lời khác ở đây, biến dễ bay hơi là không được sử dụng chỉ dành cho trình điều khiển thiết bị! Đôi khi chúng cần thiết cho việc viết mã đa luồng hiệu năng cao!

+5

* Đọc linh hoạt không thể nhanh chóng, đặc biệt là trên CPU đa nhân * điều này hoàn toàn không đúng, trên hầu hết các lần đọc phần cứng dễ bay hơi chỉ là tải bình thường. Tải là tốn kém khi thiếu bộ nhớ cache nhưng đọc dễ bay hơi không đi vào bộ nhớ chính, nếu có một giá trị trong bộ nhớ cache và thậm chí dễ bay hơi viết (mà là tốn kém) có thể cập nhật các dòng bộ nhớ cache CPU cục bộ. Multi CPU/Socket phụ thuộc vào giao thức kết hợp bộ nhớ cache để đảm bảo các giá trị hợp lệ nhưng nó không tạo ra các lần đọc dễ bay hơi ở bất kỳ nơi nào đắt hơn. – bestsss

+0

@bestsss - vâng, tôi thừa nhận sự thiếu hiểu biết về chi tiết, nhưng tôi luôn được dạy rằng đọc bình thường "luôn luôn" tốt hơn đọc dễ bay hơi. Tôi sẽ không đặt cược 1 gazillion đô la cho câu trả lời. – ripper234

+0

Không, một số cpus có thể cần một rào cản tải tải, nhưng nó vẫn còn rẻ. Như một quy tắc của ngón tay cái xem xét dễ bay hơi chỉ đọc tải bình thường. Nếu bất kỳ CPU nào cần đến bộ nhớ chính (còn gọi là cache nhớ), thì đó là một lỗ hổng thiết kế đáng sợ. – bestsss

1

Tùy thuộc vào kiến ​​trúc. Điều gì volatile làm là nói với trình biên dịch không để tối ưu hóa biến đó đi. Nó buộc hầu hết các hoạt động để xử lý trạng thái của biến là không xác định. Bởi vì nó dễ bay hơi, nó có thể bị thay đổi bởi một luồng khác hoặc một số hoạt động phần cứng khác. Vì vậy, lần đọc sẽ cần phải đọc lại biến và các hoạt động sẽ thuộc loại đọc-sửa-ghi.

Loại biến này được sử dụng cho trình điều khiển thiết bị và cũng để đồng bộ hóa với mutexes/semaphores trong bộ nhớ.

+3

Không liên quan, câu hỏi là dành cho Java. – ripper234

+2

Nó vẫn có liên quan nếu bạn hiểu những gì có nghĩa là biến động. – sybreon

+0

Nó có nghĩa là một cái gì đó hơi khác nhau trong Java. – ripper234

16

Bạn thực sự nên xem bài viết này: http://brooker.co.za/blog/2012/09/10/volatile.html.Bài viết trên blog cho rằng các lần đọc dễ bay hơi có thể chậm hơn rất nhiều (cũng cho x86) so với các lần đọc không dễ bay hơi trên x86.

  • Kiểm tra 1 là đọc và viết song song với biến không biến đổi. Có không có cơ chế hiển thị và kết quả của lần đọc là có khả năng cũ.
  • Kiểm tra 2 là đọc và viết song song với biến dễ bay hơi. Điều này không đề cập cụ thể đến câu hỏi của OP. Tuy nhiên đáng chú ý là một biến động có khuynh hướng có thể rất chậm.
  • Kiểm tra 3 được đọc thành biến động trong một vòng lặp chặt chẽ. Chứng minh là ngữ nghĩa của những gì nó có nghĩa là dễ bay hơi chỉ ra rằng giá trị có thể thay đổi với mỗi vòng lặp lặp lại. Do đó JVM không thể tối ưu hóa việc đọc và kéo nó ra khỏi vòng lặp. Trong Bài kiểm tra 1, có khả năng giá trị đã được đọc và lưu trữ một lần, do đó không có "đọc" thực sự xảy ra.

Marc Booker's tests

tín dụng để Marc Booker cho chạy các bài kiểm tra.

+1

có vẻ như là trường hợp duy nhất khi dễ bay hơi. – pdeva

+6

@pdeva, không, biểu đồ hiển thị rõ ràng không bị kiểm soát dễ bay hơi đọc chậm hơn không bay hơi. Eye-balling nó, nó trông chậm hơn 2-3 lần. – nilskp

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