|
#include <stdint.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <immintrin.h> |
|
#include <time.h> |
|
#include <string.h> |
|
|
|
double milliDiff(struct timespec *start, struct timespec *end) |
|
{ |
|
return |
|
(( end->tv_sec * 1000) + ( end->tv_nsec * 0.000001)) - |
|
((start->tv_sec * 1000) + (start->tv_nsec * 0.000001)); |
|
} |
|
|
|
#define PAGESIZE 4096 |
|
|
|
// A <- B ^ C; |
|
__attribute__((noinline)) |
|
void xor(uint8_t *A, uint8_t *B, uint8_t *C) { |
|
for (int i = 0; i < PAGESIZE; i += 128) { |
|
__m256i* p = (__m256i*)(A+i); |
|
__m256i* q = (__m256i*)(B+i); |
|
__m256i* r = (__m256i*)(C+i); |
|
|
|
__m256i v1 = _mm256_load_si256(q+0); |
|
__m256i v2 = _mm256_load_si256(q+1); |
|
__m256i v3 = _mm256_load_si256(q+2); |
|
__m256i v4 = _mm256_load_si256(q+3); |
|
|
|
__m256i w1 = _mm256_load_si256(r+0); |
|
__m256i w2 = _mm256_load_si256(r+1); |
|
__m256i w3 = _mm256_load_si256(r+2); |
|
__m256i w4 = _mm256_load_si256(r+3); |
|
|
|
__m256i x1 = _mm256_xor_si256(v1, w1); |
|
__m256i x2 = _mm256_xor_si256(v2, w2); |
|
__m256i x3 = _mm256_xor_si256(v3, w3); |
|
__m256i x4 = _mm256_xor_si256(v4, w4); |
|
|
|
_mm256_store_si256(p+0, x1); |
|
_mm256_store_si256(p+1, x2); |
|
_mm256_store_si256(p+2, x3); |
|
_mm256_store_si256(p+3, x4); |
|
} |
|
} |
|
|
|
#define NUM 120 |
|
|
|
uint8_t program(uint8_t* data[NUM], uint8_t* store[NUM]) { |
|
// 特に意味はないプログラム |
|
|
|
// (0, 1); (2, 3); (4, 5); ... |
|
for(int i = 0; i < NUM; i += 2) { |
|
xor(store[i+0], data[i+0], data[i+1]); |
|
} |
|
|
|
// (0, 2); (1, 3); |
|
// (4, 6); (5, 7); |
|
// ... |
|
for(int i = 0; i < NUM; i += 4) { |
|
xor(store[i+0], data[i+0], data[i+2]); |
|
xor(store[i+1], data[i+1], data[i+3]); |
|
} |
|
|
|
// (0, 3); (1, 4); (2, 5); |
|
// (6, 9); (7, 10); (8, 11); |
|
for(int i = 0; i < NUM; i += 6) { |
|
xor(store[i+0], data[i+0], data[i+3]); |
|
xor(store[i+1], data[i+1], data[i+4]); |
|
xor(store[i+2], data[i+2], data[i+5]); |
|
} |
|
|
|
// (0, 4); (1, 5); (2, 6); (3, 7) |
|
// (8, 12); (9, 13); (10, 14); (11, 15); |
|
for(int i = 0; i < NUM; i += 8) { |
|
xor(store[i+0], data[i+0], data[i+4]); |
|
xor(store[i+1], data[i+1], data[i+5]); |
|
xor(store[i+2], data[i+2], data[i+6]); |
|
xor(store[i+3], data[i+3], data[i+7]); |
|
} |
|
|
|
uint8_t sum = 0; |
|
for(int i = 0; i < NUM; ++i) { |
|
for(int j = 0; j < 4096; ++j) { |
|
sum += store[i][j]; |
|
} |
|
} |
|
|
|
return sum; |
|
} |
|
|
|
uint8_t program2(uint8_t* data[NUM], uint8_t* store[NUM]) { |
|
/* |
|
program1を最適化したもの |
|
こっちでは |
|
0..7 まで |
|
8..15 まで |
|
という形で 8個を1グループ として |
|
グループごとに処理していく |
|
*/ |
|
|
|
for(int i = 0; i < NUM; i += 8) { |
|
xor(store[i+0], data[i+0], data[i+1]); |
|
xor(store[i+1], data[i+1], data[i+3]); |
|
xor(store[i+2], data[i+2], data[i+5]); |
|
xor(store[i+3], data[i+3], data[i+7]); |
|
xor(store[i+0], data[i+0], data[i+2]); |
|
xor(store[i+1], data[i+1], data[i+4]); |
|
xor(store[i+2], data[i+2], data[i+6]); |
|
xor(store[i+0], data[i+0], data[i+3]); |
|
xor(store[i+1], data[i+1], data[i+5]); |
|
xor(store[i+0], data[i+0], data[i+4]); |
|
} |
|
|
|
uint8_t sum = 0; |
|
for(int i = 0; i < NUM; ++i) { |
|
for(int j = 0; j < 4096; ++j) { |
|
sum += store[i][j]; |
|
} |
|
} |
|
|
|
return sum; |
|
} |
|
|
|
int main() { |
|
struct timespec ts, te; |
|
uint8_t *data[NUM]; |
|
uint8_t *store[NUM]; |
|
|
|
const int iter = 1000; |
|
double total_elapsed = 0.0; |
|
uint8_t total_sum = 0; |
|
|
|
for(int i = 0; i < iter; ++i) { |
|
for(int j=0; j<NUM; ++j) { |
|
data[j] = malloc(4096); |
|
store[j] = malloc(4096); |
|
} |
|
for(int j = 0; j < NUM; ++j) { |
|
memcpy(store[j], data[j], 4096); |
|
} |
|
|
|
clock_gettime(CLOCK_MONOTONIC, &ts); |
|
|
|
#ifdef PROGRAM1 |
|
total_sum += program(data, store); |
|
#elif PROGRAM2 |
|
total_sum += program2(data, store); |
|
#else |
|
#error hoge |
|
#endif |
|
|
|
clock_gettime(CLOCK_MONOTONIC, &te); |
|
double elapsed = milliDiff(&ts, &te); |
|
total_elapsed += elapsed; |
|
|
|
for(int j=0; j<NUM; ++j) { |
|
free(data[j]); |
|
free(store[j]); |
|
} |
|
} |
|
|
|
printf("elapsed = %lf\n", total_elapsed); |
|
|
|
return 0; |
|
} |