This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit 9148fb97186196778ea0efa5f083ecb630e4287d Author: makejian <[email protected]> AuthorDate: Tue Jan 20 10:29:56 2026 +0800 benchmarks: Add Whetstone FPU benchmark Add the Whetstone floating-point benchmark to NuttX applications. The Whetstone benchmark is a widely-used tool for evaluating FPU (floating-point unit) performance. This benchmark is ported from netlib.org whetstone.c which has a custom permissive license requiring attribution. Therefore it depends on ALLOW_CUSTOM_PERMISSIVE_COMPONENTS. Usage: whetstone [loops] Signed-off-by: makejian <[email protected]> --- benchmarks/whetstone/CMakeLists.txt | 31 +++ benchmarks/whetstone/Kconfig | 34 +++ benchmarks/whetstone/Make.defs | 23 ++ benchmarks/whetstone/Makefile | 32 +++ benchmarks/whetstone/whetstone.c | 517 ++++++++++++++++++++++++++++++++++++ 5 files changed, 637 insertions(+) diff --git a/benchmarks/whetstone/CMakeLists.txt b/benchmarks/whetstone/CMakeLists.txt new file mode 100644 index 000000000..1bcc0f256 --- /dev/null +++ b/benchmarks/whetstone/CMakeLists.txt @@ -0,0 +1,31 @@ +# ############################################################################## +# apps/benchmarks/whetstone/CMakeLists.txt +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +if(CONFIG_BENCHMARK_WHETSTONE) + nuttx_add_application( + NAME + ${CONFIG_BENCHMARK_WHETSTONE_PROGNAME} + SRCS + whetstone.c + STACKSIZE + ${CONFIG_BENCHMARK_WHETSTONE_STACKSIZE} + PRIORITY + ${CONFIG_BENCHMARK_WHETSTONE_PRIORITY}) +endif() diff --git a/benchmarks/whetstone/Kconfig b/benchmarks/whetstone/Kconfig new file mode 100644 index 000000000..10df1429e --- /dev/null +++ b/benchmarks/whetstone/Kconfig @@ -0,0 +1,34 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config BENCHMARK_WHETSTONE + tristate "Double Precision Benchmark" + default n + depends on ALLOW_CUSTOM_PERMISSIVE_COMPONENTS + ---help--- + Enable a Whetstone test. + + This benchmark is based on the C converted version from + https://www.netlib.org/benchmark/whetstone.c which has a + custom permissive license requiring attribution. + +if BENCHMARK_WHETSTONE + +config BENCHMARK_WHETSTONE_PROGNAME + string "Program name" + default "whetstone" + ---help--- + This is the name of the program that will be used when the NSH ELF + program is installed. + +config BENCHMARK_WHETSTONE_PRIORITY + int "Whetstone test task priority" + default 100 + +config BENCHMARK_WHETSTONE_STACKSIZE + int "Whetstone test stack size" + default DEFAULT_TASK_STACKSIZE + +endif diff --git a/benchmarks/whetstone/Make.defs b/benchmarks/whetstone/Make.defs new file mode 100644 index 000000000..d9fa9f1af --- /dev/null +++ b/benchmarks/whetstone/Make.defs @@ -0,0 +1,23 @@ +############################################################################ +# apps/benchmarks/whetstone/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifneq ($(CONFIG_BENCHMARK_WHETSTONE),) +CONFIGURED_APPS += $(APPDIR)/benchmarks/whetstone +endif diff --git a/benchmarks/whetstone/Makefile b/benchmarks/whetstone/Makefile new file mode 100644 index 000000000..1bdf6dfd6 --- /dev/null +++ b/benchmarks/whetstone/Makefile @@ -0,0 +1,32 @@ +############################################################################ +# apps/benchmarks/whetstone/Makefile +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(APPDIR)/Make.defs + +# WHETSTONE speed test + +PROGNAME = $(CONFIG_BENCHMARK_WHETSTONE_PROGNAME) +PRIORITY = $(CONFIG_BENCHMARK_WHETSTONE_PRIORITY) +STACKSIZE = $(CONFIG_BENCHMARK_WHETSTONE_STACKSIZE) +MODULE = $(CONFIG_BENCHMARK_WHETSTONE) + +MAINSRC = whetstone.c + +include $(APPDIR)/Application.mk diff --git a/benchmarks/whetstone/whetstone.c b/benchmarks/whetstone/whetstone.c new file mode 100644 index 000000000..4363baaf7 --- /dev/null +++ b/benchmarks/whetstone/whetstone.c @@ -0,0 +1,517 @@ +/**************************************************************************** + * apps/benchmarks/whetstone/whetstone.c + * + * SPDX-License-Identifier: LicenseRef-Painter-Engineering-Whetstone + * + * Converted Whetstone Double Precision Benchmark + * Version 1.2 22 March 1998 + * + * (c) Copyright 1998 Painter Engineering, Inc. + * All Rights Reserved. + * + * Permission is granted to use, duplicate, and + * publish this text and program as long as it + * includes this entire comment block and limited + * rights reference. + * + * Converted by Rich Painter, Painter Engineering, Inc. based on the + * www.netlib.org benchmark/whetstoned version obtained 16 March 1998. + * + * A novel approach was used here to keep the look and feel of the + * FORTRAN version. Altering the FORTRAN-based array indices, + * starting at element 1, to start at element 0 for C, would require + * numerous changes, including decrementing the variable indices by 1. + * Instead, the array e1[] was declared 1 element larger in C. This + * allows the FORTRAN index range to function without any literal or + * variable indices changes. The array element e1[0] is simply never + * used and does not alter the benchmark results. + * + * The major FORTRAN comment blocks were retained to minimize + * differences between versions. Modules N5 and N12, like in the + * FORTRAN version, have been eliminated here. + * + * An optional command-line argument has been provided [-c] to + * offer continuous repetition of the entire benchmark. + * An optional argument for setting an alternate loop count is also + * provided. Define PRINTOUT to cause the pout() function to print + * outputs at various stages. Final timing measurements should be + * made with the PRINTOUT undefined. + * + * Questions and comments may be directed to the author at + * [email protected] + ****************************************************************************/ + +/**************************************************************************** + * Benchmark #2 -- Double Precision Whetstone (A001) + * + * o This is a REAL*8 version of + * the Whetstone benchmark program. + * + * o DO-loop semantics are ANSI-66 compatible. + * + * o Final measurements are to be made with all + * WRITE statements and FORMAT sttements removed. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* standard C library headers required */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> + +/* the following is optional depending on the timing function used */ + +#include <time.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* map the FORTRAN math functions, etc. to the C versions */ + +#define DSIN sin +#define DCOS cos +#define DATAN atan +#define DLOG log +#define DEXP exp +#define DSQRT sqrt +#define IF if +#define USAGE "usage: whetdc [-c] [loops]\n" + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* function prototypes */ + +void pout(long n, long j, long k, double x1, + double x2, double x3, double x4); +void pa(double e[]); +void p0(void); +void p3(double x, double y, FAR double *z); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* COMMON t,t1,t2,e1(4),j,k,l */ + +double t; +double t1; +double t2; +double e1[5]; +int j; +int k; +int l; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, FAR char *argv[]) +{ + /* used in the FORTRAN version */ + + long loop; + long i; + long n1; + long n2; + long n3; + long n4; + long n6; + long n7; + long n8; + long n9; + long n10; + long n11; + double x1; + double x2; + double x3; + double x4; + double x; + double y; + double z; + int ii; + int jj; + + /* added for this version */ + + long loopstart; + long startsec; + long finisec; + float KIPS; + int continuous; + + loopstart = 1000; /* see the note about loop below */ + continuous = 0; + + ii = 1; /* start at the first arg (temp use of ii here) */ + while (ii < argc) + { + if (strncmp(argv[ii], "-c", 2) == 0 || argv[ii][0] == 'c') + { + continuous = 1; + } + else if (atol(argv[ii]) > 0) + { + loopstart = atol(argv[ii]); + } + else + { + fprintf(stderr, USAGE); + return 1; + } + + ii++; + } + +LCONT: + + /* Start benchmark timing at this point. */ + + startsec = time(0); + + /* The actual benchmark starts here. */ + + t = .499975; + t1 = 0.50025; + t2 = 2.0; + + /* With loopcount loop=10, one million Whetstone instructions + * will be executed in EACH MAJOR loop..A MAJOR loop IS EXECUTED + * 'ii' TIMES TO INCREASE WALL-CLOCK TIMING ACCURACY. + * + * loop = 1000; + */ + + loop = loopstart; + ii = 1; + + jj = 1; + +IILOOP: + n1 = 0; + n2 = 12 * loop; + n3 = 14 * loop; + n4 = 345 * loop; + n6 = 210 * loop; + n7 = 32 * loop; + n8 = 899 * loop; + n9 = 616 * loop; + n10 = 0; + n11 = 93 * loop; + + /* Module 1: Simple identifiers */ + + x1 = 1.0; + x2 = -1.0; + x3 = -1.0; + x4 = -1.0; + + for (i = 1; i <= n1; i++) + { + x1 = (x1 + x2 + x3 - x4) * t; + x2 = (x1 + x2 - x3 + x4) * t; + x3 = (x1 - x2 + x3 + x4) * t; + x4 = (-x1 + x2 + x3 + x4) * t; + } + +#ifdef PRINTOUT + IF (jj == ii) + { + pout(n1, n1, n1, x1, x2, x3, x4); + } +#endif + + /* Module 2: Array elements */ + + e1[1] = 1.0; + e1[2] = -1.0; + e1[3] = -1.0; + e1[4] = -1.0; + + for (i = 1; i <= n2; i++) + { + e1[1] = (e1[1] + e1[2] + e1[3] - e1[4]) * t; + e1[2] = (e1[1] + e1[2] - e1[3] + e1[4]) * t; + e1[3] = (e1[1] - e1[2] + e1[3] + e1[4]) * t; + e1[4] = (-e1[1] + e1[2] + e1[3] + e1[4]) * t; + } + +#ifdef PRINTOUT + IF (jj == ii) + { + pout(n2, n3, n2, e1[1], e1[2], e1[3], e1[4]); + } +#endif + + /* Module 3: Array as parameter */ + + for (i = 1; i <= n3; i++) + { + pa(e1); + } + +#ifdef PRINTOUT + IF (jj == ii) + { + pout(n3, n2, n2, e1[1], e1[2], e1[3], e1[4]); + } +#endif + + /* Module 4: Conditional jumps */ + + j = 1; + for (i = 1; i <= n4; i++) + { + if (j == 1) + { + j = 2; + } + else + { + j = 3; + } + + if (j > 2) + { + j = 0; + } + else + { + j = 1; + } + + if (j < 1) + { + j = 1; + } + else + { + j = 0; + } + } + +#ifdef PRINTOUT + IF (jj == ii) + { + pout(n4, j, j, x1, x2, x3, x4); + } +#endif + +/* Module 5: Omitted + * Module 6: Integer arithmetic + */ + + j = 1; + k = 2; + l = 3; + + for (i = 1; i <= n6; i++) + { + j = j * (k - j) * (l - k); + k = l * k - (l - j) * k; + l = (l - k) * (k + j); + e1[l - 1] = j + k + l; + e1[k - 1] = j * k * l; + } + +#ifdef PRINTOUT + IF (jj == ii) + { + pout(n6, j, k, e1[1], e1[2], e1[3], e1[4]); + } +#endif + + /* Module 7: Trigonometric functions */ + + x = 0.5; + y = 0.5; + + for (i = 1; i <= n7; i++) + { + x = t * DATAN(t2 * DSIN(x) * DCOS(x) / + (DCOS(x + y) + DCOS(x - y) - 1.0)); + y = t * DATAN(t2 * DSIN(y) * DCOS(y) / + (DCOS(x + y) + DCOS(x - y) - 1.0)); + } + +#ifdef PRINTOUT + IF (jj == ii) + { + pout(n7, j, k, x, x, y, y); + } +#endif + + /* Module 8: Procedure calls */ + + x = 1.0; + y = 1.0; + z = 1.0; + + for (i = 1; i <= n8; i++) + { + p3(x, y, &z); + } + +#ifdef PRINTOUT + IF (jj == ii) + { + pout(n8, j, k, x, y, z, z); + } +#endif + + /* Module 9: Array references */ + + j = 1; + k = 2; + l = 3; + e1[1] = 1.0; + e1[2] = 2.0; + e1[3] = 3.0; + + for (i = 1; i <= n9; i++) + { + p0(); + } + +#ifdef PRINTOUT + IF (jj == ii) + { + pout(n9, j, k, e1[1], e1[2], e1[3], e1[4]); + } +#endif + + /* Module 10: Integer arithmetic */ + + j = 2; + k = 3; + + for (i = 1; i <= n10; i++) + { + j = j + k; + k = j + k; + j = k - j; + k = k - j - j; + } + +#ifdef PRINTOUT + IF (jj == ii) + { + pout(n10, j, k, x1, x2, x3, x4); + } +#endif + + /* Module 11: Standard functions */ + + x = 0.75; + + for (i = 1; i <= n11; i++) + x = DSQRT(DEXP(DLOG(x) / t1)); + +#ifdef PRINTOUT + IF (jj == ii) + { + pout(n11, j, k, x, x, x, x); + } +#endif + + /* THIS IS THE END OF THE MAJOR loop. */ + + if (++jj <= ii) + { + goto IILOOP; + } + + /* Stop benchmark timing at this point. */ + + finisec = time(0); + + /* Performance in Whetstone KIP's per second is given by + * + * (100*loop*ii)/TIME + * + * where TIME is in seconds. + */ + + printf("\n"); + if (finisec - startsec <= 0) + { + printf("Insufficient duration- Increase the loop count\n"); + return 1; + } + + printf("Loops: %ld, Iterations: %d, Duration: %ld sec.\n", + loop, ii, finisec - startsec); + + KIPS = (100.0 * loop * ii) / (float)(finisec - startsec); + if (KIPS >= 1000.0) + { + printf("C Converted Double Precision Whetstones: %.1f MIPS\n", + KIPS / 1000.0); + } + else + { + printf("C Converted Double Precision Whetstones: %.1f KIPS\n", KIPS); + } + + if (continuous) + { + goto LCONT; + } + + return 0; +} + +void +pa(double e[]) +{ + j = 0; + +L10: + e[1] = (e[1] + e[2] + e[3] - e[4]) * t; + e[2] = (e[1] + e[2] - e[3] + e[4]) * t; + e[3] = (e[1] - e[2] + e[3] + e[4]) * t; + e[4] = (-e[1] + e[2] + e[3] + e[4]) / t2; + j += 1; + + if (j < 6) + { + goto L10; + } +} + +void +p0(void) +{ + e1[j] = e1[k]; + e1[k] = e1[l]; + e1[l] = e1[j]; +} + +void p3(double x, double y, FAR double *z) +{ + double x1; + double y1; + + x1 = x; + y1 = y; + x1 = t * (x1 + y1); + y1 = t * (x1 + y1); + *z = (x1 + y1) / t2; +} + +#ifdef PRINTOUT +void +pout(long n, long j, long k, double x1, double x2, double x3, double x4) +{ + printf("%7ld %7ld %7ld %12.4e %12.4e %12.4e %12.4e\n", + n, j, k, x1, x2, x3, x4); +} +#endif
