#define _GNU_SOURCE #include #include #include #include #include #include #include static inline uint64_t read_tscp(void) { uint64_t rax, rcx, rdx; asm volatile("rdtscp" : "=a" (rax), "=d" (rdx), "=c" (rcx)); return rax | (rdx << 32); } /* * * Latences : * N = 16 (cache L1) : ~ 4 cycles * N = 256 (cache L2) : ~ 15 cycles * N = 2048 (cache L3) : ~ 47 cycles * N = 32768 (mémoire) : * locale : ~ 148 cycles * distante un saut: ~ 264 cycles * distante deux sauts: ~ 365 cycles * */ #define NB_LOOPS 10 /* * Cache line, just a structure of 64 bytes */ struct cache_line { uint64_t val[8]; }; /* * Allocate n bytes */ struct cache_line* allocate(uint64_t n) { struct cache_line* buf = mmap(0, n, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0); printf("allocate %lu byte\n", n); if(buf == MAP_FAILED) { perror("mmap"); exit(1); } return buf; } /* * Prepare the buffer to perform a randomized access */ void randomize(struct cache_line* buf, uint64_t n) { uint64_t c = 0, r; srand(time(NULL)); for(uint64_t i=0; i<(n-1); i++) { buf[c].val[0] = 1; do { r = rand() % n; } while(buf[r].val[0]); buf[c].val[0] = r; c = r; } buf[c].val[0] = 0; } void randomize_other_soluce(struct cache_line* buf, uint64_t n) { uint64_t elements[n-1]; for(uint64_t i=0; i<(n-1); i++) elements[i] = i + 1; uint64_t cur = 0; for(uint64_t i=n-1; i>0; i--) { uint64_t k = rand() % i; buf[cur].val[0] = elements[k]; elements[k] = elements[i-1]; cur = buf[cur].val[0]; } buf[cur].val[0] = 0; } /* * Access all the nbc cache lines of the buffer buf */ uint64_t access(struct cache_line* buf, uint64_t nbc) { uint64_t r = 0; for(uint64_t i=0; i