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