Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PATCH v2] test: performance: refactor bench applications #1907

Merged
merged 4 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions test/performance/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ endif
bin_PROGRAMS = $(EXECUTABLES) $(COMPILE_ONLY)

odp_atomic_perf_SOURCES = odp_atomic_perf.c
odp_bench_buffer_SOURCES = odp_bench_buffer.c
odp_bench_misc_SOURCES = odp_bench_misc.c
odp_bench_packet_SOURCES = odp_bench_packet.c
odp_bench_timer_SOURCES = odp_bench_timer.c
odp_bench_buffer_SOURCES = odp_bench_buffer.c bench_common.c bench_common.h
odp_bench_misc_SOURCES = odp_bench_misc.c bench_common.c bench_common.h
odp_bench_packet_SOURCES = odp_bench_packet.c bench_common.c bench_common.h
odp_bench_timer_SOURCES = odp_bench_timer.c bench_common.c bench_common.h
odp_cpu_bench_SOURCES = odp_cpu_bench.c
odp_crc_SOURCES = odp_crc.c
odp_crypto_SOURCES = odp_crypto.c
Expand Down
138 changes: 138 additions & 0 deletions test/performance/bench_common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2023 Nokia
*/

#include <odp_api.h>
#include <odp/helper/odph_api.h>

#include "bench_common.h"

#include <inttypes.h>
#include <stdint.h>
#include <string.h>

void bench_suite_init(bench_suite_t *suite)
{
memset(suite, 0, sizeof(bench_suite_t));

suite->measure_time = true;

odp_atomic_init_u32(&suite->exit_worker, 0);
}

void bench_run_indef(bench_info_t *info, odp_atomic_u32_t *exit_thread)
{
const char *desc;

desc = info->desc != NULL ? info->desc : info->name;

printf("Running odp_%s test indefinitely\n", desc);

while (!odp_atomic_load_u32(exit_thread)) {
int ret;

if (info->init != NULL)
info->init();

ret = info->run();

if (info->term != NULL)
info->term();

if (!ret)
ODPH_ABORT("Benchmark %s failed\n", desc);
}
}

int bench_run(void *arg)
{
uint64_t c1, c2;
odp_time_t t1, t2;
bench_suite_t *suite = arg;
const uint64_t repeat_count = suite->repeat_count;
const odp_bool_t meas_time = suite->measure_time;

printf("\nAverage %s per function call\n", meas_time ? "time (nsec)" : "CPU cycles");
printf("-------------------------------------------------\n");

/* Run each test twice. Results from the first warm-up round are ignored. */
for (int i = 0; i < 2; i++) {
uint64_t total = 0;
uint64_t round = 1;

for (int j = 0; j < suite->num_bench; round++) {
int ret;
const char *desc;
const bench_info_t *bench = &suite->bench[j];
uint64_t max_rounds = suite->rounds;

if (bench->max_rounds && bench->max_rounds < max_rounds)
max_rounds = bench->max_rounds;

/* Run selected test indefinitely */
if (suite->indef_idx) {
if ((j + 1) != suite->indef_idx) {
j++;
continue;
}
bench_run_indef(&suite->bench[j], &suite->exit_worker);
return 0;
}

desc = bench->desc != NULL ? bench->desc : bench->name;

if (bench->init != NULL)
bench->init();

if (meas_time)
t1 = odp_time_local_strict();
else
c1 = odp_cpu_cycles();

ret = bench->run();

if (meas_time)
t2 = odp_time_local_strict();
else
c2 = odp_cpu_cycles();

if (bench->term != NULL)
bench->term();

if (!ret) {
ODPH_ERR("Benchmark odp_%s failed\n", desc);
suite->retval = -1;
return -1;
}

if (meas_time)
total += odp_time_diff_ns(t2, t1);
else
total += odp_cpu_cycles_diff(c2, c1);

if (round >= max_rounds) {
double result;

/* Each benchmark runs internally 'repeat_count' times. */
result = ((double)total) / (max_rounds * repeat_count);

/* No print or results from warm-up round */
if (i > 0) {
printf("[%02d] odp_%-26s: %12.2f\n", j + 1, desc, result);

if (suite->result)
suite->result[j] = result;
}
j++;
total = 0;
round = 1;
}
}
}
printf("\n");
/* Print dummy result to prevent compiler to optimize it away*/
if (suite->dummy)
printf("(dummy result: 0x%" PRIx64 ")\n\n", suite->dummy);

return 0;
}
119 changes: 119 additions & 0 deletions test/performance/bench_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2023 Nokia
*/

#ifndef BENCH_COMMON_H
#define BENCH_COMMON_H

#ifdef __cplusplus
extern "C" {
#endif

#include <odp_api.h>
#include <odp/helper/odph_api.h>

#include <stdint.h>

/**
* Check benchmark preconditions
*
* @retval !0 test enabled
*/
typedef int (*bench_cond_fn_t)(void);

/**
* Initialize benchmark resources
*/
typedef void (*bench_init_fn_t)(void);

/**
* Run benchmark
*
* @retval >0 on success
*/
typedef int (*bench_run_fn_t)(void);

/**
* Release benchmark resources
*/
typedef void (*bench_term_fn_t)(void);

/* Benchmark test data */
typedef struct {
/* Default test name */
const char *name;

/* Optional alternate test description */
const char *desc;

/* Optional precondition to run test */
bench_cond_fn_t cond;

/* Optional test initializer function */
bench_init_fn_t init;

/* Test function to run */
bench_run_fn_t run;

/* Optional test terminate function */
bench_term_fn_t term;

/* Optional test specific limit for rounds (tuning for slow implementations) */
uint32_t max_rounds;

} bench_info_t;

/* Benchmark suite data */
typedef struct {
/* Array of benchmark functions */
bench_info_t *bench;

/* Number of benchmark functions */
int num_bench;

/* Optional benchmark index to run indefinitely (1...num_bench) */
int indef_idx;

/* Suite exit value output */
int retval;

/* Measure time vs. CPU cycles */
odp_bool_t measure_time;

/* Break worker loop if set to 1 */
odp_atomic_u32_t exit_worker;

/* Number of API function calls per test case */
uint64_t repeat_count;

/* Number of rounds per test case */
uint64_t rounds;

/* Dummy test result output */
uint64_t dummy;

/* Optional test result output array */
double *result;

} bench_suite_t;

/**
* Initialize benchmark suite parameters
*/
void bench_suite_init(bench_suite_t *suite);

/**
* Run selected test indefinitely
*/
void bench_run_indef(bench_info_t *info, odp_atomic_u32_t *exit_thread);

/**
* Run tests suite and print results
*/
int bench_run(void *arg);

#ifdef __cplusplus
}
#endif

#endif
Loading