Tôi thấy câu hỏi đã được kích hoạt lại với một khoản tiền thưởng, bây giờ hỏi mục đích thực tế yield
là gì. Tôi sẽ đưa ra một ví dụ từ kinh nghiệm của tôi.
Như chúng ta đã biết, yield
buộc luồng gọi từ bỏ bộ xử lý mà nó đang chạy để luồng khác có thể được lên lịch chạy. Điều này rất hữu ích khi luồng hiện tại đã hoàn thành công việc nhưng muốn nhanh chóng quay trở lại phía trước hàng đợi và kiểm tra xem một số điều kiện đã thay đổi hay chưa. Điều này khác với một biến điều kiện như thế nào? yield
cho phép luồng trở về trạng thái đang chạy nhanh hơn nhiều. Khi chờ một biến điều kiện, luồng bị tạm dừng và cần đợi một luồng khác báo hiệu rằng nó sẽ tiếp tục.yield
về cơ bản nói rằng "cho phép một luồng khác chạy, nhưng hãy cho phép tôi trở lại làm việc rất sớm khi tôi mong đợi điều gì đó sẽ thay đổi trong trạng thái của tôi rất nhanh". Điều này gợi ý về việc quay bận rộn, trong đó một điều kiện có thể thay đổi nhanh chóng nhưng việc tạm dừng chỉ sẽ gây ra một hiệu suất lớn.
Nhưng lảm nhảm đủ rồi, đây là một ví dụ cụ thể: mô hình song song mặt sóng. Một ví dụ cơ bản của vấn đề này là tính toán các "đảo" riêng lẻ của 1s trong một mảng hai chiều chứa đầy 0s và 1s. "Đảo" là một nhóm các ô liền kề với nhau theo chiều dọc hoặc chiều ngang:
1 0 0 0
1 1 0 0
0 0 0 1
0 0 1 1
0 0 1 1
Ở đây chúng ta có hai hòn đảo 1s: trên cùng bên trái và dưới cùng bên phải.
Một giải pháp đơn giản là thực hiện chuyển đầu tiên trên toàn bộ mảng và thay thế các giá trị 1 bằng bộ đếm tăng dần sao cho cuối mỗi giá trị 1 được thay thế bằng số thứ tự của nó theo thứ tự chính của hàng:
1 0 0 0
2 3 0 0
0 0 0 4
0 0 5 6
0 0 7 8
Trong bước tiếp theo, mỗi giá trị được thay thế bằng giá trị nhỏ nhất giữa chính nó và các giá trị lân cận của nó:
1 0 0 0
1 1 0 0
0 0 0 4
0 0 4 4
0 0 4 4
Bây giờ chúng ta có thể dễ dàng xác định rằng chúng ta có hai hòn đảo.
Phần chúng tôi muốn chạy song song là bước chúng tôi tính toán các giá trị tối thiểu. Không đi vào quá nhiều chi tiết, mỗi luồng nhận được các hàng theo cách xen kẽ và dựa vào các giá trị được tính toán bởi luồng xử lý hàng ở trên. Do đó, mỗi luồng cần hơi trễ so với luồng xử lý của dòng trước đó, nhưng cũng phải theo kịp trong thời gian hợp lý. Chi tiết hơn và cách triển khai được tôi trình bày trong tài liệu này . Lưu ý cách sử dụng của sleep(0)
nó nhiều hơn hoặc ít hơn C tương đương với yield
.
Trong trường hợp này yield
được sử dụng để buộc mỗi luồng lần lượt tạm dừng, nhưng vì luồng xử lý hàng liền kề sẽ tiến rất nhanh trong thời gian chờ đợi, một biến điều kiện sẽ chứng minh một lựa chọn tai hại.
Như bạn có thể thấy, yield
là một tối ưu hóa khá nhỏ. Sử dụng nó không đúng chỗ, ví dụ như chờ đợi một điều kiện ít khi thay đổi, sẽ gây ra việc sử dụng CPU quá mức.
Xin lỗi vì những lời nói lảm nhảm dài dòng, hy vọng tôi đã nói rõ.