-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc] Change rand implementation so all tests pass in both 32- and 64-bit systems #98692
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
Conversation
@llvm/pr-subscribers-libc Author: Mikhail R. Gadelha (mikhailramalho) ChangesThe current xorshift star algorithm fails to produce uniform enough values in 32-bit systems, so this patch changes the algorithm so the tests now pass in both 32- and 64-bit systems. The multiplier used in the algorithm was obtained from "The Art of Computer Programming" book. It is also used by musl and newlib. Full diff: https://github.com/llvm/llvm-project/pull/98692.diff 1 Files Affected:
diff --git a/libc/src/stdlib/rand.cpp b/libc/src/stdlib/rand.cpp
index ff3875c2f6959..a38d3af7b8aaa 100644
--- a/libc/src/stdlib/rand.cpp
+++ b/libc/src/stdlib/rand.cpp
@@ -13,18 +13,18 @@
namespace LIBC_NAMESPACE {
-// An implementation of the xorshift64star pseudo random number generator. This
-// is a good general purpose generator for most non-cryptographics applications.
+// This multiplier was obtained from Knuth, D.E., "The Art of
+// Computer Programming," Vol 2, Seminumerical Algorithms, Third
+// Edition, Addison-Wesley, 1998, p. 106 (line 26) & p. 108 */
LLVM_LIBC_FUNCTION(int, rand, (void)) {
unsigned long orig = rand_next.load(cpp::MemoryOrder::RELAXED);
for (;;) {
- unsigned long x = orig;
- x ^= x >> 12;
- x ^= x << 25;
- x ^= x >> 27;
- if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE,
+ uint64_t x = orig;
+ x = static_cast<unsigned long>(6364136223846793005ULL) * x;
+ if (rand_next.compare_exchange_strong(orig, static_cast<unsigned long>(x),
+ cpp::MemoryOrder::ACQUIRE,
cpp::MemoryOrder::RELAXED))
- return static_cast<int>((x * 0x2545F4914F6CDD1Dul) >> 32) & RAND_MAX;
+ return static_cast<int>(x >> 32) & RAND_MAX;
sleep_briefly();
}
}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we change x
to uint64_t
wouldn't that also solve the issue? It's called xorshift64star
because it needs 64-bit state, but I forgot that unsigned long
was 32-bit on some systems.
I've tried, and a static_cast back to unsigned long on compare exchange
call, but the fsb test still failed
…On Fri, 12 Jul 2024, 17:49 Joseph Huber, ***@***.***> wrote:
***@***.**** commented on this pull request.
If we change x to uint64_t wouldn't that also solve the issue? It's
called xorshift64star because it needs 64-bit state, but I forgot that unsigned
long was 32-bit on some systems.
—
Reply to this email directly, view it on GitHub
<#98692 (review)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAKEJHZ45JOGB6OW3ICRTNLZMA6MDAVCNFSM6AAAAABKZRQQ6SVHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZDCNZVG4ZDIOBYGA>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
3681378
to
9acec2f
Compare
Can you resolve conflicts? |
9acec2f
to
6ea6bde
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think these should just be separate functions, the constants aren't arbitrary and can't be mixed, making it a template is just confusing.
I can move the code to rand()'s body, wdyt?
|
Works for me, though having the function name helps people know what it's supposed to be. If it's an internal function it'll just be trvially dropped if uncalled. |
…4-bit systems This patch makes rand select different algorithms depending on the arch. This is needed to avoid a test failure in 32-bit systems where the LSB of rand was not uniform enough when the 64-bit constants are used in 32-bit systems.
6ea6bde
to
7698105
Compare
…4-bit systems (#98692) This patch makes rand select different algorithms depending on the arch. This is needed to avoid a test failure in 32-bit systems where the LSB of rand was not uniform enough when the 64-bit constants are used in 32-bit systems.
The current xorshift star algorithm fails to produce uniform enough values in 32-bit systems, so this patch changes the algorithm so the tests now pass in both 32- and 64-bit systems.
The multiplier used in the algorithm was obtained from "The Art of Computer Programming" book. It is also used by musl and newlib.