1 /**
2 * @file isal_multithread_perf.c
3 * @brief It is used to verify high speed algorithm saturation issue
4 * @details
5 * usage: taskset -c <cpu_index1,cpu_index2,...> isal_multithread_perf -m <algorithm name> -n
6 *<thread num> eg: taskset -c 0-9,20-29 ./isal_multithread_perf -m md5_mb -n 10
7 */
8
9 #include <pthread.h>
10 #include <sys/time.h>
11 #include <sys/types.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <stdbool.h>
15 #include <string.h>
16 #include <unistd.h>
17 #include <stdarg.h>
18
19 #include "isal_multithread_perf.h"
20
21 alg_method algs[] = { { "md5", md5_ossl_func, ISAL_MD5_MAX_LANES },
22 { "md5_mb", md5_mb_func, ISAL_MD5_MAX_LANES },
23 { "sha1", sha1_ossl_func, SHA1_MAX_LANES },
24 { "sha1_mb", sha1_mb_func, SHA1_MAX_LANES },
25 { "sha256", sha256_ossl_func, ISAL_SHA256_MAX_LANES },
26 { "sha256_mb", sha256_mb_func, ISAL_SHA256_MAX_LANES },
27 { "sha512", sha512_ossl_func, ISAL_SHA512_MAX_LANES },
28 { "sha512_mb", sha512_mb_func, SHA512_MAX_LANES },
29 { "cbc_128_dec", cbc_128_dec_func, 1 },
30 { "cbc_192_dec", cbc_192_dec_func, 1 },
31 { "cbc_256_dec", cbc_256_dec_func, 1 },
32 { "xts_128_enc", xts_128_enc_func, 1 },
33 { "xts_256_enc", xts_256_enc_func, 1 },
34 { "gcm_128_enc", gcm_128_enc_func, 1 },
35 { "gcm_256_enc", gcm_256_enc_func, 1 },
36
37 { NULL, NULL } };
38
39 /* Global parameters*/
40 long long run_secs = 10;
41 uint32_t num_threads = 2;
42 uint32_t buflen = 32 * 1024;
43 uint32_t prememcpy = 0;
44 uint32_t postmemcpy = 0;
45 char *method = "md5_mb";
46
47 /* Global thread sync */
48 pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER;
49 pthread_cond_t count_cond = PTHREAD_COND_INITIALIZER;
50 volatile uint32_t count = 0;
51
52 int verbose = 0;
53
54 void
usage(char * appname)55 usage(char *appname)
56 {
57 int i = 0;
58 printf("Usage: %s -n num_threads\n", appname);
59 printf("\t-v verbose output\n"
60 "\t-t time to run(secs)\n"
61 "\t-n number of algorithm threads\n"
62 "\t-l len of each buffer(KB)\n"
63 "\t-a memory copy before algorithm -- 1 do(default); 0 not do\n"
64 "\t-b memory copy after algorithm -- 1 do(default); 0 not do\n"
65 "\t-m method of algorithm:");
66 for (i = 0; algs[i].name != NULL; i++)
67 printf(" %s", algs[i].name);
68 printf("\n");
69 }
70
71 void
notice(char * appname,alg_method * alg_choose_p)72 notice(char *appname, alg_method *alg_choose_p)
73 {
74 int i = 0;
75 printf("%s starts to run\n", appname);
76 printf("\tverbose output is %d\n"
77 "\truntime is %lld(secs)\n"
78 "\tnumber of algorithm threads is %d\n"
79 "\tlen of each buffer(KB) is %d\n"
80 "\tmemory copy before algorithm is %d\n"
81 "\tmemory copy after algorithm is %d\n"
82 "\tmethod of algorithm is %s\n",
83 verbose, run_secs, num_threads, buflen / 1024, prememcpy, postmemcpy,
84 alg_choose_p->name);
85 }
86
87 int
main(int argc,char ** argv)88 main(int argc, char **argv)
89 {
90 int i = 0;
91 int opt;
92 char *optstring = "t:n:m:l:a:b:v";
93 int32_t *id = NULL, ret = 0;
94 alg_method alg_choose;
95 pthread_t *clients = NULL;
96 uint64_t count = 0, sum = 0;
97 uint32_t rounds_buf;
98
99 while ((opt = getopt(argc, argv, optstring)) != -1) {
100 switch (opt) {
101 case 't':
102 run_secs = atol(optarg);
103 if (run_secs <= 0) {
104 usage(argv[0]);
105 exit(-1);
106 }
107 break;
108 case 'n':
109 num_threads = atoi(optarg);
110 if (num_threads <= 0) {
111 usage(argv[0]);
112 exit(-1);
113 }
114 break;
115 case 'm':
116 method = optarg;
117 break;
118 case 'l':
119 buflen = atoi(optarg) * 1024;
120 if (buflen <= 0) {
121 usage(argv[0]);
122 exit(-1);
123 }
124 break;
125 case 'a':
126 prememcpy = atoi(optarg);
127 if (prememcpy != 0 && prememcpy != 1) {
128 usage(argv[0]);
129 exit(-1);
130 }
131 break;
132 case 'b':
133 postmemcpy = atoi(optarg);
134 if (postmemcpy != 0 && postmemcpy != 1) {
135 usage(argv[0]);
136 exit(-1);
137 }
138 break;
139 case 'v':
140 verbose = 1;
141 break;
142 default:
143 usage(argv[0]);
144 exit(0);
145 }
146 }
147
148 /* Check method str and set algorithm_func */
149 for (i = 0; algs[i].name != NULL; i++) {
150 if (!strcmp(method, algs[i].name)) {
151 alg_choose = algs[i];
152 break;
153 }
154 }
155 if (algs[i].name == NULL) {
156 usage(argv[0]);
157 exit(-1);
158 }
159
160 notice(argv[0], &alg_choose);
161 rounds_buf = alg_choose.rounds_nbuf;
162
163 clients = (pthread_t *) calloc(num_threads + 1, sizeof(pthread_t));
164 id = (int32_t *) calloc(num_threads + 1, sizeof(int32_t));
165
166 printf("Start %i threads, use %s function\n", num_threads, alg_choose.name);
167
168 for (i = 0; i < num_threads; i++) {
169 id[i] = i;
170
171 ret = pthread_create(&clients[i], NULL, alg_choose.thread_func, (void *) &id[i]);
172
173 if (ret != 0) {
174 printf("Failed to create thread %i: %s", i, strerror(ret));
175 exit(-1);
176 }
177 printfv("Thread %i is created\n", i);
178 }
179
180 for (i = 0; i < num_threads; i++) {
181 pthread_join(clients[i], (void *) &count);
182 sum += count;
183 }
184 double loop_unit = ((double) buflen) * rounds_buf / run_secs / 1024 / 1024;
185 printf("Sum of rounds is %ld\n"
186 "Average throughput(MB/s) is %.2f\n"
187 "Total throughput(MB/s) is %.2f\n",
188 sum, (double) sum / i * loop_unit, (double) sum * loop_unit);
189
190 exit(0);
191 }
192