0

I'm implementing an algorithm. Because calculations takes time, and I need to repeat them multiple times, I'm saving to output file seed values as well. The idea was that I could repeat same instance of a program if I'll need to get more info about what was happening (like additional values, some percentage, anything that will not mess in the algorithm itself).

Unfortunately, even though I thought everything worked as intended, about 20% of the seeded instances gave different values in at least one of the outputted values.

My question is - what type of changes in the code affects how srand() / rand() works in C++? Each class is compiled separately and all are linked together at the end. Can I implement functions and everything will be fine? Does it break only when I change the size of any class in the program by adding/removing class fields? Is it connected with heap/stack allocation?

Until now, I thought that if I seed srand() I will have same order of rand() values no matter what (eg. for srand(123) I'll always get first rand() == 5, second rand() == 8 etc.). And I can break it only when I'll put more rand() calls in between.

I hope you could find where I'm thinking wrong, or you could link something that will help me.

Cheers mrozo

mrozo
  • 53
  • 6
  • 1
    Your thought of `srand` and `rand` are correct, that's how they should work. Do you have a [mre] of the problematic code you can show us? – Some programmer dude Apr 06 '22 at 09:06
  • 1
    On another note, since the C++11 standard (published over ten years ago, and supported by all major compilers) there's a much better [pseudo-random generation library](https://en.cppreference.com/w/cpp/numeric/random). It also supports setting seeds and should be predictable from the seed. – Some programmer dude Apr 06 '22 at 09:07
  • @Someprogrammerdude Unfortunately, I don't think that I could be able to make minimal reproducible example from that. But maybe I found another problem, according to the [cppreference](https://en.cppreference.com/w/c/numeric/random/srand) `srand` is not guaranteed to be thread safe. I'm not using threads in the program itself, but I'm using [GNU parralel](https://www.gnu.org/software/parallel/) to run same program multiple times on many threads. – mrozo Apr 06 '22 at 09:28
  • Also, from your second comment I understand that `srand` should be avoided. In my algorithm I'm calling `rand` thousands of times, so if 46/60 program executions for different topologies (network optimization problem) gives excactly the same results, where most of the outputs are more complicated than 0/1 (that could be reproduced by luck), then maybe there is accually a problem with `rand` not being always predictable. – mrozo Apr 06 '22 at 09:29
  • 1
    Not just `srand`, but `rand` should be avoided in general in C++ programs nowadays. See also: https://stackoverflow.com/questions/52869166 . – Peter O. Apr 06 '22 at 11:07

1 Answers1

2

Your understanding about srand is correct: seeding with a specific value should be enough to generate a reproducible sequence of random numbers. You should debug your application to discover why it behaves in a non-reproducible way.

One reason for such behavior is a race condition on the hidden RNG state. Quoting from the C++ rand wiki:

It is implementation-defined whether rand() is thread-safe.

...

It is recommended to use C++11's random number generation facilities to replace rand().

anatolyg
  • 26,506
  • 9
  • 60
  • 134
  • How should I understand *thread-safe*? Of course it refers to obvious - when you implement multiple threads in the single program. But if I execute multiple times a compiled program on multiple threads simultaneously (I'm using [GNU parralel](https://www.gnu.org/software/parallel/) to do so), could it be also a threat for *thread-safe* that wiki refers to? – mrozo Apr 06 '22 at 09:43
  • I don't know any details about GNU parallel. I think yes, it should have problems with non-thread-safe code. You can check this using a simple test program, or possibly ask a dedicated question on that. – anatolyg Apr 06 '22 at 11:02
  • 1
    @mrozo -- even if `rand()` is thread-safe, calling it from multiple threads will not produce consistent results, because the sequence of the calls will vary. If that's what your code is doing, getting reproducible sequences requires a separate random number generator for each thread. `rand()` isn't equipped for that. – Pete Becker Apr 06 '22 at 13:15
  • @PeteBecker thanks a lot, I'll look for different random number generator that will work for those kind of calls. – mrozo Apr 06 '22 at 19:18