2017-12-24 108 views
10

Tôi đã tự hỏi nên hỏi điều gì ở đây, vì vậy tôi hỏi câu hỏi này trên Meta (https://meta.stackexchange.com/questions/304981) và được hướng dẫn ở đây.Làm thế nào absl :: Các phần quan trọng có điều kiện của Mutex xử lý các lần đánh thức người đọc

Tôi thực sự tò mò về loại tối ưu hóa nào được xây dựng trong việc triển khai các phần quan trọng có điều kiện của Google với absl::Mutex (https://github.com/abseil/abseil-cpp/blob/master/absl/synchronization/mutex.h). Đặc biệt tôi đã tự hỏi làm thế nào họ xử lý các lần đánh thức người đọc khi điều kiện của người đọc trở thành sự thật. Họ có đánh thức tất cả các độc giả khác trong danh sách chờ không? This line dường như báo hiệu rằng họ làm .. Không phải là nguy cơ một O (n) traversal mỗi lần và cũng có nguy cơ sấm bầy đàn trong một mutex ưu tiên viết?

+0

Chỉ cần đọc tại các tệp bao gồm trong mutex.cc, người ta có thể thấy chúng sử dụng pthread hoặc window.h. Với thư viện luồng cao cấp đó, bạn có thể không thể làm bất cứ điều gì kỳ diệu. Cho dù đây là hệ thống đánh thức chủ đề. Với mã mức thấp hơn, bạn có thể kiểm soát trình đọc để tỉnh táo (hoặc ít nhất là chọn một vài trong số chúng thấy 'man 2 futex'). Đừng lãng phí thời gian của bạn đọc wrapper này xung quanh wrapper với các lớp siêu tồn tại để giải quyết vấn đề mà sẽ không có nếu không có sublayer! – Oliv

+0

'futex' (trên Linux) là những gì sẽ hạn chế vũ trụ của khả năng. Sau đó, bất cứ thứ gì được xây dựng xung quanh nó (mutex, semaphore, vv ...) sẽ càng hạn chế. – Oliv

Trả lời

4

Tôi nghĩ điều quan trọng là phải đặt ra sự khác biệt giữa tối ưu hóa thiết kế và triển khai. Dường như absl :: ưu tiên thiết kế tốt hơn bằng cách cung cấp một triển khai hỗ trợ các thiết kế đó, trái với việc cung cấp các thành phần được tối ưu hóa tốt hơn. Đôi khi, thiết kế tốt hơn vốn đã hoạt động tốt hơn so với thiết kế gọn gàng hơn, do đó kết quả được tối ưu hóa trên cả hai yếu tố (sức mạnh tổng hợp). Absiel.io thảo luận chi tiết hơn về điều này.

Từ khi nhìn vào nguồn của chúng, không có vẻ như cố gắng ma thuật để tránh phát sóng tới người đọc đang chờ xử lý, do đó có, đàn sấm vẫn là vấn đề. Nói chung, không thực hiện có thể giải quyết vấn đề đó một cách có ý nghĩa; nó là một vấn đề thiết kế.

Bằng cách nhúng điều kiện như là một phần của khóa, absl: không cho phép lập trình viên tránh hoặc thiết kế xung quanh, vấn đề đó. Vẫn còn một đàn, nhưng việc thực hiện khóa có thể làm mỏng nó plan 9 nod here. Nếu bạn thiết kế lý do của mình để đánh thức tốt, ví dụ bit trong mặt nạ, bạn có thể sử dụng khóa chia sẻ/độc quyền một cách an toàn mà không phải lo lắng về việc đánh thức giả mạo ảnh hưởng đến hiệu suất của bạn.

Đây là bản chất của 'tối ưu hóa thiết kế': vấn đề được mô tả rõ ràng hơn trong nguồn và kết quả thực hiện có chất lượng cao hơn (hiệu suất, tỷ lệ, ...).

Plan9. Biến điều kiện tương đương với khái niệm hạt nhân unix của giấc ngủ (không phải là thời gian một) và thức dậy. Khi bạn phát hiện rằng một đối tượng không ở trạng thái bạn cần, bạn thực hiện một số hành động để bắt đầu đưa nó đến trạng thái đó, sau đó đợi cho đến khi trạng thái đó đạt được. Ví dụ: bạn có thể tra cứu một đối tượng trong bộ nhớ cache và khi khám phá ra nó không có ở đó, hãy tạo một đối tượng không hợp lệ và yêu cầu nó được làm hợp lệ. Điều này cho phép một loại đối xứng giữa tất cả những người tham gia bộ nhớ cache: họ khóa đối tượng, đánh giá hoặc cập nhật trạng thái của nó, sau đó đồng thời mở khóa đối tượng và đợi những thay đổi tiếp theo.

Vấn đề xấu là có: không có điều như đồng thời, và b: việc xử lý khóa dễ bị lỗi (tôi có giữ bất kỳ khóa nào khác không? Điều này có thể dẫn đến bế tắc không?) Và không được thể hiện rõ trong chương trình . Giấc ngủ và thức tỉnh của Plan9 được sát nhập một cách trang nhã, vì vậy tại thời điểm mà điều kiện được kiểm tra thì không ai có thể ảnh hưởng đến đối tượng. Trong thực tế, điểm của giấy tham chiếu là khó khăn như thế nào để thực thi hợp đồng đơn giản đó. Các hợp đồng phức tạp trong một môi trường đa xử lý tốt nhất nên tránh for example.

Tối ưu hóa quan trọng (trong absl :) là không cần phải thực hiện thao tác chuyển ngữ cảnh đắt tiền để xác định rằng đối tượng ở trạng thái sai, sau đó quay lại chế độ ngủ. Nếu mã được chọn để đánh thức bạn dậy có thể xác minh rằng trạng thái đối tượng là trạng thái bạn có khả năng quan tâm, thì càng nhiều càng tốt. Một lời gọi hàm/phương thức gọi hàm là nhanh hơn 100 lần so với chuyển đổi ngữ cảnh.

AbslThis section giải quyết cả cách ứng cử viên để đánh thức được chọn và cách đàn bị tiêu hủy. This section tạo chương trình phát sóng.

Vì vậy, phần trước chọn các phần tử từ danh sách người phục vụ và phần sau sẽ đánh thức chúng. Nếu bạn nhìn vào điều kiện khác của dòng 2203, nó cho thấy cách một người viết sẽ chấm dứt danh sách - w_walk-> wake là không đúng, và wr_wait đã được thiết lập. Ngoài ra, các thử nghiệm trước đó vào năm 2015 và năm 2023 ngăn chặn việc xây dựng danh sách này nếu nó là bản ghi.

màn

obj.enter(); 
while (obj.state != StateIWant) { 
    obj.wait(); 
} 
... 
obj.exit(); 

Đòi hỏi chủ đề này để thực hiện các điều kiện bảo vệ. Hành động di chuyển luồng bị chặn này có thể gấp 1000 lần chi phí thực hiện điều kiện. Ngược lại:

obj.wait(^{return obj.state == StateIWant;}); 
... 
obj.exit(); 

sẽ cho phép cuộc gọi chờ đánh giá điều kiện trong trường hợp bất kỳ chủ đề nào cho phép chuyển đổi trong trường hợp vô dụng.

+0

Bất kỳ ý tưởng nào về chức năng "thợ làm bánh được chỉ định" dành cho mã của họ? https://github.com/abseil/abseil-cpp/blob/be40fdf1a86f4956d2f8125a7b6bd6d34e133c2d/absl/synchronization/mutex.cc#L593 Tôi nghĩ rằng nó có liên quan đến cách các chủ đề được đánh thức – Curious

+0

Bạn đã bao giờ giữ cửa cho ai đó chưa và thấy mình đang giữ cửa cho một dòng người? Nếu tôi đọc nó một cách chính xác, nó là một chút như thế. Cánh cửa, trong trường hợp này, là dịch vụ đồng bộ hóa cơ bản (ví dụ: Futex, Win32, SEM, ...) và mã đang cố gắng tránh nó để có hiệu suất tốt hơn. Điều đó nói rằng, tôi dường như không thể tưởng tượng được trường hợp xảy ra điều này, nhưng đôi khi tôi cũng đang giữ cửa cho một dòng người .. – mevets

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