TL;DR

  • GameMathFreeBSD msun에서 파생된 독립형 C 수학 라이브러리로, IEEE 754 준수 시스템과 컴파일러·하드웨어 사이에서 일관된 부동소수점 연산을 제공함.
  • 클라이언트가 각자 시뮬레이션 상태를 유지하는 게임의 락스텝 시뮬레이션(lock-step simulation)에서 바이너리 수준의 연산 불일치로 인한 동기화 이탈을 줄이는 용도임.
  • 플랫폼별 libc 수학 라이브러리 대신 공통 소프트웨어 구현을 사용해 CPU 모델과 라이브러리 버전에 따른 결과 차이의 한 가지 원인을 제거함.
  • gmath.hgamemath_static_lib를 통해 통합하며, 표준 C 수학 함수의 GameMath 버전은 gm_ 접두사를 사용하고 현재는 float 정밀도 함수만 구현됨.
  • 일관성이 정확도보다 중요한 게임 네트워킹 관점의 라이브러리이며, 컴파일러의 FLT_EVAL_METHOD == 0 설정과 streflop 등 대안의 특성을 함께 고려해야 함.

GameMath 개요

  • GameMathFreeBSD msun 라이브러리에서 파생된 C 수학 라이브러리임.
  • 자체 완결형 부동소수점 수학 라이브러리를 제공해 IEEE 754 준수 시스템에서 일관되게 동작하고, 컴파일러와 하드웨어 사이에서 부동소수점 연산을 재현 가능하게 만드는 것이 목적임.
  • 네트워크 및 리플레이 코드가 클라이언트별 시뮬레이션 상태 유지에 의존하고, 클라이언트 사이에는 명령 목록만 전달하는 게임에 필요함.
  • 이러한 락스텝 시뮬레이션에서는 바이너리 수준의 부동소수점 결과가 일치하지 않으면 시뮬레이션이 서로 달라져 동기화가 깨질 수 있음.

플랫폼 수학 라이브러리의 문제

  • 플랫폼의 libc 수학 라이브러리에 의존하는 방식은 여러 문제를 일으킬 수 있음.
  • 일부 라이브러리는 사용 가능한 경우 CPU의 초월 함수 명령을 호출하며, CPU 모델에 따라 서로 다른 결과가 나올 수 있음.
  • CPU 명령을 사용하지 않는 경우에도 같은 플랫폼에서 라이브러리 버전이 업데이트되면 결과가 달라질 수 있고, 플랫폼 사이의 일관성도 거의 보장되지 않음.
  • 공통 소프트웨어 라이브러리로 해당 연산을 처리하면 결과 불일치의 한 가지 원인을 제거할 수 있음.

사용 방법

  • 권장 방식은 GameMath를 소스 트리에 포함하고 cmake에서 하위 디렉터리로 추가하는 것임.
  • 이후 주 바이너리를 gamemath_static_lib 대상에 연결하고, 일반적으로 math.h 또는 cmath를 포함하는 위치에 gmath.h를 포함함.
  • 표준 C 수학 함수에 대응하는 GameMath 함수는 gm_ 접두사를 사용함.
  • 예를 들어 tanf 대신 gm_tanf를 사용함.
  • 현재는 float 정밀도 버전의 함수만 구현됨.

부동소수점 일관성의 한계

  • GameMath만으로 모든 부동소수점 결과의 일관성을 보장할 수 있는 것은 아니며, 특정 플랫폼의 libc 구현과 동일한 정확도를 제공하지 않을 수 있음.
  • 게임 네트워킹 관점에서는 일반적으로 정확한 결과보다 일관된 결과가 더 중요함.
  • SEI CERT C Coding Standard는 부동소수점 값을 다룰 때 고려해야 할 추가 문제와 완화 방법을 제시함.
  • 가능한 경우 컴파일러가 FLT_EVAL_METHOD == 0이 되도록 구성하는 것이 권장됨.
  • x86 플랫폼에서는 일반적으로 SSE2 코드 생성을 활성화해 해당 설정을 적용함.
  • GameMath의 float 정밀도 구현 대부분은 float 정밀도만 사용하므로 SSE만 필요할 수 있음.

대안

  • 부동소수점 수학 라이브러리를 찾을 때 openlim 또는 streflop을 접할 수 있음.
  • 두 라이브러리 중 순수 소프트웨어 구현을 사용하고 플랫폼과 컴파일러 사이의 일관된 결과를 목표로 하는 것은 streflop임.
  • streflop은 GameMath보다 기능이 풍부하지만, 순수 C 인터페이스가 아닌 C++ 인터페이스만 구현함.
  • 또한 streflop은 LGPL 라이선스이므로 LGPL로 라이선스하지 않거나 LGPL의 제한을 따르지 않으려는 프로젝트에서는 특정 버전의 라이브러리를 정적으로 연결하는 데 제약이 있음.