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