$ lscpu | grep "^Model n"
Model name: AMD Ryzen 7 7700 8-Core Processor
$ CFLAGS=-O3 make m
cc -O3 m.c -o m
$ ./m
Start Creator
End Creator, Time required = 4.57157 seconds
99999999
mult: 0.023283
Start Pointer Copy (800 Megabytes)
End Pointer Copy, Time required = 0.04994 seconds
Start Shaker
End Shaker, Time required = 2.22900 seconds
0: 54146917, 1: 15112755, 2: 48826822, 3: 90161046, 4: 10923243,
99999999: 54148343, 99999998: 52793713, 99999997: 68249870, 99999996: 17562227,
Start sampling (5 Percent) (5000000 count)
End Sampling Time required = 0.12274 seconds
0: 82482960, 1: 47175951, 2: 37191809, 3: 41093301, 4: 55602759,
Start sampling (10 Percent) (10000000 count)
End Sampling Time required = 0.24817 seconds
0: 78543114, 1: 4953348, 2: 96917277, 3: 57940122, 4: 68840531,
Start sampling (15 Percent) (15000000 count)
End Sampling Time required = 0.37811 seconds
0: 71401878, 1: 71245615, 2: 28743191, 3: 81102185, 4: 49441787,
Start sampling (20 Percent) (20000000 count)
End Sampling Time required = 0.51284 seconds
0: 51449520, 1: 54203948, 2: 48830793, 3: 38648269, 4: 2932325,
Start sampling (25 Percent) (25000000 count)
End Sampling Time required = 0.65101 seconds
0: 13677937, 1: 38751965, 2: 28455323, 3: 40211532, 4: 77048749,
Start sampling (30 Percent) (30000000 count)
End Sampling Time required = 0.79616 seconds
0: 19157634, 1: 86224120, 2: 21237978, 3: 44600371, 4: 72549474,
Start sampling (35 Percent) (35000000 count)
End Sampling Time required = 0.94841 seconds
0: 78075291, 1: 23268388, 2: 4078930, 3: 12950136, 4: 35845025,
Start sampling (40 Percent) (40000000 count)
End Sampling Time required = 1.11407 seconds
0: 9685732, 1: 76826284, 2: 21667725, 3: 64293081, 4: 4223722,
Start sampling (45 Percent) (45000000 count)
End Sampling Time required = 1.29862 seconds
0: 4422140, 1: 37975280, 2: 20967172, 3: 52639719, 4: 55117114,
Start sampling (50 Percent) (50000000 count)
End Sampling Time required = 1.50990 seconds
0: 38379790, 1: 99657310, 2: 11661422, 3: 60556903, 4: 56984284,
Start sampling (55 Percent) (55000000 count)
End Sampling Time required = 1.77024 seconds
0: 90483048, 1: 28992318, 2: 43425535, 3: 26784200, 4: 29736220,
Start sampling (60 Percent) (60000000 count)
End Sampling Time required = 2.08957 seconds
0: 8162742, 1: 75658173, 2: 6369056, 3: 66982369, 4: 29892973,
Start sampling (65 Percent) (65000000 count)
End Sampling Time required = 2.45925 seconds
0: 49468421, 1: 16180629, 2: 25248074, 3: 97352443, 4: 99277901,
Start sampling (70 Percent) (70000000 count)
End Sampling Time required = 2.87456 seconds
0: 17534114, 1: 16463428, 2: 85334151, 3: 31573731, 4: 93497949,
Start sampling (75 Percent) (75000000 count)
End Sampling Time required = 3.32572 seconds
0: 11736580, 1: 98481698, 2: 73895709, 3: 35632777, 4: 53114223,
Start sampling (80 Percent) (80000000 count)
End Sampling Time required = 3.80037 seconds
0: 41698599, 1: 31345766, 2: 80130064, 3: 82786614, 4: 74684718,
Start sampling (85 Percent) (85000000 count)
End Sampling Time required = 4.30775 seconds
0: 55397316, 1: 13262261, 2: 21874730, 3: 72380467, 4: 48686991,
Start sampling (90 Percent) (90000000 count)
End Sampling Time required = 4.86745 seconds
0: 33692799, 1: 66840080, 2: 12800394, 3: 10943696, 4: 79676488,
Start sampling (95 Percent) (95000000 count)
End Sampling Time required = 5.67329 seconds
0: 38726026, 1: 74504358, 2: 91645937, 3: 47024247, 4: 59864699,
$ cat m.c
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#define mw_state_n 624
// Version 0.1 (Bugs: many :-)
// Use "ulimit -s" for alloca !!!!! If ulimit is not availible substitute alloa with malloc (#define alloca malloc)
#define myrand ((int) ((double) random_uint32(&rnd_state) * mult));
typedef struct {
uint32_t state_array[mw_state_n]; // the array for the state vector
int state_index; // index into state vector array, 0 <= state_index <= n-1 always
} mt_state;
void initialize_state(mt_state* state, uint32_t seed);
uint32_t random_uint32(mt_state* state);
int main(int argc, char** argv)
{
// int i, ElementsCnt = 100;
// int i, ElementsCnt = 65535;
int i, ElementsCnt = 100000000;
int percent;
char **Elements, **Elements_copy;
char *issampled;
struct timespec begin, end;
double mult;
mt_state rnd_state;
printf("%s\n", "Start Creator"); clock_gettime(CLOCK_MONOTONIC, &begin);
Elements = alloca(ElementsCnt * sizeof(char*)); // TODO check
for (i = 0; i <= ElementsCnt; i++) {
char buff[100];
snprintf(buff, 100, "%d", i);
if (!(Elements[i] = alloca(strlen(buff) + 1))) { puts("mem"); exit(1); }
strcpy(Elements[i], buff);
}
clock_gettime(CLOCK_MONOTONIC, &end); printf("End Creator, Time required = %.5f seconds\n\n", ((double) end.tv_sec + 1.0e-9 * end.tv_nsec) - ((double) begin.tv_sec + 1.0e-9 * begin.tv_nsec));
puts(Elements[ElementsCnt - 1]);
initialize_state(&rnd_state, 19650218UL);
mult = (double) (ElementsCnt ) / UINT32_MAX;
// mult = (double) (ElementsCnt ) / (UINT32_MAX & 0x0000ffff);
printf("mult: %f\n", mult);
// for (i = 0; 1 ; i++) {
// printf("%d rand: %u\n", i, (int) ((double) (random_uint32(&rnd_state) & 0x0000ffff) * mult));
// printf("%d rand: %d %d\n", i, (int) ((double) random_uint32(&rnd_state) * mult), ElementsCnt);
// }
Elements_copy = alloca(ElementsCnt * sizeof(char*)); printf("\nStart Pointer Copy (%ld Megabytes)\n", ElementsCnt * sizeof(char*) / 1000000); // TODO check
clock_gettime(CLOCK_MONOTONIC, &begin);
memcpy(Elements_copy, Elements, ElementsCnt * sizeof(char*)); clock_gettime(CLOCK_MONOTONIC, &end);
printf("End Pointer Copy, Time required = %.5f seconds\n\n", ((double) end.tv_sec + 1.0e-9 * end.tv_nsec) - ((double) begin.tv_sec + 1.0e-9 * begin.tv_nsec));
printf("\n%s\n", "Start Shaker"); clock_gettime(CLOCK_MONOTONIC, &begin);
for (i = 0; i <= ElementsCnt; i++) {
char* tmp_Element;
int rand;
rand = myrand;
tmp_Element = Elements[i];
Elements[i] = Elements[rand];
Elements[rand] = tmp_Element;
}
clock_gettime(CLOCK_MONOTONIC, &end); printf("End Shaker, Time required = %.5f seconds\n\n", ((double) end.tv_sec + 1.0e-9 * end.tv_nsec) - ((double) begin.tv_sec + 1.0e-9 * begin.tv_nsec));
for (i = 0; i <= 4; i++) {
printf("%d: %s, ", i, Elements[i]);
}
puts("");
for (i = ElementsCnt -1; i >= ElementsCnt - 4; i--) {
printf("%d: %s, ", i, Elements[i]);
}
puts(""); puts("");
memcpy(Elements, Elements_copy, ElementsCnt * sizeof(char*)); // deshake for sampling
#define inc_with_wrap(foo) (foo < ElementsCnt ? foo + 1 : 0)
issampled = alloca(ElementsCnt); // TODO check
for (percent = 5; percent <= 95; percent += 5) {
int cnt, tmp, run, rand, runner = 0;
bzero(Elements_copy, ElementsCnt * sizeof(char*));
bzero (issampled,ElementsCnt);
cnt = (int) (ElementsCnt * ((double) percent / 100));
printf("Start sampling (%d Percent) (%d count)\n", percent, cnt); clock_gettime(CLOCK_MONOTONIC, &begin);
for (i = 0; i <= cnt; i++) {
rand = myrand;
if (!issampled[rand]) { // Element was free;
Elements_copy[runner++] = Elements[rand]; issampled[rand]++;
} else { // Element was sampled before
tmp = rand;
tmp = inc_with_wrap(tmp);
while (rand != tmp && issampled[tmp]) { // Search for Empty Element
tmp = inc_with_wrap(tmp);
}
if (rand == tmp) {
puts("Infinite Loop stopped");
exit(1);
}
Elements_copy[runner++] = Elements[tmp]; issampled[tmp]++;
}
}
clock_gettime(CLOCK_MONOTONIC, &end); printf("End Sampling Time required = %.5f seconds\n", ((double) end.tv_sec + 1.0e-9 * end.tv_nsec) - ((double) begin.tv_sec + 1.0e-9 * begin.tv_nsec));
for (run = 0; run <= 4; run++) {
printf("%d: %s, ", run, Elements_copy[run] ? Elements_copy[run] : "NULL");
}
puts(""); puts("");
}
exit (0);
}
// https://en.wikipedia.org/wiki/Mersenne_Twister
// replaced by mw_state_n
// #define n 624
#define m 397
#define w 32
#define r 31
#define UMASK (0xffffffffUL << r)
#define LMASK (0xffffffffUL >> (w-r))
#define a 0x9908b0dfUL
#define u 11
#define s 7
#define t 15
#define l 18
#define b 0x9d2c5680UL
#define c 0xefc60000UL
#define f 1812433253UL
void initialize_state(mt_state* state, uint32_t seed)
{
uint32_t* state_array = &(state->state_array[0]);
state_array[0] = seed; // suggested initial seed = 19650218UL
for (int i=1; i<mw_state_n; i++)
{
seed = f * (seed ^ (seed >> (w-2))) + i; // Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
state_array[i] = seed;
}
state->state_index = 0;
}
uint32_t random_uint32(mt_state* state)
{
uint32_t* state_array = &(state->state_array[0]);
int k = state->state_index; // point to current state location
// 0 <= state_index <= n-1 always
// int k = k - n; // point to state n iterations before
// if (k < 0) k += n; // modulo n circular indexing
// the previous 2 lines actually do nothing
// for illustration only
int j = k - (mw_state_n-1); // point to state n-1 iterations before
if (j < 0) j += mw_state_n; // modulo n circular indexing
uint32_t x = (state_array[k] & UMASK) | (state_array[j] & LMASK);
uint32_t xA = x >> 1;
if (x & 0x00000001UL) xA ^= a;
j = k - (mw_state_n-m); // point to state n-m iterations before
if (j < 0) j += mw_state_n; // modulo n circular indexing
x = state_array[j] ^ xA; // compute next value in the state
state_array[k++] = x; // update new state value
if (k >= mw_state_n) k = 0; // modulo n circular indexing
state->state_index = k;
uint32_t y = x ^ (x >> u); // tempering
y = y ^ ((y << s) & b);
y = y ^ ((y << t) & c);
uint32_t z = y ^ (y >> l);
return z;
}
$