API Reference Manual 1.51.0
Loading...
Searching...
No Matches
odp_bench_misc.c
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (c) 2022-2025 Nokia
3 */
4
13#ifndef _GNU_SOURCE
14#define _GNU_SOURCE /* Needed for sigaction */
15#endif
16
17#include <odp_api.h>
18#include <odp/helper/odph_api.h>
19
20#include <bench_common.h>
21#include <export_results.h>
22
23#include <getopt.h>
24#include <inttypes.h>
25#include <signal.h>
26#include <stdlib.h>
27#include <unistd.h>
28
29/* Number of API function calls per test case */
30#define REPEAT_COUNT 1024
31
32/* Default number of rounds per test case */
33#define ROUNDS 1000u
34
35/* Maximum number of results to be held */
36#define TEST_MAX_BENCH 70
37
38#define BENCH_INFO(run_fn, init_fn, max, alt_name) \
39 {.name = #run_fn, .run = run_fn, .init = init_fn, .max_rounds = max, .desc = alt_name}
40
41typedef struct {
42 /* Measure time vs CPU cycles */
43 int time;
44
45 /* Benchmark index to run indefinitely */
46 int bench_idx;
47
48 /* Rounds per test case */
49 uint32_t rounds;
50
51} appl_args_t;
52
53/* Global data */
54typedef struct {
55 appl_args_t appl;
56
57 /* Common benchmark suite data */
58 bench_suite_t suite;
59
60 /* Time stamp 1 */
61 odp_time_t t1[REPEAT_COUNT];
62 /* Time stamp 2 */
63 odp_time_t t2[REPEAT_COUNT];
64 /* Resulting time stamp */
65 odp_time_t t3[REPEAT_COUNT];
66
67 odp_time_t global_short[REPEAT_COUNT];
68 odp_time_t global_long[REPEAT_COUNT];
69
70 /* Integer input / output data */
71 uint64_t a1[REPEAT_COUNT];
72 uint64_t a2[REPEAT_COUNT];
73 uint32_t b1[REPEAT_COUNT];
74 uint32_t b2[REPEAT_COUNT];
75 uint16_t c1[REPEAT_COUNT];
76 uint16_t c2[REPEAT_COUNT];
77
78 /* CPU mask as string */
79 char cpumask_str[ODP_CPUMASK_STR_SIZE];
80
81 /* Array for storing results */
82 double result[TEST_MAX_BENCH];
83
84} gbl_args_t;
85
86static gbl_args_t *gbl_args;
87
88static void sig_handler(int signo ODP_UNUSED)
89{
90 if (gbl_args == NULL)
91 return;
92 odp_atomic_store_u32(&gbl_args->suite.exit_worker, 1);
93}
94
95static int setup_sig_handler(void)
96{
97 struct sigaction action;
98
99 memset(&action, 0, sizeof(action));
100 action.sa_handler = sig_handler;
101
102 /* No additional signals blocked. By default, the signal which triggered
103 * the handler is blocked. */
104 if (sigemptyset(&action.sa_mask))
105 return -1;
106
107 if (sigaction(SIGINT, &action, NULL))
108 return -1;
109
110 return 0;
111}
112
113static void init_time_global(void)
114{
115 int i;
116 odp_time_t *t1 = gbl_args->t1;
117 odp_time_t *t2 = gbl_args->t2;
118 uint64_t *a1 = gbl_args->a1;
119
120 for (i = 0; i < REPEAT_COUNT; i++)
121 t1[i] = odp_time_global();
122
123 for (i = 0; i < REPEAT_COUNT; i++)
124 t2[i] = odp_time_global();
125
126 for (i = 0; i < REPEAT_COUNT; i++)
127 a1[i] = odp_time_global_ns();
128}
129
130static void init_time_local(void)
131{
132 int i;
133 odp_time_t *t1 = gbl_args->t1;
134 odp_time_t *t2 = gbl_args->t2;
135 uint64_t *a1 = gbl_args->a1;
136
137 for (i = 0; i < REPEAT_COUNT; i++)
138 t1[i] = odp_time_local();
139
140 for (i = 0; i < REPEAT_COUNT; i++)
141 t2[i] = odp_time_local();
142
143 for (i = 0; i < REPEAT_COUNT; i++)
144 a1[i] = odp_time_local_ns();
145}
146
147static void init_cpu_cycles(void)
148{
149 int i;
150 uint64_t *a1 = gbl_args->a1;
151 uint64_t *a2 = gbl_args->a2;
152
153 for (i = 0; i < REPEAT_COUNT; i++)
154 a1[i] = odp_cpu_cycles();
155
156 for (i = 0; i < REPEAT_COUNT; i++)
157 a2[i] = odp_cpu_cycles();
158}
159
160static int time_local(void)
161{
162 int i;
163 odp_time_t *t1 = gbl_args->t1;
164
165 for (i = 0; i < REPEAT_COUNT; i++)
166 t1[i] = odp_time_local();
167
168 return i;
169}
170
171static int time_local_strict(void)
172{
173 int i;
174 odp_time_t *t1 = gbl_args->t1;
175
176 for (i = 0; i < REPEAT_COUNT; i++)
177 t1[i] = odp_time_local_strict();
178
179 return i;
180}
181
182static int time_local_ns(void)
183{
184 int i;
185 uint64_t *a1 = gbl_args->a1;
186
187 for (i = 0; i < REPEAT_COUNT; i++)
188 a1[i] = odp_time_local_ns();
189
190 return i;
191}
192
193static int time_local_strict_ns(void)
194{
195 int i;
196 uint64_t *a1 = gbl_args->a1;
197
198 for (i = 0; i < REPEAT_COUNT; i++)
199 a1[i] = odp_time_local_strict_ns();
200
201 return i;
202}
203
204static int time_global(void)
205{
206 int i;
207 odp_time_t *t1 = gbl_args->t1;
208
209 for (i = 0; i < REPEAT_COUNT; i++)
210 t1[i] = odp_time_global();
211
212 return i;
213}
214
215static int time_global_strict(void)
216{
217 int i;
218 odp_time_t *t1 = gbl_args->t1;
219
220 for (i = 0; i < REPEAT_COUNT; i++)
221 t1[i] = odp_time_global_strict();
222
223 return i;
224}
225
226static int time_global_ns(void)
227{
228 int i;
229 uint64_t *a1 = gbl_args->a1;
230
231 for (i = 0; i < REPEAT_COUNT; i++)
232 a1[i] = odp_time_global_ns();
233
234 return i;
235}
236
237static int time_global_strict_ns(void)
238{
239 int i;
240 uint64_t *a1 = gbl_args->a1;
241
242 for (i = 0; i < REPEAT_COUNT; i++)
244
245 return i;
246}
247
248static int time_diff(void)
249{
250 int i;
251 odp_time_t *t1 = gbl_args->t1;
252 odp_time_t *t2 = gbl_args->t2;
253 odp_time_t *t3 = gbl_args->t3;
254
255 for (i = 0; i < REPEAT_COUNT; i++)
256 t3[i] = odp_time_diff(t2[i], t1[i]);
257
258 return i;
259}
260
261static int time_diff_ns(void)
262{
263 int i;
264 odp_time_t *t1 = gbl_args->t1;
265 odp_time_t *t2 = gbl_args->t2;
266 uint64_t res = 0;
267
268 for (i = 0; i < REPEAT_COUNT; i++)
269 res += odp_time_diff_ns(t2[i], t1[i]);
270
271 gbl_args->suite.dummy += res;
272
273 return i;
274}
275
276static int time_add_ns(void)
277{
278 int i;
279 odp_time_t *t1 = gbl_args->t1;
280 odp_time_t *t3 = gbl_args->t3;
281 uint64_t *a1 = gbl_args->a1;
282
283 for (i = 0; i < REPEAT_COUNT; i++)
284 t3[i] = odp_time_add_ns(t1[i], a1[i]);
285
286 return i;
287}
288
289static int time_sum(void)
290{
291 int i;
292 odp_time_t *t1 = gbl_args->t1;
293 odp_time_t *t2 = gbl_args->t2;
294 odp_time_t *t3 = gbl_args->t3;
295
296 for (i = 0; i < REPEAT_COUNT; i++)
297 t3[i] = odp_time_sum(t1[i], t2[i]);
298
299 return i;
300}
301
302static int time_to_ns_short(void)
303{
304 int i;
305 odp_time_t *t = gbl_args->global_short;
306 uint64_t res = 0;
307
308 for (i = 0; i < REPEAT_COUNT; i++)
309 res += odp_time_to_ns(t[i]);
310
311 gbl_args->suite.dummy += res;
312
313 return i;
314}
315
316static int time_to_ns_long(void)
317{
318 int i;
319 odp_time_t *t = gbl_args->global_long;
320 uint64_t res = 0;
321
322 for (i = 0; i < REPEAT_COUNT; i++)
323 res += odp_time_to_ns(t[i]);
324
325 gbl_args->suite.dummy += res;
326
327 return i;
328}
329
330static int time_local_from_ns(void)
331{
332 int i;
333 odp_time_t *t1 = gbl_args->t1;
334 uint64_t *a1 = gbl_args->a1;
335
336 for (i = 0; i < REPEAT_COUNT; i++)
337 t1[i] = odp_time_local_from_ns(a1[i]);
338
339 return i;
340}
341
342static int time_global_from_ns(void)
343{
344 int i;
345 odp_time_t *t1 = gbl_args->t1;
346 uint64_t *a1 = gbl_args->a1;
347
348 for (i = 0; i < REPEAT_COUNT; i++)
349 t1[i] = odp_time_global_from_ns(a1[i]);
350
351 return i;
352}
353
354static int time_cmp(void)
355{
356 int i;
357 odp_time_t *t1 = gbl_args->t1;
358 odp_time_t *t2 = gbl_args->t2;
359 int res = 0;
360
361 for (i = 0; i < REPEAT_COUNT; i++)
362 res += odp_time_cmp(t1[i], t2[i]);
363
364 gbl_args->suite.dummy += res;
365
366 return i;
367}
368
369static int time_local_res(void)
370{
371 int i;
372 uint64_t *a1 = gbl_args->a1;
373
374 for (i = 0; i < REPEAT_COUNT; i++)
375 a1[i] = odp_time_local_res();
376
377 return i;
378}
379
380static int time_global_res(void)
381{
382 int i;
383 uint64_t *a1 = gbl_args->a1;
384
385 for (i = 0; i < REPEAT_COUNT; i++)
386 a1[i] = odp_time_global_res();
387
388 return i;
389}
390
391static int time_startup(void)
392{
393 int i;
394 uint64_t *a1 = gbl_args->a1;
395 odp_time_startup_t startup;
396
397 for (i = 0; i < REPEAT_COUNT; i++) {
398 odp_time_startup(&startup);
399 a1[i] = startup.global_ns;
400 }
401
402 return i;
403}
404
405static int cpu_id(void)
406{
407 int i;
408 uint64_t *a1 = gbl_args->a1;
409
410 for (i = 0; i < REPEAT_COUNT; i++)
411 a1[i] = odp_cpu_id();
412
413 return i;
414}
415
416static int cpu_count(void)
417{
418 int i;
419 uint64_t *a1 = gbl_args->a1;
420
421 for (i = 0; i < REPEAT_COUNT; i++)
422 a1[i] = odp_cpu_count();
423
424 return i;
425}
426
427static int cpu_hz(void)
428{
429 int i;
430 uint64_t *a1 = gbl_args->a1;
431
432 for (i = 0; i < REPEAT_COUNT; i++)
433 a1[i] = odp_cpu_hz();
434
435 return i;
436}
437
438static int cpu_hz_id(void)
439{
440 int i;
441 const int id = odp_cpu_id();
442 uint64_t *a1 = gbl_args->a1;
443
444 for (i = 0; i < REPEAT_COUNT; i++)
445 a1[i] = odp_cpu_hz_id(id);
446
447 return i;
448}
449
450static int cpu_hz_max(void)
451{
452 int i;
453 uint64_t *a1 = gbl_args->a1;
454
455 for (i = 0; i < REPEAT_COUNT; i++)
456 a1[i] = odp_cpu_hz_max();
457
458 return i;
459}
460
461static int cpu_hz_max_id(void)
462{
463 int i;
464 const int id = odp_cpu_id();
465 uint64_t *a1 = gbl_args->a1;
466
467 for (i = 0; i < REPEAT_COUNT; i++)
468 a1[i] = odp_cpu_hz_max_id(id);
469
470 return i;
471}
472
473static int cpu_cycles(void)
474{
475 int i;
476 uint64_t *a1 = gbl_args->a1;
477
478 for (i = 0; i < REPEAT_COUNT; i++)
479 a1[i] = odp_cpu_cycles();
480
481 return i;
482}
483
484static int cpu_cycles_diff(void)
485{
486 int i;
487 uint64_t *a1 = gbl_args->a1;
488 uint64_t *a2 = gbl_args->a2;
489 uint64_t res = 0;
490
491 for (i = 0; i < REPEAT_COUNT; i++)
492 res += odp_cpu_cycles_diff(a2[i], a1[i]);
493
494 gbl_args->suite.dummy += res;
495
496 return i;
497}
498
499static int cpu_cycles_max(void)
500{
501 int i;
502 uint64_t *a1 = gbl_args->a1;
503
504 for (i = 0; i < REPEAT_COUNT; i++)
505 a1[i] = odp_cpu_cycles_max();
506
507 return i;
508}
509
510static int cpu_cycles_resolution(void)
511{
512 int i;
513 uint64_t *a1 = gbl_args->a1;
514
515 for (i = 0; i < REPEAT_COUNT; i++)
517
518 return i;
519}
520
521static int cpu_pause(void)
522{
523 int i;
524
525 for (i = 0; i < REPEAT_COUNT; i++)
527
528 return i;
529}
530
531static int thread_id(void)
532{
533 int i;
534 uint64_t *a1 = gbl_args->a1;
535
536 for (i = 0; i < REPEAT_COUNT; i++)
537 a1[i] = odp_thread_id();
538
539 return i;
540}
541
542static int thread_count(void)
543{
544 int i;
545 uint64_t *a1 = gbl_args->a1;
546
547 for (i = 0; i < REPEAT_COUNT; i++)
548 a1[i] = odp_thread_count();
549
550 return i;
551}
552
553static int thread_count_max(void)
554{
555 int i;
556 uint64_t *a1 = gbl_args->a1;
557
558 for (i = 0; i < REPEAT_COUNT; i++)
559 a1[i] = odp_thread_count_max();
560
561 return i;
562}
563
564static int thread_type(void)
565{
566 int i;
567 uint64_t *a1 = gbl_args->a1;
568
569 for (i = 0; i < REPEAT_COUNT; i++)
570 a1[i] = (int)odp_thread_type();
571
572 return i;
573}
574
575static int be_to_cpu_64(void)
576{
577 int i;
578 uint64_t *a1 = gbl_args->a1;
579 uint64_t *a2 = gbl_args->a2;
580
581 for (i = 0; i < REPEAT_COUNT; i++)
582 a2[i] = odp_be_to_cpu_64(a1[i]);
583
584 return i;
585}
586
587static int be_to_cpu_32(void)
588{
589 int i;
590 uint32_t *b1 = gbl_args->b1;
591 uint32_t *b2 = gbl_args->b2;
592
593 for (i = 0; i < REPEAT_COUNT; i++)
594 b2[i] = odp_be_to_cpu_32(b1[i]);
595
596 return i;
597}
598
599static int be_to_cpu_16(void)
600{
601 int i;
602 uint16_t *c1 = gbl_args->c1;
603 uint16_t *c2 = gbl_args->c2;
604
605 for (i = 0; i < REPEAT_COUNT; i++)
606 c2[i] = odp_be_to_cpu_16(c1[i]);
607
608 return i;
609}
610
611static int cpu_to_be_64(void)
612{
613 int i;
614 uint64_t *a1 = gbl_args->a1;
615 uint64_t *a2 = gbl_args->a2;
616
617 for (i = 0; i < REPEAT_COUNT; i++)
618 a2[i] = odp_cpu_to_be_64(a1[i]);
619
620 return i;
621}
622
623static int cpu_to_be_32(void)
624{
625 int i;
626 uint32_t *b1 = gbl_args->b1;
627 uint32_t *b2 = gbl_args->b2;
628
629 for (i = 0; i < REPEAT_COUNT; i++)
630 b2[i] = odp_cpu_to_be_32(b1[i]);
631
632 return i;
633}
634
635static int cpu_to_be_16(void)
636{
637 int i;
638 uint16_t *c1 = gbl_args->c1;
639 uint16_t *c2 = gbl_args->c2;
640
641 for (i = 0; i < REPEAT_COUNT; i++)
642 c2[i] = odp_cpu_to_be_16(c1[i]);
643
644 return i;
645}
646
647static int le_to_cpu_64(void)
648{
649 int i;
650 uint64_t *a1 = gbl_args->a1;
651 uint64_t *a2 = gbl_args->a2;
652
653 for (i = 0; i < REPEAT_COUNT; i++)
654 a2[i] = odp_le_to_cpu_64(a1[i]);
655
656 return i;
657}
658
659static int le_to_cpu_32(void)
660{
661 int i;
662 uint32_t *b1 = gbl_args->b1;
663 uint32_t *b2 = gbl_args->b2;
664
665 for (i = 0; i < REPEAT_COUNT; i++)
666 b2[i] = odp_le_to_cpu_32(b1[i]);
667
668 return i;
669}
670
671static int le_to_cpu_16(void)
672{
673 int i;
674 uint16_t *c1 = gbl_args->c1;
675 uint16_t *c2 = gbl_args->c2;
676
677 for (i = 0; i < REPEAT_COUNT; i++)
678 c2[i] = odp_le_to_cpu_16(c1[i]);
679
680 return i;
681}
682
683static int cpu_to_le_64(void)
684{
685 int i;
686 uint64_t *a1 = gbl_args->a1;
687 uint64_t *a2 = gbl_args->a2;
688
689 for (i = 0; i < REPEAT_COUNT; i++)
690 a2[i] = odp_cpu_to_le_64(a1[i]);
691
692 return i;
693}
694
695static int cpu_to_le_32(void)
696{
697 int i;
698 uint32_t *b1 = gbl_args->b1;
699 uint32_t *b2 = gbl_args->b2;
700
701 for (i = 0; i < REPEAT_COUNT; i++)
702 b2[i] = odp_cpu_to_le_32(b1[i]);
703
704 return i;
705}
706
707static int cpu_to_le_16(void)
708{
709 int i;
710 uint16_t *c1 = gbl_args->c1;
711 uint16_t *c2 = gbl_args->c2;
712
713 for (i = 0; i < REPEAT_COUNT; i++)
714 c2[i] = odp_cpu_to_le_16(c1[i]);
715
716 return i;
717}
718
719static int mb_release(void)
720{
721 int i;
722
723 for (i = 0; i < REPEAT_COUNT; i++)
725
726 return i;
727}
728
729static int mb_acquire(void)
730{
731 int i;
732
733 for (i = 0; i < REPEAT_COUNT; i++)
735
736 return i;
737}
738
739static int mb_full(void)
740{
741 int i;
742
743 for (i = 0; i < REPEAT_COUNT; i++)
744 odp_mb_full();
745
746 return i;
747}
748
749typedef void (*prefetch_fn_t)(const void *addr);
750
751static int run_prefetch(prefetch_fn_t fn)
752{
753 uint64_t *a1 = gbl_args->a1;
754 uint32_t index = 0;
755 int i;
756
757 for (i = 0; i < REPEAT_COUNT; i++) {
758 fn(&a1[index]);
759
760 /* Prefetch every 64B */
761 index += 8;
762 if (odp_unlikely(index >= REPEAT_COUNT))
763 index = 0;
764 }
765
766 return i;
767}
768
769static int prefetch(void) { return run_prefetch(odp_prefetch); }
770static int prefetch_l1(void) { return run_prefetch(odp_prefetch_l1); }
771static int prefetch_l2(void) { return run_prefetch(odp_prefetch_l2); }
772static int prefetch_l3(void) { return run_prefetch(odp_prefetch_l3); }
773static int prefetch_strm_l1(void) { return run_prefetch(odp_prefetch_strm_l1); }
774static int prefetch_l1i(void) { return run_prefetch(odp_prefetch_l1i); }
775
776static int prefetch_store(void) { return run_prefetch(odp_prefetch_store); }
777static int prefetch_store_l1(void) { return run_prefetch(odp_prefetch_store_l1); }
778static int prefetch_store_l2(void) { return run_prefetch(odp_prefetch_store_l2); }
779static int prefetch_store_l3(void) { return run_prefetch(odp_prefetch_store_l3); }
780static int prefetch_store_strm_l1(void){ return run_prefetch(odp_prefetch_store_strm_l1); }
781
782static int bench_misc_export(void *data)
783{
784 gbl_args_t *gbl_args = data;
785 int ret = 0;
786
787 if (test_common_write("%s", gbl_args->appl.time ?
788 "function name,average nsec per function call\n" :
789 "function name,average cpu cycles per function call\n")) {
790 ret = -1;
791 goto exit;
792 }
793
794 for (int i = 0; i < gbl_args->suite.num_bench; i++) {
795 if (test_common_write("odp_%s,%f\n", gbl_args->suite.bench[i].desc != NULL ?
796 gbl_args->suite.bench[i].desc : gbl_args->suite.bench[i].name,
797 gbl_args->suite.result[i])) {
798 ret = -1;
799 goto exit;
800 }
801 }
802
803exit:
804 test_common_write_term();
805
806 return ret;
807}
808
809bench_info_t test_suite[] = {
810 BENCH_INFO(time_local, NULL, 0, NULL),
811 BENCH_INFO(time_local_strict, NULL, 0, NULL),
812 BENCH_INFO(time_local_ns, NULL, 0, NULL),
813 BENCH_INFO(time_local_strict_ns, NULL, 0, NULL),
814 BENCH_INFO(time_global, NULL, 0, NULL),
815 BENCH_INFO(time_global_strict, NULL, 0, NULL),
816 BENCH_INFO(time_global_ns, NULL, 0, NULL),
817 BENCH_INFO(time_global_strict_ns, NULL, 0, NULL),
818 BENCH_INFO(time_diff, init_time_global, 0, "time_diff (global)"),
819 BENCH_INFO(time_diff, init_time_local, 0, "time_diff (local)"),
820 BENCH_INFO(time_diff_ns, init_time_global, 0, NULL),
821 BENCH_INFO(time_add_ns, init_time_global, 0, NULL),
822 BENCH_INFO(time_sum, init_time_global, 0, NULL),
823 BENCH_INFO(time_to_ns_short, NULL, 0, "time_to_ns (short)"),
824 BENCH_INFO(time_to_ns_long, NULL, 0, "time_to_ns (long)"),
825 BENCH_INFO(time_local_from_ns, init_time_global, 0, NULL),
826 BENCH_INFO(time_global_from_ns, init_time_global, 0, NULL),
827 BENCH_INFO(time_cmp, init_time_global, 0, NULL),
828 BENCH_INFO(time_local_res, NULL, 0, NULL),
829 BENCH_INFO(time_global_res, NULL, 0, NULL),
830 BENCH_INFO(time_startup, NULL, 0, NULL),
831 BENCH_INFO(cpu_id, NULL, 0, NULL),
832 BENCH_INFO(cpu_count, NULL, 0, NULL),
833 BENCH_INFO(cpu_hz, NULL, 1, NULL),
834 BENCH_INFO(cpu_hz_id, NULL, 1, NULL),
835 BENCH_INFO(cpu_hz_max, NULL, 0, NULL),
836 BENCH_INFO(cpu_hz_max_id, NULL, 0, NULL),
837 BENCH_INFO(cpu_cycles, NULL, 0, NULL),
838 BENCH_INFO(cpu_cycles_diff, init_cpu_cycles, 0, NULL),
839 BENCH_INFO(cpu_cycles_max, NULL, 0, NULL),
840 BENCH_INFO(cpu_cycles_resolution, NULL, 0, NULL),
841 BENCH_INFO(cpu_pause, NULL, 0, NULL),
842 BENCH_INFO(thread_id, NULL, 0, NULL),
843 BENCH_INFO(thread_count, NULL, 0, NULL),
844 BENCH_INFO(thread_count_max, NULL, 0, NULL),
845 BENCH_INFO(thread_type, NULL, 0, NULL),
846 BENCH_INFO(be_to_cpu_64, NULL, 0, NULL),
847 BENCH_INFO(be_to_cpu_32, NULL, 0, NULL),
848 BENCH_INFO(be_to_cpu_16, NULL, 0, NULL),
849 BENCH_INFO(cpu_to_be_64, NULL, 0, NULL),
850 BENCH_INFO(cpu_to_be_32, NULL, 0, NULL),
851 BENCH_INFO(cpu_to_be_16, NULL, 0, NULL),
852 BENCH_INFO(le_to_cpu_64, NULL, 0, NULL),
853 BENCH_INFO(le_to_cpu_32, NULL, 0, NULL),
854 BENCH_INFO(le_to_cpu_16, NULL, 0, NULL),
855 BENCH_INFO(cpu_to_le_64, NULL, 0, NULL),
856 BENCH_INFO(cpu_to_le_32, NULL, 0, NULL),
857 BENCH_INFO(cpu_to_le_16, NULL, 0, NULL),
858 BENCH_INFO(mb_release, NULL, 0, NULL),
859 BENCH_INFO(mb_acquire, NULL, 0, NULL),
860 BENCH_INFO(mb_full, NULL, 0, NULL),
861 BENCH_INFO(prefetch, NULL, 0, NULL),
862 BENCH_INFO(prefetch_l1, NULL, 0, NULL),
863 BENCH_INFO(prefetch_l2, NULL, 0, NULL),
864 BENCH_INFO(prefetch_l3, NULL, 0, NULL),
865 BENCH_INFO(prefetch_strm_l1, NULL, 0, NULL),
866 BENCH_INFO(prefetch_l1i, NULL, 0, NULL),
867 BENCH_INFO(prefetch_store, NULL, 0, NULL),
868 BENCH_INFO(prefetch_store_l1, NULL, 0, NULL),
869 BENCH_INFO(prefetch_store_l2, NULL, 0, NULL),
870 BENCH_INFO(prefetch_store_l3, NULL, 0, NULL),
871 BENCH_INFO(prefetch_store_strm_l1, NULL, 0, NULL),
872};
873
874ODP_STATIC_ASSERT(ODPH_ARRAY_SIZE(test_suite) < TEST_MAX_BENCH,
875 "Result array is too small to hold all the results");
876
877/* Print usage information */
878static void usage(void)
879{
880 printf("\n"
881 "ODP miscellaneous API micro benchmarks\n"
882 "\n"
883 "Options:\n"
884 " -t, --time <opt> Time measurement. 0: measure CPU cycles (default), 1: measure time\n"
885 " -i, --index <idx> Benchmark index to run indefinitely.\n"
886 " -r, --rounds <num> Run each test case 'num' times (default %u).\n"
887 " -h, --help Display help and exit.\n\n"
888 "\n", ROUNDS);
889}
890
891/* Parse command line arguments */
892static int parse_args(int argc, char *argv[])
893{
894 int opt;
895 appl_args_t *appl_args = &gbl_args->appl;
896 static const struct option longopts[] = {
897 {"time", required_argument, NULL, 't'},
898 {"index", required_argument, NULL, 'i'},
899 {"rounds", required_argument, NULL, 'r'},
900 {"help", no_argument, NULL, 'h'},
901 {NULL, 0, NULL, 0}
902 };
903
904 static const char *shortopts = "t:i:r:h";
905
906 appl_args->time = 0; /* Measure CPU cycles */
907 appl_args->bench_idx = 0; /* Run all benchmarks */
908 appl_args->rounds = ROUNDS;
909
910 while (1) {
911 opt = getopt_long(argc, argv, shortopts, longopts, NULL);
912
913 if (opt == -1)
914 break; /* No more options */
915
916 switch (opt) {
917 case 't':
918 appl_args->time = atoi(optarg);
919 break;
920 case 'i':
921 appl_args->bench_idx = atoi(optarg);
922 break;
923 case 'r':
924 appl_args->rounds = atoi(optarg);
925 break;
926 case 'h':
927 usage();
928 return 1;
929 default:
930 ODPH_ERR("Bad option. Use -h for help.\n");
931 return -1;
932 }
933 }
934
935 if (appl_args->rounds < 1) {
936 ODPH_ERR("Invalid test cycle repeat count: %u\n", appl_args->rounds);
937 return -1;
938 }
939
940 if (appl_args->bench_idx < 0 || appl_args->bench_idx > (int)ODPH_ARRAY_SIZE(test_suite)) {
941 ODPH_ERR("Bad bench index %i\n", appl_args->bench_idx);
942 return -1;
943 }
944
945 optind = 1; /* Reset 'extern optind' from the getopt lib */
946
947 return 0;
948}
949
950/* Print system and application info */
951static void print_info(void)
952{
954
955 printf("\n"
956 "odp_bench_misc options\n"
957 "----------------------\n");
958
959 printf("CPU mask: %s\n", gbl_args->cpumask_str);
960 printf("Measurement unit: %s\n", gbl_args->appl.time ? "nsec" : "CPU cycles");
961 printf("Test rounds: %u\n", gbl_args->appl.rounds);
962 printf("\n");
963}
964
965int main(int argc, char *argv[])
966{
967 odph_helper_options_t helper_options;
968 test_common_options_t common_options;
969 odph_thread_t worker_thread;
970 odph_thread_common_param_t thr_common;
971 odph_thread_param_t thr_param;
972 int cpu, i;
973 odp_shm_t shm;
974 odp_cpumask_t cpumask, default_mask;
975 odp_instance_t instance;
976 odp_init_t init_param;
977 int ret = 0;
978
979 /* Let helper collect its own arguments (e.g. --odph_proc) */
980 argc = odph_parse_options(argc, argv);
981 if (odph_options(&helper_options)) {
982 ODPH_ERR("Reading ODP helper options failed\n");
983 exit(EXIT_FAILURE);
984 }
985
986 argc = test_common_parse_options(argc, argv);
987 if (test_common_options(&common_options)) {
988 ODPH_ERR("Reading test options failed\n");
989 exit(EXIT_FAILURE);
990 }
991
992 odp_init_param_init(&init_param);
993 init_param.mem_model = helper_options.mem_model;
994
995 /* Init ODP before calling anything else */
996 if (odp_init_global(&instance, &init_param, NULL)) {
997 ODPH_ERR("Global init failed\n");
998 exit(EXIT_FAILURE);
999 }
1000
1001 /* Init this thread */
1002 if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
1003 ODPH_ERR("Local init failed\n");
1004 exit(EXIT_FAILURE);
1005 }
1006
1007 if (setup_sig_handler()) {
1008 ODPH_ERR("Signal handler setup failed\n");
1009 exit(EXIT_FAILURE);
1010 }
1011
1012 /* Reserve memory for args from shared mem */
1013 shm = odp_shm_reserve("shm_args", sizeof(gbl_args_t), ODP_CACHE_LINE_SIZE, 0);
1014 if (shm == ODP_SHM_INVALID) {
1015 ODPH_ERR("Shared mem reserve failed\n");
1016 exit(EXIT_FAILURE);
1017 }
1018
1019 gbl_args = odp_shm_addr(shm);
1020 if (gbl_args == NULL) {
1021 ODPH_ERR("Shared mem alloc failed\n");
1022 exit(EXIT_FAILURE);
1023 }
1024
1025 memset(gbl_args, 0, sizeof(gbl_args_t));
1026
1027 for (i = 0; i < REPEAT_COUNT; i++) {
1028 gbl_args->t1[i] = ODP_TIME_NULL;
1029 gbl_args->t2[i] = ODP_TIME_NULL;
1030 gbl_args->t3[i] = ODP_TIME_NULL;
1031 gbl_args->global_short[i] = odp_time_global_from_ns(ODP_TIME_MSEC_IN_NS);
1032 gbl_args->global_long[i] = odp_time_global_from_ns(10 * ODP_TIME_SEC_IN_NS);
1033 gbl_args->a1[i] = i;
1034 gbl_args->a2[i] = i;
1035 gbl_args->b1[i] = i;
1036 gbl_args->b2[i] = i;
1037 gbl_args->c1[i] = i;
1038 gbl_args->c2[i] = i;
1039 }
1040
1041 /* Parse and store the application arguments */
1042 ret = parse_args(argc, argv);
1043 if (ret)
1044 goto exit;
1045
1046 bench_suite_init(&gbl_args->suite);
1047 gbl_args->suite.bench = test_suite;
1048 gbl_args->suite.num_bench = ODPH_ARRAY_SIZE(test_suite);
1049 gbl_args->suite.measure_time = !!gbl_args->appl.time;
1050 gbl_args->suite.indef_idx = gbl_args->appl.bench_idx;
1051 gbl_args->suite.rounds = gbl_args->appl.rounds;
1052 gbl_args->suite.repeat_count = REPEAT_COUNT;
1053 if (common_options.is_export)
1054 gbl_args->suite.result = gbl_args->result;
1055
1056 /* Get default worker cpumask */
1057 if (odp_cpumask_default_worker(&default_mask, 1) != 1) {
1058 ODPH_ERR("Unable to allocate worker thread\n");
1059 ret = -1;
1060 goto exit;
1061 }
1062
1063 (void)odp_cpumask_to_str(&default_mask, gbl_args->cpumask_str,
1064 sizeof(gbl_args->cpumask_str));
1065
1066 print_info();
1067
1068 memset(&worker_thread, 0, sizeof(odph_thread_t));
1069
1070 /* Create worker thread */
1071 cpu = odp_cpumask_first(&default_mask);
1072
1073 odp_cpumask_zero(&cpumask);
1074 odp_cpumask_set(&cpumask, cpu);
1075
1076 odph_thread_common_param_init(&thr_common);
1077 thr_common.instance = instance;
1078 thr_common.cpumask = &cpumask;
1079 thr_common.share_param = 1;
1080
1081 odph_thread_param_init(&thr_param);
1082 thr_param.start = bench_run;
1083 thr_param.arg = &gbl_args->suite;
1084 thr_param.thr_type = ODP_THREAD_WORKER;
1085
1086 odph_thread_create(&worker_thread, &thr_common, &thr_param, 1);
1087
1088 odph_thread_join(&worker_thread, 1);
1089
1090 ret = gbl_args->suite.retval;
1091
1092 if (ret == 0 && common_options.is_export) {
1093 if (bench_misc_export(gbl_args)) {
1094 ODPH_ERR("Error: Export failed\n");
1095 ret = -1;
1096 }
1097 }
1098
1099exit:
1100 if (odp_shm_free(shm)) {
1101 ODPH_ERR("Shared mem free failed\n");
1102 exit(EXIT_FAILURE);
1103 }
1104
1105 if (odp_term_local()) {
1106 ODPH_ERR("Local term failed\n");
1107 exit(EXIT_FAILURE);
1108 }
1109
1110 if (odp_term_global(instance)) {
1111 ODPH_ERR("Global term failed\n");
1112 exit(EXIT_FAILURE);
1113 }
1114
1115 if (ret < 0)
1116 return EXIT_FAILURE;
1117
1118 return EXIT_SUCCESS;
1119}
void odp_atomic_store_u32(odp_atomic_u32_t *atom, uint32_t val)
Store value to atomic uint32 variable.
void odp_mb_full(void)
Full memory barrier.
void odp_mb_acquire(void)
Memory barrier for acquire operations.
void odp_mb_release(void)
Memory barrier for release operations.
odp_u64le_t odp_cpu_to_le_64(uint64_t cpu64)
Convert cpu native uint64_t to 64bit little endian.
#define odp_unlikely(x)
Branch unlikely taken.
Definition spec/hints.h:64
odp_u16le_t odp_cpu_to_le_16(uint16_t cpu16)
Convert cpu native uint16_t to 16bit little endian.
odp_u16be_t odp_cpu_to_be_16(uint16_t cpu16)
Convert cpu native uint16_t to 16bit big endian.
odp_u64be_t odp_cpu_to_be_64(uint64_t cpu64)
Convert cpu native uint64_t to 64bit big endian.
#define ODP_UNUSED
Intentionally unused variables of functions.
Definition spec/hints.h:54
uint32_t odp_le_to_cpu_32(odp_u32le_t le32)
Convert 32bit little endian to cpu native uint32_t.
uint16_t odp_be_to_cpu_16(odp_u16be_t be16)
Convert 16bit big endian to cpu native uint16_t.
uint64_t odp_be_to_cpu_64(odp_u64be_t be64)
Convert 64bit big endian to cpu native uint64_t.
odp_u32le_t odp_cpu_to_le_32(uint32_t cpu32)
Convert cpu native uint32_t to 32bit little endian.
uint16_t odp_le_to_cpu_16(odp_u16le_t le16)
Convert 16bit little endian to cpu native uint16_t.
uint64_t odp_le_to_cpu_64(odp_u64le_t le64)
Convert 64bit little endian to cpu native uint64_t.
odp_u32be_t odp_cpu_to_be_32(uint32_t cpu32)
Convert cpu native uint32_t to 32bit big endian.
uint32_t odp_be_to_cpu_32(odp_u32be_t be32)
Convert 32bit big endian to cpu native uint32_t.
void odp_cpu_pause(void)
Pause CPU execution for a short while.
uint64_t odp_cpu_cycles_diff(uint64_t c2, uint64_t c1)
CPU cycle count difference.
uint64_t odp_cpu_cycles_resolution(void)
Resolution of CPU cycle count.
void odp_prefetch_store(const void *addr)
Prefetch into data cache for storing.
uint64_t odp_cpu_cycles(void)
Current CPU cycle count.
int odp_cpu_id(void)
CPU identifier.
int odp_cpu_count(void)
CPU count.
void odp_prefetch_l3(const void *addr)
Prefetch into L3 data cache.
void odp_prefetch_store_strm_l1(const void *addr)
Streaming prefetch into L1 data cache for storing.
void odp_prefetch_l1i(const void *addr)
Prefetch into L1 instruction cache.
void odp_prefetch_store_l1(const void *addr)
Prefetch into L1 data cache for storing.
void odp_prefetch_l1(const void *addr)
Prefetch into L1 data cache.
uint64_t odp_cpu_hz_max_id(int id)
Maximum CPU frequency of a CPU (in Hz)
void odp_prefetch_l2(const void *addr)
Prefetch into L2 data cache.
uint64_t odp_cpu_hz_max(void)
Maximum CPU frequency in Hz.
void odp_prefetch(const void *addr)
Prefetch into data cache.
void odp_prefetch_store_l2(const void *addr)
Prefetch into L2 data cache for storing.
uint64_t odp_cpu_cycles_max(void)
Maximum CPU cycle count.
void odp_prefetch_strm_l1(const void *addr)
Streaming prefetch into L1 data cache.
uint64_t odp_cpu_hz(void)
Current CPU frequency in Hz.
void odp_prefetch_store_l3(const void *addr)
Prefetch into L3 data cache for storing.
uint64_t odp_cpu_hz_id(int id)
Current CPU frequency of a CPU (in Hz)
void odp_cpumask_set(odp_cpumask_t *mask, int cpu)
Add CPU to mask.
int odp_cpumask_default_worker(odp_cpumask_t *mask, int num)
Default CPU mask for worker threads.
int odp_cpumask_first(const odp_cpumask_t *mask)
Find first set CPU in mask.
void odp_cpumask_zero(odp_cpumask_t *mask)
Clear entire CPU mask.
int32_t odp_cpumask_to_str(const odp_cpumask_t *mask, char *str, int32_t size)
Format a string from CPU mask.
#define ODP_CPUMASK_STR_SIZE
The maximum number of characters needed to record any CPU mask as a string (output of odp_cpumask_to_...
void odp_init_param_init(odp_init_t *param)
Initialize the odp_init_t to default values for all fields.
#define ODP_STATIC_ASSERT(cond, msg)
Compile time assertion macro.
int odp_init_local(odp_instance_t instance, odp_thread_type_t thr_type)
Thread local ODP initialization.
int odp_init_global(odp_instance_t *instance, const odp_init_t *params, const odp_platform_init_t *platform_params)
Global ODP initialization.
int odp_term_local(void)
Thread local ODP termination.
int odp_term_global(odp_instance_t instance)
Global ODP termination.
uint64_t odp_instance_t
ODP instance ID.
int odp_shm_free(odp_shm_t shm)
Free a contiguous block of shared memory.
void * odp_shm_addr(odp_shm_t shm)
Shared memory block address.
#define ODP_SHM_INVALID
Invalid shared memory block.
odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align, uint32_t flags)
Reserve a contiguous block of shared memory.
void odp_sys_info_print(void)
Print system info.
odp_thread_type_t odp_thread_type(void)
Thread type.
int odp_thread_count(void)
Thread count.
int odp_thread_count_max(void)
Maximum thread count.
int odp_thread_id(void)
Get thread identifier.
@ ODP_THREAD_WORKER
Worker thread.
@ ODP_THREAD_CONTROL
Control thread.
uint64_t odp_time_to_ns(odp_time_t time)
Convert time to nanoseconds.
odp_time_t odp_time_diff(odp_time_t t2, odp_time_t t1)
Time difference.
odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2)
Time sum.
#define ODP_TIME_SEC_IN_NS
A second in nanoseconds.
uint64_t odp_time_local_strict_ns(void)
Current local time in nanoseconds (strict)
odp_time_t odp_time_local_from_ns(uint64_t ns)
Convert nanoseconds to local time.
odp_time_t odp_time_global(void)
Current global time.
odp_time_t odp_time_local(void)
Current local time.
#define ODP_TIME_NULL
Zero time stamp.
uint64_t odp_time_global_strict_ns(void)
Current global time in nanoseconds (strict)
uint64_t odp_time_local_res(void)
Local time resolution in hertz.
odp_time_t odp_time_global_strict(void)
Current global time (strict)
odp_time_t odp_time_add_ns(odp_time_t time, uint64_t ns)
Add nanoseconds into time.
#define ODP_TIME_MSEC_IN_NS
A millisecond in nanoseconds.
uint64_t odp_time_global_ns(void)
Current global time in nanoseconds.
odp_time_t odp_time_local_strict(void)
Current local time (strict)
int odp_time_cmp(odp_time_t t2, odp_time_t t1)
Compare two times.
odp_time_t odp_time_global_from_ns(uint64_t ns)
Convert nanoseconds to global time.
uint64_t odp_time_local_ns(void)
Current local time in nanoseconds.
uint64_t odp_time_diff_ns(odp_time_t t2, odp_time_t t1)
Time difference in nanoseconds.
uint64_t odp_time_global_res(void)
Global time resolution in hertz.
void odp_time_startup(odp_time_startup_t *startup)
Get ODP instance startup time.
The OpenDataPlane API.
Global initialization parameters.
odp_mem_model_t mem_model
Application memory model.
Time stamp values at ODP startup.
uint64_t global_ns
Global time in nanoseconds at ODP startup.