No, this isn’t how it works. The atomic add is needed to remove the data race.
From a brief look, if you invoke the function with doubles, the computation should be done in doubles, so you could just cast to double, run the kernel then cast back. Note that double computation is much slower than single precision (aka float). Still it should give you an idea of how much of an improvement you see in avoiding randomness in your outputs.
Best regards
Thomas