Is Clang more deterministic than GCC on different platforms?

I am considering programming a multi-player RTS game (partially) in C ++. What I quickly discovered is that one tough requirement is that the game simulation must be completely deterministic for the very last bit on the server and all clients in order to be able to restrict the network connection by the user and not by the game state itself, Because everyone has a different computer, this seems like a difficult problem.

So, is there any “magic” way to get a C ++ compiler to create an executable that will be completely deterministic for Linux (server), Windows and Mac? I think the two main OSS C ++ compilers are GCC and Clang, so I was wondering if it works better than others in this regard.

I will also be interested in any test suite that could be used to test C ++ determinism.

[EDIT] By deterministic, I meant that a compiled program, taking into account the same initial state and input in the same order, will always produce the same result on any platform where it runs. Thus, also throughout the network. Consistent sounds, as a suitable definition of this behavior for me, but I am not a native speaker, so I could misinterpret the exact meaning.

[EDIT # 2] While discussions about whether determinism / consistency have, and whether I should strive for this in the game engine, and how big a problem it is in C ++ at all, is pretty interesting, this is by no means actually answer the question. So far, no one has had any facts telling me whether to use Clang or GCC to get the most reliable / deterministic / consistent results.

[EDIT # 3] It just occurred to me that there is a way to get exactly the same result in C ++ as in Java. You need to take the open source JVM implementation and extract the code that implements the operators and mathematical functions. Then you turn it into a stand-alone library and call the built-in functions inside it, instead of using operators directly. It would be painful to do this manually, but if the code is generated, then this is the perfect solution. Perhaps this can even be done with classes and operator overloading, so it also looks natural.

+6
source share
5 answers

Because everyone has a different computer, this seems like a difficult problem.

This is not true. Indeed, this kind of network is quite simple if you are not doing anything that is undefined by specification. IEEE-754 speaks very clearly about how floating point math should be done, how rounding should be done, etc., and it is implemented the same on all platforms.

The biggest thing you do not need to do is rely on the SIMD processor instructions in the code, which must be deterministic (note: this is physics, AI, etc .: game state. Not graphics where you need SIMD). These instructions are played quickly and freely using floating point rules. Thus, there is no SIMD in the game code; only in the "client" code (graphics, sound, etc.).

In addition, you need to make sure that your playing state is independent of things like time; Each game state clock gadget should be a fixed time interval, not based on a PC clock or the like.

Obviously, you should avoid any random function in which you have no code. But then again, only for your main game loop; graphic material may be specific to the client, as it simply visualizes and does not matter.

This is pretty much the case if you keep two game states in sync. The compiler you use will not be a big problem for you.

Please note that StarCraft and StarCraft II use this as the basis of their network model. They both work on Macs and PCs, and both can play against each other. So it is very possible and does not require Clang.

Although, if you like Klang, you should use it. But it should be because you like it, not for networks.

+1
source

Do not rely on undefined or undefined behavior (in particular, do not use floating point), and it does not matter which compiler you use.

If a is 1, and b is 2, then a + b is 3. This is guaranteed by the language standard.

C ++ is not land in which in some compilers some things are "deterministic" and in other compilers they are not. C ++ contains some facts (e.g. 1 + 2 == 3) and leaves some things to the compiler (e.g., the order in which function arguments are evaluated). If the output of your program depends only on the previous one (and user input), and you use a compiler compatible with the standards, then your program will always produce the same result, given the same user input.

If the output of your program also depends on (say) the user operating system, then the program is still deterministic, simply that the output is now determined by both user input and the operating system. If you want the output to depend only on user input, you need to make sure that the user operating system is not a factor contributing to the exit of your program. One way to do this is to rely only on the behavior guaranteed by the language standard and use a compiler that complies with this standard.

Thus, the entire code is determined based on its input. You just need to make sure that the input consists only of what you want.

+1
source

I think which compiler you use doesn't really matter.

Such a completely deterministic approach was used, for example, in Doom. Instead of a random number generator, they used a fixed "random" array number. Game time was measured in in-game ticks (it was about 1/30 second, if I remember).

If you measure everything in game mechanics, and do not unload your work into some standard libraries that may appear in different versions, I believe that you should achieve good portability on different machines. Of course, if these machines are fast enough to run your code!

However, network communication can create problems on its own: delays, drops, etc. Your game should be able to process delayed messages and, if necessary, re-synchronize itself. For example, you might want to send a full (or at least more detailed) game state, rather than relying solely on user input.

Think about possible feats:

  • Client: I throw a grenade
  • Server: you don't have grenades
  • Client: I don't care. Nevertheless, I throw a grenade.
0
source

This is a bit stupid thing. Your program will not be “completely deterministic” (whatever that means) “to the last bit” on a large end machine compared to a small end machine, and also on a 64-bit machine compared to a 32-bit machine compared to any or another random machine.

Speaking of randomness, many games have an element of randomness. If you achieve this by calling the c-standard rand () function, all bets are disabled.

0
source

If you start using floating point, all your bets are disabled. You will encounter difficulties in finding / fixing problems when you get different values ​​even on the same platform, simply by choosing an Intel or AMD processor.

Many runtime libraries have optimized code paths for different chips. All of them are in the specification, but some of them are a little more accurate. This leads to subtle rounding errors, which sooner or later accumulate to a difference that can disrupt the work.

Your goal should be to escape without 100% determinism. In the end: does it matter to the player if the adversary is a pixel larger on the left than it should? Is not. The important thing is that small differences between clients and server do not destroy the gameplay.

What a player sees on his screen should look deterministic, so he does not feel cheated, but this is by no means required.

The games in which I worked are archived, constantly re-synchronizing the state of the game of all objects between all clients. However, we almost never sent the entire gameplay, but we sent the game state from several objects to each frame, distributing the task for several seconds.

Just give objects in which it has the highest priority than others, and everything will be fine. For example, in an automobile racing game, the exact position of the opponent’s car does not matter if it is far away from you, and it’s normal to only update it every 20 seconds or so.

Inside these updates, simply believe that small rounding errors do not accumulate so much that you run into problems.

0
source

Source: https://habr.com/ru/post/892434/


All Articles