Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ti.random(ti.i32) always returns number of the same parity in the same thread #7182

Closed
AmesingFlank opened this issue Jan 16, 2023 · 12 comments
Assignees

Comments

@AmesingFlank
Copy link
Collaborator

AmesingFlank commented Jan 16, 2023

Consider this program which generates 100 random ints and checks their parity (even or odd)

import taichi as ti
x = [0,0]

for i in range(100):
    ti.init(ti.cuda, random_seed=i)

    @ti.kernel
    def k() -> int:
        return ti.random(ti.i32) % 2 
    p = k()
    x[p] += 1

print(x) 

This ends up printing

[100, 0]

More generally, I noticed that, for a given thread, regardless of the random seed, the 1st random int it generates always has the same parity.

@lucifer1004
Copy link
Contributor

lucifer1004 commented Jan 20, 2023

Ideas:

  • Make a separate package and implement multiple RNGs with Taichi.

Resources:

@lin-hitonami
Copy link
Contributor

@lucifer1004 Thanks! Would you like to contribute the RNGs to Taichi? Maybe we can let them be an official module (maybe ti.math.random?) in Taichi.

@lin-hitonami
Copy link
Contributor

We need to expose the random states of each thread to Python first if we want to implement RNGs outside the Taichi runtime.

struct RandState {
u32 x;
u32 y;
u32 z;
u32 w;
i32 lock;
};

@lucifer1004
Copy link
Contributor

lucifer1004 commented Jan 20, 2023

I would love to contribute, but I have higher priorities at the moment. So if this needs to be implemented very soon, I may not be able to help.

@lin-hitonami
Copy link
Contributor

lin-hitonami commented Jan 20, 2023

@lucifer1004 Thank you very much! This is an old problem, and this doesn't need to be implemented very soon. Please contribute whenever is convenient for you!

@lucifer1004
Copy link
Contributor

lucifer1004 commented Jan 22, 2023

@lin-hitonami @yuanming-hu

As for this specific issue, the root cause is

int starting_rand_state = config_->random_seed * 1048576;

Then the x part of the initial random state is always an even number.

void initialize_rand_state(RandState *state, u32 i) {
state->x = 123456789 * i * 1000000007;
state->y = 362436069;
state->z = 521288629;
state->w = 88675123;
state->lock = 0;
}

If we change 1048576 to 1048577, for example, the output of @AmesingFlank 's code would be [51, 49].

@bobcao3
Copy link
Collaborator

bobcao3 commented Jan 26, 2023

We can move it to 1048391 which is a prime?

@lin-hitonami
Copy link
Contributor

@lucifer1004 @bobcao3 Thanks! Let me make a quick fix.

@lin-hitonami
Copy link
Contributor

BTW @bobcao3 it seems that the SPIRV-based backends don't use this random seed?

@bobcao3
Copy link
Collaborator

bobcao3 commented Jan 28, 2023

BTW @bobcao3 it seems that the SPIRV-based backends don't use this random seed?

They don't (and they uses a different algorithm), so this doesn't apply there.

lin-hitonami added a commit that referenced this issue Jan 28, 2023
@lucifer1004
Copy link
Contributor

Shall we close this issue and open a new one to track the RNG implementations? @lin-hitonami

@lin-hitonami
Copy link
Contributor

Good idea! Please open a new one!

@github-project-automation github-project-automation bot moved this from Todo to Done in Taichi Lang Jan 31, 2023
quadpixels pushed a commit to quadpixels/taichi that referenced this issue May 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

No branches or pull requests

4 participants