11

Làm cách nào để đảm bảo rằng các phép tính dấu chấm động trong một ứng dụng .NET (nói trong C#) luôn tạo ra cùng một kết quả chính xác bit? Đặc biệt khi sử dụng các phiên bản .NET khác nhau và chạy trên các nền tảng khác nhau (x86 vs x86_64). Không chính xác của các hoạt động điểm nổi không quan trọng.Điểm nổi bật xác định và .NET

Trong Java, tôi sẽ sử dụng strictfp. Trong C/C++ và các ngôn ngữ cấp thấp khác, vấn đề này về cơ bản được giải quyết bằng cách truy cập vào thanh ghi điều khiển FPU/SSE nhưng điều đó có lẽ không khả thi trong .NET.

Ngay cả khi kiểm soát đăng ký kiểm soát FPU, JIT của .NET sẽ tạo mã khác trên các nền tảng khác nhau. Một cái gì đó như HotSpot thậm chí còn tệ hơn trong trường hợp này ...

Tại sao tôi cần nó? Tôi đang nghĩ về việc viết một trò chơi chiến lược thời gian thực (RTS) mà phụ thuộc rất nhiều vào phép toán điểm nổi nhanh cùng với một mô phỏng bước khóa. Về cơ bản tôi sẽ chỉ truyền đầu vào của người dùng trên mạng. Điều này cũng áp dụng cho các trò chơi khác thực hiện replay bằng cách lưu trữ đầu vào của người dùng.

Không một tùy chọn là:

  • thập phân (quá chậm)
  • giá trị điểm cố định (quá chậm và cồng kềnh khi sử dụng sqrt, sin, cos, tan, atan ...)
  • cập nhật trạng thái trên mạng như FPS: Gửi thông tin vị trí cho hàng trăm hoặc vài nghìn đơn vị không phải là một tùy chọn

Bất kỳ ý tưởng nào?

Trả lời

2

Tôi không chắc chắn câu trả lời chính xác cho câu hỏi của bạn nhưng bạn có thể sử dụng C++ và làm tất cả công việc nổi của bạn trong một dll C++ và sau đó trả về kết quả đến .Net thông qua một interopt.

+0

Nếu tôi viết phần quan trọng (mô phỏng) của trò chơi trong C/C++ thì tôi có thể viết toàn bộ trò chơi mà không cần .Net. Có lẽ đó là cách "đúng" ở đây. – user285934

+0

Xem xét chức năng C/C++ IJW (Chỉ hoạt động) của trình biên dịch MSVC. Nó sẽ cho phép bạn viết những gì bạn cần để viết dưới dạng mã không được quản lý và thực hiện phần còn lại dưới dạng mã được quản lý để giao diện thuận lợi với phần còn lại của các phần được quản lý trong trò chơi của bạn. – Ants

1

Kết quả Bitexact cho các nền tảng khác nhau là nỗi đau trong **. Nếu bạn chỉ sử dụng x86, nó không quan trọng vì FPU không thay đổi từ 32 đến 64bit. Nhưng vấn đề là các chức năng siêu việt có thể có nhiều hơn chính xác trên các bộ vi xử lý mới.

Bốn hoạt động cơ sở không được đưa ra kết quả khác nhau, nhưng VM của bạn có thể tối ưu hóa các biểu thức và có thể cho kết quả khác nhau. Như Ants đã đề xuất, viết thói quen thêm/mul/div/sub của bạn dưới dạng mã không được quản lý để ở bên an toàn.

Đối với các chức năng siêu việt, tôi sợ bạn phải sử dụng bảng tra cứu để đảm bảo độ chính xác bit. Tính toán kết quả của ví dụ: 4096 giá trị, lưu trữ chúng như hằng số và nếu bạn cần một giá trị giữa chúng, nội suy. Điều này không cung cấp cho bạn độ chính xác tuyệt vời, nhưng nó sẽ bị cắn.

+0

Bốn hoạt động cơ sở tạo ra các kết quả khác nhau ngay cả trên một bộ xử lý đơn khi bộ SSE và FPU không được cấu hình đúng (vô hiệu hóa các số phụ cho cả hai, sử dụng giá trị 32 bit hoặc 64 bit trên fpu thay vì độ chính xác tối đa). Các chức năng siêu việt có thể được thực hiện trong phần mềm sử dụng môi trường được kiểm soát này trong C/C++. – user285934

0

Nếu bạn muốn xác định điểm động, bạn cần loại bỏ tất cả các biến. Điều này là có thể nếu bạn hạn chế phạm vi của bạn một chút.

  1. Làm cho ứng dụng của bạn chỉ 64 bit. Bằng cách này bạn không phải đối phó với x87 vs SSE (x86 JIT vẫn phát ra mã x87 fp, các JIT khác phát ra SSE).
  2. Sử dụng .NET Core và bundle the runtime with your application. Bằng cách này, bạn đảm bảo cùng một codegen cho bất kỳ phiên bản nào của ứng dụng của bạn. Điều này là rất quan trọng, sự khác biệt nhỏ nhất của codegen có thể gây ra các tính toán fp để đưa ra các kết quả khác nhau.
  3. Gắn bó với một hệ điều hành. Nghiêm túc, có bao nhiêu nền tảng RTS có ở ngoài đó? Vâng, có Starcraft 2; đó là AFAIK. Blizzard đã làm chủ được nghệ thuật này trong một thời gian dài và rất ít người có thể tái tạo thành công này. Nếu bạn thực sự muốn hỗ trợ nhiều người dùng Mac-PC, bạn sẽ phải cẩn thận xác minh rằng thời gian chạy .NET của bạn tạo ra cùng một mã fp trên cả hai nền tảng. Và nếu bạn không may mắn.

Một điểm tôi vẫn không chắc liệu bạn có thể tin tưởng vào lớp Toán để đưa ra kết quả nhất quán hay không, với các hạn chế trên; nhưng tôi cho là vậy.

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