-
Notifications
You must be signed in to change notification settings - Fork 2
/
memcpy_bench.c
131 lines (110 loc) · 3.71 KB
/
memcpy_bench.c
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
* @author Ammar Faizi <ammarfaizi2@gmail.com> https://www.facebook.com/ammarfaizi2
* @link https://github.com/ammarfaizi2/memcpy_benchmark
*
* Benchmark memcpy.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/time.h>
#include "libs/memcpy_multithread.h"
#define MEM_ALLOC (1024 * 1024 * 128)
#define TEST_COUNT 10
#define START_BENCHMARK(LABEL) do { \
uint32_t i = 0; \
total = min = max = 0; \
chk_##LABEL: \
src = (char *)malloc(MEM_ALLOC); \
dst = (char *)malloc(MEM_ALLOC); \
printf("Initializing source data...\n"); \
fflush(stdout); \
memset(src, 'a', MEM_ALLOC); \
start_time = get_timestamp();
#define END_BENCHMARK(LABEL) \
end_time = get_timestamp(); \
double secs = (end_time - start_time) / 1000000.0L; \
printf("%0.10lf seconds\n", secs); \
printf("Verificating copied data...\n"); \
assert(!memcmp(dst, src, MEM_ALLOC)); \
fflush(stdout); \
total += secs; \
min = i ? (min > secs ? secs : min) : secs; \
max = i ? (max < secs ? secs : max) : secs; \
free(dst); free(src); \
if (i++ < TEST_COUNT) goto chk_##LABEL; \
printf("Max\t: %0.10lf\n", max); \
printf("Min\t: %0.10lf\n", min); \
printf("Avg\t: %0.10lf\n", total / TEST_COUNT); \
printf("Total\t: %0.10lf\n", total); \
} while (0)
void *memcpy_avx256(void *dst, const void *src, size_t len);
void *memcpy_avx512(void *dst, const void *src, size_t len);
void *memcpy_movsb(void *dst, const void *src, size_t len);
typedef unsigned long long timestamp_t;
static void
usage(char *app) {
printf("Usage: %s 1|2|3|4\n", app);
}
static timestamp_t
get_timestamp()
{
struct timeval now;
gettimeofday(&now, NULL);
return now.tv_usec + (timestamp_t)now.tv_sec * 1000000;
}
int
main(int argc, char *argv[])
{
if (argc != 2) {
usage(argv[0]);
return 1;
}
double total, min, max;
char *dst = NULL, *src = NULL;
timestamp_t start_time, end_time;
switch (argv[1][0]) {
case '1':
printf("Benchmarking memcpy...\n");
START_BENCHMARK(memcpy);
memcpy(dst, src, MEM_ALLOC);
END_BENCHMARK(memcpy);
break;
case '2':
printf("Benchmarking memcpy_avx256...\n");
START_BENCHMARK(memcpy_avx256);
memcpy_avx256(dst, src, MEM_ALLOC);
END_BENCHMARK(memcpy_avx256);
break;
case '3':
printf("Benchmarking memcpy_avx512...\n");
START_BENCHMARK(memcpy_avx512);
memcpy_avx512(dst, src, MEM_ALLOC);
END_BENCHMARK(memcpy_avx512);
break;
case '4':
printf("Benchmarking memcpy_movsb...\n");
START_BENCHMARK(memcpy_movsb);
memcpy_movsb(dst, src, MEM_ALLOC);
END_BENCHMARK(memcpy_movsb);
break;
case '5':
memcpy_mt_init(4);
memcpy_mt_set_callback(memcpy_avx256);
printf("Benchmarking memcpy_mt_exec...\n");
START_BENCHMARK(memcpy_mt);
memcpy_mt_exec(dst, src, MEM_ALLOC);
END_BENCHMARK(memcpy_mt);
memcpy_mt_destroy();
break;
default:
usage(argv[0]);
free(dst);
free(src);
return 1;
}
printf("OK!\n");
return 0;
}