Hiệu suất của mã định hướng ADT gán đơn trên CPU hiện đại


32

Làm việc trong dữ liệu không thay đổi với các bài tập đơn lẻ có tác dụng rõ ràng là cần nhiều bộ nhớ hơn, người ta sẽ cho rằng, vì bạn liên tục tạo ra các giá trị mới (mặc dù các trình biên dịch dưới vỏ bọc thực hiện các thủ thuật con trỏ để làm giảm vấn đề này).

Nhưng tôi đã nghe một vài lần rằng các tổn thất trong hiệu năng vượt trội hơn nhiều so với mức tăng theo cách mà CPU (bộ điều khiển bộ nhớ của nó) có thể tận dụng thực tế là bộ nhớ không bị biến đổi (nhiều như vậy).

Tôi đã hy vọng ai đó có thể làm sáng tỏ về việc điều này là đúng (hoặc nếu không?).

Trong một bình luận trên một bài đăng khác, người ta đã đề cập rằng các loại dữ liệu trừu tượng (ADT) phải làm điều này khiến tôi tò mò hơn nữa, làm thế nào các ADT đặc biệt ảnh hưởng đến cách CPU xử lý bộ nhớ? Tuy nhiên, điều này là một bên, chủ yếu tôi chỉ quan tâm đến độ tinh khiết của ngôn ngữ nhất thiết ảnh hưởng đến hiệu suất của CPU và bộ nhớ cache của nó, v.v.


2
điều này chủ yếu hữu ích trong đa luồng, trong đó người đọc có thể chụp ảnh chụp nhanh và an toàn với kiến ​​thức rằng nó sẽ không biến đổi trong khi anh ta đọc nó
ratchet freak

@ratchetfreak Tôi hiểu rằng từ quan điểm lập trình rằng mã của bạn được đảm bảo an toàn hơn, nhưng sự tò mò của tôi là về bộ điều khiển bộ nhớ trên CPU và cách thức hoạt động của nó đối với nó (hoặc nếu không) về một bàn tay đầy thời gian nói rằng nó hiệu quả hơn cho bộ điều khiển bộ nhớ và tôi không biết rõ các chi tiết cấp thấp đủ để nói liệu điều này có đúng hay không.
Jimmy Hoffa

Ngay cả khi đó là sự thật, tôi sẽ không nghĩ rằng việc sửa đổi bộ nhớ ít hơn là điểm bán hàng tốt nhất cho tính bất biến. Rốt cuộc, bộ nhớ đã được sửa đổi, và các trình quản lý CPU và bộ nhớ đã trở nên khá tốt trong những năm qua.
Rein Henrichs

1
Tôi cũng muốn chỉ ra rằng hiệu quả bộ nhớ không nhất thiết phải phụ thuộc vào tối ưu hóa trình biên dịch khi sử dụng các cấu trúc bất biến. Trong ví dụ này let a = [1,2,3] in let b = 0:a in (a, b, (-1):c)chia sẻ làm giảm yêu cầu bộ nhớ, nhưng phụ thuộc vào định nghĩa của (:)[]và không phải là trình biên dịch. Tôi nghĩ? Không chắc chắn về điều này.

Câu trả lời:


28

CPU (bộ điều khiển bộ nhớ cụ thể) có thể tận dụng thực tế là bộ nhớ không bị đột biến

Ưu điểm là, thực tế này tiết kiệm trình biên dịch từ việc sử dụng các hướng dẫn membar khi dữ liệu được truy cập.

Rào chắn bộ nhớ, còn được gọi là thanh ghi nhớ, hàng rào bộ nhớ hoặc lệnh hàng rào, là một loại lệnh rào cản khiến bộ xử lý trung tâm (CPU) hoặc trình biên dịch thực thi một ràng buộc đặt hàng đối với các hoạt động bộ nhớ được ban hành trước và sau lệnh rào cản. Điều này thường có nghĩa là các hoạt động nhất định được đảm bảo được thực hiện trước hàng rào và các hoạt động khác sau.

