File: random_numerators.hpp

package info (click to toggle)
libdivide 5.2.0-0.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 17,564 kB
  • sloc: ansic: 131,647; cpp: 70,136; python: 47; makefile: 3
file content (102 lines) | stat: -rw-r--r-- 2,688 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#pragma once

#include <time.h>

#if defined(__AVR__)
int freeRAM()
{
	extern int __heap_start, *__brkval;
	int v;
	return (int) &v - (__brkval == 0 ? (int) &__heap_start: (int) __brkval);
}
#endif

// A READONLY buffer of RANDOM LENGTH and RANDOM CONTENT
template <typename T>
class random_numerators {
private:

    uint32_t *_pData;
    uint32_t _length;

    uint32_t *allocate(uint32_t size) {
#if defined(__AVR__)
        return (uint32_t *)malloc(size);
#elif defined(LIBDIVIDE_WINDOWS)
        /* Align memory to 64 byte boundary for AVX512 */
        return (uint32_t *)_aligned_malloc(size, 64);
#else
        /* Align memory to 64 byte boundary for AVX512 */
        void *ptr = NULL;
        int failed = posix_memalign(&ptr, 64, size);
        if (failed) {
            printf("Failed to align memory!\n");
            exit(1);
        }
        return  (uint32_t *)ptr;
#endif
    }

    static void deallocate(uint32_t *pData) {
#if defined(LIBDIVIDE_WINDOWS)
        _aligned_free((void *)pData);
#else
        free((void *)pData);
#endif        
    }

    struct random_state {
        uint32_t hi;
        uint32_t lo;
    };

    static uint32_t my_random(struct random_state *state) {
        state->hi = (state->hi << 16) + (state->hi >> 16);
        state->hi += state->lo;
        state->lo += state->hi;
        return state->hi;
    }

    void randomize_buffer() {
        size_t size = (length() * sizeof(T)) / sizeof(*_pData);
        struct random_state state = { 2147483563, 2147483563 ^ 0x49616E42 };
        for (size_t i = 0; i < size; i++) {
            _pData[i] = my_random(&state);
        }
    }

public:

    using const_pointer   = const T *;
    using const_reference = const T&;
    using const_iterator  = const_pointer;

    random_numerators() {
#if defined(__AVR__)
        // Using 1/8 of free RAM should be enough to fool the 
        // compiler optimizer and give enough test iterations on
        // AVR hardware
        _length = (freeRAM()/8)/sizeof(T);
#else
        _length = 1 << 19;
        // Make sure that the number of iterations is not
        // known at compile time to prevent the compiler
        // from magically calculating results at compile
        // time and hence falsifying the benchmark.        
        srand((unsigned)time(NULL));
        _length += (rand() % 3) * (1 << 10);
#endif 
        _pData = allocate(_length * sizeof(T));

        randomize_buffer();
    }

    ~random_numerators() {
        deallocate(_pData);
    }

    const_iterator begin() const { return (const_pointer)_pData; }
    const_iterator end() const { return begin()+length(); }

    uint32_t length() const { return _length; }
};