Thiết lập
Tôi có một kiến trúc thành phần thực thể trong đó Thực thể có thể có một tập các thuộc tính (là dữ liệu thuần túy không có hành vi) và tồn tại các hệ thống chạy logic thực thể hoạt động trên dữ liệu đó. Về cơ bản, trong mã giả phần nào:
Entity
{
id;
map<id_type, Attribute> attributes;
}
System
{
update();
vector<Entity> entities;
}
Một hệ thống chỉ di chuyển dọc theo tất cả các thực thể với tốc độ không đổi có thể là
MovementSystem extends System
{
update()
{
for each entity in entities
position = entity.attributes["position"];
position += vec3(1,1,1);
}
}
Về cơ bản, tôi đang cố gắng song song cập nhật () hiệu quả nhất có thể. Điều này có thể được thực hiện bằng cách chạy song song toàn bộ hệ thống hoặc bằng cách cung cấp cho mỗi bản cập nhật () của một hệ thống một vài thành phần để các luồng khác nhau có thể thực hiện cập nhật của cùng một hệ thống, nhưng đối với một tập hợp con khác của các thực thể được đăng ký với hệ thống đó.
Vấn đề
Trong trường hợp của MovementSystem được hiển thị, việc song song hóa là không đáng kể. Vì các thực thể không phụ thuộc vào nhau và không sửa đổi dữ liệu được chia sẻ, chúng tôi có thể di chuyển song song tất cả các thực thể.
Tuy nhiên, các hệ thống này đôi khi yêu cầu các thực thể tương tác với (đọc / ghi dữ liệu từ / đến) lẫn nhau, đôi khi trong cùng một hệ thống, nhưng thường là giữa các hệ thống khác nhau phụ thuộc vào nhau.
Ví dụ, trong một hệ thống vật lý đôi khi các thực thể có thể tương tác với nhau. Hai đối tượng va chạm, vị trí, vận tốc của chúng và các thuộc tính khác được đọc từ chúng, được cập nhật và sau đó các thuộc tính được cập nhật được ghi lại cho cả hai thực thể.
Và trước khi hệ thống kết xuất trong công cụ có thể bắt đầu kết xuất các thực thể, nó phải chờ các hệ thống khác hoàn thành thực thi để đảm bảo rằng tất cả các thuộc tính có liên quan là những gì chúng cần phải có.
Nếu chúng ta cố gắng song song một cách mù quáng điều này, nó sẽ dẫn đến các điều kiện chủng tộc cổ điển nơi các hệ thống khác nhau có thể đọc và sửa đổi dữ liệu cùng một lúc.
Lý tưởng nhất là tồn tại một giải pháp trong đó tất cả các hệ thống có thể đọc dữ liệu từ bất kỳ thực thể nào mà nó muốn, mà không phải lo lắng về các hệ thống khác sửa đổi cùng một dữ liệu đó và không cần lập trình viên quan tâm đến việc sắp xếp đúng cách thực hiện và song song hóa các hệ thống này bằng tay (đôi khi có thể thậm chí không thể).
Trong một triển khai cơ bản, điều này có thể đạt được bằng cách chỉ cần đặt tất cả các dữ liệu đọc và ghi vào các phần quan trọng (bảo vệ chúng bằng các mutexes). Nhưng điều này gây ra một lượng lớn chi phí thời gian chạy và có lẽ không phù hợp với các ứng dụng nhạy cảm hiệu năng.
Giải pháp?
Theo tôi, một giải pháp khả thi sẽ là một hệ thống phân tách đọc / cập nhật và ghi dữ liệu, do đó, trong một giai đoạn đắt tiền, các hệ thống chỉ đọc dữ liệu và tính toán những gì chúng cần để tính toán, bằng cách nào đó lưu trữ kết quả và sau đó viết tất cả dữ liệu đã thay đổi trở lại các thực thể đích trong một lần viết riêng. Tất cả các hệ thống sẽ hành động trên dữ liệu ở trạng thái ở đầu khung và sau đó trước khi kết thúc khung, khi tất cả các hệ thống đã cập nhật xong, một lần viết nối tiếp xảy ra trong đó các kết quả được lưu trong bộ nhớ cache từ tất cả các kết quả khác nhau các hệ thống được lặp lại thông qua và được viết lại cho các thực thể đích.
Điều này dựa trên ý tưởng (có thể sai?) Rằng chiến thắng song song dễ dàng có thể đủ lớn để vượt chi phí (cả về hiệu năng thời gian chạy cũng như chi phí mã) của bộ đệm kết quả và vượt qua ghi.
Câu hỏi
Làm thế nào một hệ thống như vậy có thể được thực hiện để đạt được hiệu suất tối ưu? Các chi tiết triển khai của một hệ thống như vậy là gì và các điều kiện tiên quyết cho một hệ thống Thực thể-Thành phần muốn sử dụng giải pháp này là gì?