11

¿Cómo puedo garantizar que los cálculos de punto flotante en una aplicación .NET (digamos en C#) siempre produzcan el mismo resultado de bit exacto? Especialmente cuando se usan diferentes versiones de .NET y se ejecutan en diferentes plataformas (x86 vs x86_64). Las imprecisiones de las operaciones de punto flotante no importan.Punto flotante determinista y .NET

En Java usaría strictfp. En C/C++ y otros lenguajes de bajo nivel, este problema se resuelve esencialmente accediendo a los registros de control de FPU/SSE, pero eso probablemente no sea posible en .NET.

Incluso con el control del registro de control FPU, el JIT de .NET generará código diferente en diferentes plataformas. Algo así como HotSpot sería aún peor en este caso ...

¿Por qué lo necesito? Estoy pensando en escribir un juego de estrategia en tiempo real (RTS) que depende en gran medida de la matemática de coma flotante rápida junto con una simulación de bloqueo por pasos. Esencialmente, solo transmitiré la entrada del usuario a través de la red. Esto también se aplica a otros juegos que implementan repeticiones almacenando la entrada del usuario.

No es una opción son:

  • decimales (demasiado lento)
  • valores de punto fijo (demasiado lentos y engorrosos cuando se utiliza sqrt, sin, cos, tan, atan ...)
  • actualización estado en la red como un FPS: enviar información de posición para cientos o miles de unidades no es una opción

¿Alguna idea?

Respuesta

2

No estoy seguro de la respuesta exacta para su pregunta, pero podría usar C++ y hacer todo su trabajo de flotación en un C++ dll y luego devolver el resultado a .Net a través de una interopt.

+0

Si escribo la parte crítica (simulación) del juego en C/C++, entonces puedo simplemente escribir todo el juego sin .Net. Quizás esa sea la manera "correcta" aquí. – user285934

+0

Mire la funcionalidad C/C++ IJW (It-Just-Works) del compilador MSVC. Te permitirá escribir lo que necesitas para escribir como código no administrado, y hacer el resto como código administrado para interactuar sin problemas con el resto de las partes administradas de tu juego. – Ants

1

Los resultados de Bitexact para diferentes plataformas son un dolor en el a **. Si solo usa x86, no debería importar porque la FPU no cambia de de 32 a 64 bits. Pero el problema es que las funciones trascendentales pueden ser más precisas en los procesadores nuevos .

Las cuatro operaciones básicas no deben dar resultados diferentes, pero su VM pueden optimizar expresiones y que pueden dar resultados diferentes. Así que como Ants propuso, escriba sus rutinas add/mul/div/sub como código no administrado para estar en el lado seguro.

Para las funciones trascendentales me temo que debe usar una tabla de búsqueda para garantizar la precisión de bit. Calcule el resultado de, p. 4096 valores, almacénelos como como constantes y si necesita un valor entre ellos, interpole. Esto no le da una gran precisión, pero será bitexact.

+0

Las cuatro operaciones base producen resultados diferentes incluso en un solo procesador cuando la unidad SSE y la FPU no están configuradas correctamente (deshabilite los números subnormales para ambos, utilice valores de 32 bits o 64 bits en fpu en lugar de la precisión máxima). Las funciones trascendentales se pueden implementar en software usando este entorno controlado en C/C++. – user285934

0

Si desea un determinismo de coma flotante, debe eliminar todas las variables. Esto es posible si restringe un poco su alcance.

  1. Haga su aplicación de 64 bits solamente. De esta manera, no tiene que tratar con x87 frente a SSE (x86 JIT aún emite código x87 fp, otros JIT emiten SSE).
  2. Utilice .NET Core y bundle the runtime with your application. De esta manera, usted garantiza el mismo codegen para cualquier versión dada de su aplicación. Esto es crucial, las diferencias de codegen más pequeñas pueden causar cálculos de fp para dar resultados diferentes.
  3. Stick con un sistema operativo. En serio, ¿cuántas RTS de plataformas cruzadas hay por ahí? Sí, está Starcraft 2; eso es todo AFAIK. Blizzard ha dominado este arte durante mucho tiempo y muy pocos podrían replicar esta hazaña. Si realmente quieres admitir el modo multijugador para Mac-PC, deberás verificar minuciosamente que tu tiempo de ejecución .NET genera el mismo código fp en ambas plataformas. Y si no, no tienes suerte.

Un punto del que todavía no estoy seguro es si puede confiar en la clase de Matemáticas para dar resultados consistentes, dadas las restricciones anteriores; pero supongo que debería.

Cuestiones relacionadas