Skip to content

Commit

Permalink
[ISSUE-0051]: Unified additive and multiplicative performance tests
Browse files Browse the repository at this point in the history
  • Loading branch information
SzigetiJ committed Jan 8, 2024
1 parent 9f5201a commit 951e00f
Show file tree
Hide file tree
Showing 6 changed files with 363 additions and 114 deletions.
12 changes: 11 additions & 1 deletion tests/performance/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
UINT_PROGS = add_uperf
BUINT128_PROGS = \
add_perf128 \
mul_perf128 \
div10_perf128 \
div1000_perf128 \
parse_perf128 \
Expand All @@ -13,6 +14,7 @@ CLEANFILES =

BUINT256_PROGS = \
add_perf256 \
mul_perf256 \
div10_perf256 \
div1000_perf256 \
parse_perf256 \
Expand All @@ -21,6 +23,7 @@ BUINT256_PROGS = \

BUINT512_PROGS = \
add_perf512 \
mul_perf512 \
div10_perf512 \
div1000_perf512 \
parse_perf512 \
Expand All @@ -29,6 +32,7 @@ BUINT512_PROGS = \

BUINTEXTRA_PROGS = \
add_perf@userdef_bits@ \
mul_perf@userdef_bits@ \
div10_perf@userdef_bits@ \
div1000_perf@userdef_bits@ \
parse_perf@userdef_bits@ \
Expand All @@ -40,13 +44,15 @@ if WITH_BIGUINT256

CLEANFILES += perf_common256.h \
add_perf256.c \
mul_perf256.c \
div10_perf256.c \
div1000_perf256.c \
parse_perf256.c \
print_perf256.c \
shift_perf256.c

nodist_add_perf256_SOURCES = add_perf256.c
nodist_mul_perf256_SOURCES = mul_perf256.c
nodist_div10_perf256_SOURCES = div10_perf256.c
nodist_div1000_perf256_SOURCES = div1000_perf256.c
nodist_parse_perf256_SOURCES = parse_perf256.c
Expand All @@ -66,13 +72,15 @@ if WITH_BIGUINT512

CLEANFILES += perf_common512.h \
add_perf512.c \
mul_perf512.c \
div10_perf512.c \
div1000_perf512.c \
parse_perf512.c \
print_perf512.c \
shift_perf512.c

nodist_add_perf512_SOURCES = add_perf512.c
nodist_mul_perf512_SOURCES = mul_perf512.c
nodist_div10_perf512_SOURCES = div10_perf512.c
nodist_div1000_perf512_SOURCES = div1000_perf512.c
nodist_parse_perf512_SOURCES = parse_perf512.c
Expand All @@ -92,13 +100,15 @@ if EXTRA_BITLEN

CLEANFILES += perf_common@[email protected] \
add_perf@[email protected] \
mul_perf@[email protected] \
div10_perf@[email protected] \
div1000_perf@[email protected] \
parse_perf@[email protected] \
print_perf@[email protected] \
shift_perf@[email protected]

nodist_add_perf@userdef_bits@_SOURCES = add_perf@[email protected]
nodist_mul_perf@userdef_bits@_SOURCES = mul_perf@[email protected]
nodist_div10_perf@userdef_bits@_SOURCES = div10_perf@[email protected]
nodist_div1000_perf@userdef_bits@_SOURCES = div1000_perf@[email protected]
nodist_parse_perf@userdef_bits@_SOURCES = parse_perf@[email protected]
Expand All @@ -114,7 +124,7 @@ if EXTRA_BITLEN
endif

AM_CPPFLAGS = -I${top_srcdir}/src -I../../src
LDADD = ../../src/libbiguint.a
LDADD = perf_common.o ../../src/libbiguint.a

EXTRA_DIST = perf_common128.h

Expand Down
189 changes: 78 additions & 111 deletions tests/performance/add_perf128.c
Original file line number Diff line number Diff line change
@@ -1,129 +1,96 @@
#include "biguint128.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define LOOPS (1<<26) // 64M loops
#define BUFLEN 40 // for printsceen debugging
#include "biguint128.h"
#include "perf_common.h"
#include "perf_common128.h"

static void print_result(clock_t t_begin, clock_t t_end, const char *op, int cnt) {
clock_t dt = t_end - t_begin;
fprintf(stdout, "=== %d BigUInt128 %s operations ===\n", cnt, op);
fprintf(stdout, "Elapsed time: %ld us,\t%.1f op/s\n", dt, (1000000.0 * cnt) / dt);
}

