xref: /isa-l_crypto/examples/saturation_test/isal_multithread_perf.c (revision 27316f255a881d386b0b1f395c59599945284be0)
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, MD5_MAX_LANES },
22                       { "md5_mb", md5_mb_func, 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, 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
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
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
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