Rào cản bộ nhớ là cần thiết bởi vì hầu hết các CPU hiện đại sử dụng tối ưu hóa hiệu suất có thể dẫn đến thực hiện không theo thứ tự. Việc sắp xếp lại các hoạt động bộ nhớ (tải và lưu trữ) thường không được chú ý trong một luồng thực thi, nhưng có thể gây ra hành vi không thể đoán trước trong các chương trình và trình điều khiển thiết bị đồng thời trừ khi được kiểm soát cẩn thận ...


Bạn thấy, khi dữ liệu được truy cập từ các luồng khác nhau, tại CPU đa lõi, nó sẽ diễn ra như sau: các luồng khác nhau chạy ở các lõi khác nhau, mỗi luồng sử dụng bộ đệm riêng (cục bộ đến lõi của chúng) - một bản sao của một số bộ đệm chung.

Nếu dữ liệu có thể thay đổi và lập trình viên cần dữ liệu thống nhất giữa các luồng khác nhau, các biện pháp cần được thực hiện để đảm bảo tính nhất quán. Đối với lập trình viên, điều này có nghĩa là sử dụng các cấu trúc đồng bộ hóa khi họ truy cập (ví dụ đọc) dữ liệu trong luồng cụ thể.

Đối với trình biên dịch, đồng bộ hóa cấu trúc trong các phương tiện mã nó cần để chèn một hướng dẫn membar để đảm bảo rằng những thay đổi thực hiện cho các bản sao dữ liệu tại một trong các lõi được truyền đúng cách ( "xuất bản"), để đảm bảo rằng cache tại lõi khác có cùng bản sao (cập nhật).

Phần nào đơn giản hóa xem ghi chú bên dưới , đây là những gì xảy ra ở bộ xử lý đa lõi cho membar:

  1. Tất cả các lõi dừng xử lý - để tránh việc vô tình ghi vào bộ đệm.
  2. Tất cả các bản cập nhật được thực hiện cho bộ nhớ cache cục bộ được ghi lại thành toàn cục - để đảm bảo rằng bộ đệm chung chứa dữ liệu gần đây nhất. Điều này cần một chút thời gian.
  3. Dữ liệu cập nhật được ghi lại từ bộ đệm chung cho bộ nhớ cache cục bộ - để đảm bảo rằng bộ nhớ cache cục bộ chứa dữ liệu gần đây nhất. Điều này cần một chút thời gian.
  4. Tất cả các lõi tiếp tục thực hiện.

Bạn thấy đấy, tất cả các lõi đều không làm gì trong khi dữ liệu được sao chép qua lại giữa bộ nhớ cache toàn cục và cục bộ . Điều này là cần thiết để đảm bảo rằng dữ liệu có thể thay đổi được đồng bộ hóa đúng cách (luồng an toàn). Nếu có 4 lõi, cả 4 dừng lại và chờ trong khi bộ nhớ cache đang được đồng bộ hóa. Nếu có 8, tất cả 8 dừng lại. Nếu có 16 ... thì bạn đã có 15 lõi không làm gì cả trong khi chờ đợi những thứ cần thiết để làm một trong những điều này.

Bây giờ, hãy xem điều gì xảy ra khi dữ liệu là bất biến? Bất kể chủ đề nào truy cập nó, nó được đảm bảo là như nhau. Đối với lập trình viên, điều này có nghĩa là không cần chèn các cấu trúc đồng bộ hóa khi họ truy cập (đọc) dữ liệu trong luồng cụ thể.

Đối với trình biên dịch, điều này có nghĩa là không cần phải chèn một lệnh ghi nhớ .

Do đó, việc truy cập dữ liệu không cần phải dừng lõi và chờ trong khi dữ liệu được ghi lại giữa các bộ đệm toàn cục và cục bộ. Đó là một lợi thế của thực tế là bộ nhớ không bị đột biến .


Lưu ý phần nào giải thích đơn giản hóa ở trên làm giảm một số tác động tiêu cực phức tạp hơn của dữ liệu có thể thay đổi, ví dụ như trên đường ống . Để đảm bảo yêu cầu đặt hàng, CPU phải vô hiệu hóa các phi công bị ảnh hưởng bởi thay đổi dữ liệu - đó là một hình phạt hiệu suất khác. Nếu điều này được thực hiện bằng cách đơn giản (và do đó đáng tin cậy :) vô hiệu hóa tất cả các đường ống, thì hiệu ứng tiêu cực được khuếch đại hơn nữa.



Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.