int main() {
BigUInt128 b0 = biguint128_ctor_default();
BigUInt128 b1 = biguint128_ctor_unit();
uint32_t loop_cnt;
clock_t t0, t1;
char buf[BUFLEN];
// ### Constraints and default values
#define MAX_LEVELS 8U
#define DEFAULT_LEVELS 3U
#define MAX_LOOPS (1<<28) // 256M loops
#define DEFAULT_LOOPS (1<<26) // 64M loops
#define BUFLEN 40 // for full function names
#define INC_A 37U
#define INC_B 29U

// #1: conventional add
t0 = clock();
for (loop_cnt = 0; loop_cnt < LOOPS; ++loop_cnt) {
b0 = biguint128_add(&b0, &b1);
}
t1 = clock();
print_result(t0, t1, "add", LOOPS);
buf[biguint128_print_dec(&b0, buf, BUFLEN)] = 0;
fprintf(stdout, "(current sum: %s)\n", buf);
// ### Local types
typedef enum {
FUN_ADD = 0,
FUN_ADD_ASGN,
FUN_ADD_REPL,
FUN_ADD_TINY,
FUN_SUB,
FUN_SUB_ASGN,
FUN_SUB_REPL,
FUN_SUB_TINY
} AdditiveFun;

// #2: add-assignment
t0 = clock();
for (loop_cnt = 0; loop_cnt < LOOPS; ++loop_cnt) {
biguint128_add_assign(&b0, &b1);
}
t1 = clock();
print_result(t0, t1, "add-assignment", LOOPS);
buf[biguint128_print_dec(&b0, buf, BUFLEN)] = 0;
fprintf(stdout, "(current sum: %s)\n", buf);
// ### Constants
const char *funname[]={
"add",
"add_assign",
"add_replace",
"add_tiny",
"sub",
"sub_assign",
"sub_replace",
"sub_tiny"
};
const unsigned int fun_n = sizeof(funname) / sizeof(funname[0]);

// #2: add-replace
t0 = clock();
for (loop_cnt = 0; loop_cnt < LOOPS; ++loop_cnt) {
biguint128_add_replace(&b0, &b0, &b1);
}
t1 = clock();
print_result(t0, t1, "add-replace", LOOPS);
buf[biguint128_print_dec(&b0, buf, BUFLEN)] = 0;
fprintf(stdout, "(current sum: %s)\n", buf);
const StandardArgs ARGS_DEFAULT = {
DEFAULT_LOOPS, false, false,
DEFAULT_LEVELS, -1, -1,
INC_A, INC_B,
-1, 0
};

// #3: add-assign uint as biguint
{
t0 = clock();
BigUInt128 b2 = biguint128_ctor_standard(&b1.dat[0]);
for (loop_cnt = 0; loop_cnt < LOOPS; ++loop_cnt) {
biguint128_add_assign(&b0, &b2);
}
t1 = clock();
print_result(t0, t1, "add-assign uint", LOOPS);
buf[biguint128_print_dec(&b0, buf, BUFLEN)] = 0;
fprintf(stdout, "(current sum: %s)\n", buf);
}
// #4: add-tiny
t0 = clock();
for (loop_cnt = 0; loop_cnt < LOOPS; ++loop_cnt) {
biguint128_add_tiny(&b0, b1.dat[0]);
}
t1 = clock();
print_result(t0, t1, "add-tiny", LOOPS);
buf[biguint128_print_dec(&b0, buf, BUFLEN)] = 0;
fprintf(stdout, "(current sum: %s)\n", buf);
// ### Internal functions
static void exec_function_loop_(unsigned int ai, unsigned int bi, unsigned int fun, const StandardArgs *args) {
BigUInt128 a = get_value_by_level(ai, args->levels);
BigUInt128 b = get_value_by_level(bi, args->levels);
BigUInt128 chkval = biguint128_ctor_default();
BigUInt128 res;
BigUInt128 *procref = (fun&1)?&a:&res; // note, every second function is an assignment operation
clock_t t0, t1;
char fnamebuf[BUFLEN];

// #5: sub-tiny
t0 = clock();
for (loop_cnt = 0; loop_cnt < LOOPS; ++loop_cnt) {
biguint128_sub_tiny(&b0, b1.dat[0]);
}
t1 = clock();
print_result(t0, t1, "sub-tiny", LOOPS);
buf[biguint128_print_dec(&b0, buf, BUFLEN)] = 0;
fprintf(stdout, "(current sum: %s)\n", buf);

// #6: sub-assign uint as biguint
{
t0 = clock();
BigUInt128 b2 = biguint128_ctor_standard(&b1.dat[0]);
for (loop_cnt = 0; loop_cnt < LOOPS; ++loop_cnt) {
biguint128_sub_assign(&b0, &b2);
for (unsigned int i = 0; i < args->loops; ++i) {
if (!(fun & 4)) { // lower 4 functions
if (fun == FUN_ADD) {
res = biguint128_add(&a, &b);
} else if (fun == FUN_ADD_ASGN) {
biguint128_add_assign(&a, &b);
} else if (fun == FUN_ADD_TINY) {
biguint128_add_tiny(&a, b.dat[0]);
} else if (fun == FUN_ADD_REPL) {
biguint128_add_replace(&res, &a, &b);
}
} else { // upper 4 functions
if (fun == FUN_SUB) {
res = biguint128_sub(&a, &b);
} else if (fun == FUN_SUB_ASGN) {
biguint128_sub_assign(&a, &b);
} else if (fun == FUN_SUB_TINY) {
biguint128_sub_tiny(&a, b.dat[0]);
} else if (fun == FUN_SUB_REPL) {
biguint128_sub_replace(&res, &a, &b);
}
}
t1 = clock();
print_result(t0, t1, "sub-assign uint", LOOPS);
buf[biguint128_print_dec(&b0, buf, BUFLEN)] = 0;
fprintf(stdout, "(current sum: %s)\n", buf);
}

// #7: sub-replace
t0 = clock();
for (loop_cnt = 0; loop_cnt < LOOPS; ++loop_cnt) {
biguint128_sub_replace(&b0, &b0, &b1);
process_result_v1(procref, &chkval.dat[0]);
inc_operands_v1(&a, &b, args->diff_a, args->diff_b);
}
t1 = clock();
print_result(t0, t1, "sub-replace", LOOPS);
buf[biguint128_print_dec(&b0, buf, BUFLEN)] = 0;
fprintf(stdout, "(current sum: %s)\n", buf);

// #8: sub-assignment
t0 = clock();
for (loop_cnt = 0; loop_cnt < LOOPS; ++loop_cnt) {
biguint128_sub_assign(&b0, &b1);
}
t1 = clock();
print_result(t0, t1, "sub-assignment", LOOPS);
buf[biguint128_print_dec(&b0, buf, BUFLEN)] = 0;
fprintf(stdout, "(current sum: %s)\n", buf);

// #9: conventional sub
t0 = clock();
for (loop_cnt = 0; loop_cnt < LOOPS; ++loop_cnt) {
b0 = biguint128_sub(&b0, &b1);
}
t1 = clock();
print_result(t0, t1, "sub", LOOPS);
buf[biguint128_print_dec(&b0, buf, BUFLEN)] = 0;
fprintf(stdout, "(current sum: %s)\n", buf);
snprintf(fnamebuf, BUFLEN, "%s + 2*add_tiny(C)", funname[fun]);
print_exec_summary(t0, t1, fnamebuf, args->loops, &chkval, 1);
}

return 0;
// ### Main function
int main(int argc, const char *argv[]) {
return fun2_main(argc, argv, 128, ARGS_DEFAULT, MAX_LEVELS, MAX_LOOPS, fun_n, funname, &exec_function_loop_);
}
76 changes: 76 additions & 0 deletions tests/performance/mul_perf128.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "biguint128.h"
#include "perf_common.h"
#include "perf_common128.h"


// ### Constraints and default values
#define MAX_LEVELS 8U
#define DEFAULT_LEVELS 3U
#define MAX_LOOPS (1<<26) // 64M loops
#define DEFAULT_LOOPS (1<<20) // 1M loops
#define BUFLEN 40 // for full function names
#define INC_A 37U
#define INC_B 29U

// ### Local types
typedef enum {
FUN_MUL = 0,
FUN_DMUL,
FUN_DIV
} MultiplicativeFun;

// ### Constants
const char *funname[]={
"mul",
"dmul",
"div"
};
const unsigned int fun_n = sizeof(funname) / sizeof(funname[0]);

const StandardArgs ARGS_DEFAULT = {
DEFAULT_LOOPS, false, false,
DEFAULT_LEVELS, -1, -1,
INC_A, INC_B,
-1, 0
};


// ### Internal functions
static void exec_function_loop_(unsigned int ai, unsigned int bi, unsigned int fun, const StandardArgs *args) {
BigUInt128 a = get_value_by_level(ai, args->levels);
BigUInt128 b = get_value_by_level(bi, args->levels);
BigUInt128 chkval = biguint128_ctor_default();
BigUInt128 res;
BigUIntPair128 resp;
BigUInt128 *procref1 = fun==FUN_MUL?&res:&resp.first;
BigUInt128 *procref2 = fun==FUN_MUL?&res:&resp.second;
clock_t t0, t1;
char fnamebuf[BUFLEN];

t0 = clock();
for (unsigned int i = 0; i < args->loops; ++i) {
if (fun == FUN_MUL) {
res = biguint128_mul(&a, &b);
} else if (fun == FUN_DMUL) {
resp = biguint128_dmul(&a, &b);
} else if (fun == FUN_DIV) {
resp = biguint128_div(&a, &b);
}
process_result_v1(procref2, &chkval.dat[0]);
process_result_v1(procref1, &chkval.dat[0]);
inc_operands_v1(&a, &b, (UInt) args->diff_a, (UInt) args->diff_b);
}
t1 = clock();
snprintf(fnamebuf, BUFLEN, "%s + 2*add_tiny(C)", funname[fun]);
print_exec_summary(t0, t1, fnamebuf, args->loops, &chkval, 1);
}

// ### Main function
int main(int argc, const char *argv[]) {
return fun2_main(argc, argv, 128, ARGS_DEFAULT, MAX_LEVELS, MAX_LOOPS, fun_n, funname, &exec_function_loop_);
}
Loading

0 comments on commit 951e00f

Please sign in to comment.