From b3ad9fca05ac0ab722f770328d2cc5c9876a1085 Mon Sep 17 00:00:00 2001 From: Minseong Jang Date: Fri, 25 Apr 2025 13:00:42 +0900 Subject: [PATCH] Add benchmarks from riscv-tests --- bench/LICENSE | 34 +++++++++ bench/driver.cpp | 22 ++++++ bench/median.c | 70 +++++++++++++++++ bench/multiply.c | 65 ++++++++++++++++ bench/qsort.c | 129 +++++++++++++++++++++++++++++++ bench/rsort.c | 117 ++++++++++++++++++++++++++++ bench/spmv.c | 90 ++++++++++++++++++++++ bench/towers.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++ bench/vvadd.c | 48 ++++++++++++ 9 files changed, 768 insertions(+) create mode 100644 bench/LICENSE create mode 100644 bench/median.c create mode 100644 bench/multiply.c create mode 100644 bench/qsort.c create mode 100644 bench/rsort.c create mode 100644 bench/spmv.c create mode 100644 bench/towers.c create mode 100644 bench/vvadd.c diff --git a/bench/LICENSE b/bench/LICENSE new file mode 100644 index 0000000..c8a785c --- /dev/null +++ b/bench/LICENSE @@ -0,0 +1,34 @@ +The following files are distributed under the following license with modifications. + +* median.c +* multiply.c +* qsort.c +* rsort.c +* spmv.c +* towers.c +* vvadd.c + +Copyright (c) 2012-2015, The Regents of the University of California (Regents). +All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the Regents nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. diff --git a/bench/driver.cpp b/bench/driver.cpp index 541de6e..bfe5d38 100644 --- a/bench/driver.cpp +++ b/bench/driver.cpp @@ -12,6 +12,13 @@ namespace model { #include #include #include + #include + #include + #include + #include + #include + #include + #include } extern "C" { @@ -28,6 +35,14 @@ extern "C" { int matrix_add(int, int); int graph_dijkstra(int, int); int graph_floyd_warshall(int, int); + // From riscv-tests + int run_median(int, int); + int run_multiply(int, int); + int run_qsort(int, int); + int run_rsort(int, int); + int run_spmv(int, int); + int run_towers(int, int); + int run_vvadd(int, int); } namespace { @@ -80,6 +95,13 @@ int main() { cycles.push_back(evaluate("matrix_add", 30, matrix_add, model::matrix_add)); cycles.push_back(evaluate("graph_dijkstra", 1000, graph_dijkstra, model::graph_dijkstra)); cycles.push_back(evaluate("graph_floyd_warshall", 200, graph_floyd_warshall, model::graph_floyd_warshall)); + cycles.push_back(evaluate("median", -1, run_median, model::run_median)); + cycles.push_back(evaluate("mutiply", -1, run_multiply, model::run_multiply)); + cycles.push_back(evaluate("qsort", -1, run_qsort, model::run_qsort)); + cycles.push_back(evaluate("rsort", -1, run_rsort, model::run_rsort)); + cycles.push_back(evaluate("spmv", -1, run_spmv, model::run_spmv)); + cycles.push_back(evaluate("towers", -1, run_towers, model::run_towers)); + cycles.push_back(evaluate("vvadd", -1, run_vvadd, model::run_vvadd)); } // Calculates the geometric mean. diff --git a/bench/median.c b/bench/median.c new file mode 100644 index 0000000..173b5d5 --- /dev/null +++ b/bench/median.c @@ -0,0 +1,70 @@ +//************************************************************************** +// Median filter bencmark +//-------------------------------------------------------------------------- +// +// This benchmark performs a 1D three element median filter. + +int input_median[400]; +int results_median[400]; + +void median_data_init(int nonce) { + int i; + int x = nonce; + + for (i = 0; i < 400; i++) { + x = (x * 97 + 17) % 1000; + input_median[i] = x; + } +} + +void median(int n, int input[400], int results[400]) { + int A, B, C, i; + + // Zero the ends + results[0] = 0; + results[n - 1] = 0; + + // Do the filter + for (i = 1; i < (n - 1); i++) { + A = input[i - 1]; + B = input[i]; + C = input[i + 1]; + + if (A < B) { + if (B < C) + results[i] = B; + else if (C < A) + results[i] = A; + else + results[i] = C; + } + + else { + if (A < C) + results[i] = A; + else if (C < B) + results[i] = B; + else + results[i] = C; + } + } +} + +int verify_median(int n, int* test) { + int i; + int result = 0; + + for (i = 0; i < n; i++) { + int v = test[i]; + result += v; + } + + return result; +} + +int run_median(int dummy_0, int nonce) { + median_data_init(nonce); + median(400, input_median, results_median); + + return verify_median(400, results_median); +} diff --git a/bench/multiply.c b/bench/multiply.c new file mode 100644 index 0000000..9ef782f --- /dev/null +++ b/bench/multiply.c @@ -0,0 +1,65 @@ +// ************************************************************************* +// multiply filter bencmark +// ------------------------------------------------------------------------- +// +// This benchmark tests the software multiply implemenation. + +int input1_multiply[100]; +int input2_multiply[100]; +int results_multiply[100]; + +void multiply_data_init(int nonce) { + int i; + int x = nonce; + int y = nonce; + + for (i = 0; i < 100; i++) { + x = (x * 97 + 17) % 10009; + y = (y * 17 + 23) % 10007; + input1_multiply[i] = x; + input2_multiply[i] = y; + } +} + +int multiply(int x, int y) { + int i; + int result = 0; + + for (i = 0; i < 32; i++) { + if ((x & 0x1) == 1) + result = result + y; + + x = x >> 1; + y = y << 1; + } + + return result; +} + +int verify_multiply(int n, int* test) { + int i; + int result = 0; + + for (i = 0; i < n; i++) { + int t0 = input1_multiply[i]; + int t1 = input2_multiply[i]; + int v = results_multiply[i]; + if (t0 * t1 != v) + return 1; + + result += v; + } + + return result; +} + +int run_multiply(int dummy_0, int nonce) { + int i; + + multiply_data_init(nonce); + for (i = 0; i < 100; i++) { + results_multiply[i] = multiply(input1_multiply[i], input2_multiply[i]); + } + + return verify_multiply(100, results_multiply); +} diff --git a/bench/qsort.c b/bench/qsort.c new file mode 100644 index 0000000..956feaa --- /dev/null +++ b/bench/qsort.c @@ -0,0 +1,129 @@ +//************************************************************************** +// Quicksort benchmark +//-------------------------------------------------------------------------- +// +// This benchmark uses quicksort to sort an array of integers. The +// implementation is largely adapted from Numerical Recipes for C. + +int input_qsort_data[16384]; + +void qsort_data_init(int nonce) { + int i; + int x = nonce; + + for (i = 0; i < 16384; i++) { + x = (x * 97 + 17) % 100000009; + input_qsort_data[i] = x; + } +} + +void swap(int* a, int* b) { + int temp = *a; + *a = *b; + *b = temp; +} + +void swap_if_greater(int* a, int* b) { + if (*a > *b) + swap(a, b); +} + +void insertion_sort(int n, int* arr) { + int i, j; + int value; + for (i = 1; i < n; i++) { + value = arr[i]; + j = i; + while (value < arr[j - 1]) { + arr[j] = arr[j - 1]; + if (--j == 0) + break; + } + arr[j] = value; + } +} + +void qsort(int n, int arr[16384]) { + int ir = n; + int l = 1; + int stack[50]; + int stackp = 0; + + for (;;) { + // Insertion sort when subarray small enough. + if (ir - l < 10) { + insertion_sort(ir - l + 1, &arr[l - 1]); + + if (stackp == 0) + break; + + // Pop stack and begin a new round of partitioning. + ir = stack[stackp--]; + l = stack[stackp--]; + } else { + // Choose median of left, center, and right elements as + // partitioning element a. Also rearrange so that a[l-1] <= a[l] <= a[ir-]. + swap(&arr[(l + ir) / 2 - 1], &arr[l]); + swap_if_greater(&arr[l - 1], &arr[ir - 1]); + swap_if_greater(&arr[l], &arr[ir - 1]); + swap_if_greater(&arr[l - 1], &arr[l]); + + // Initialize pointers for partitioning. + int i = l + 1; + int j = ir; + + // Partitioning element. + int a = arr[l]; + + for (;;) { // Beginning of innermost loop. + while (arr[i++] < a) + ; // Scan up to find element > a. + while (arr[(j-- - 2)] > a) + ; // Scan down to find element < a. + if (j < i) + break; // Pointers crossed. Partitioning complete. + swap(&arr[i - 1], &arr[j - 1]); // Exchange elements. + } // End of innermost loop. + + // Insert partitioning element. + arr[l] = arr[j - 1]; + arr[j - 1] = a; + stackp += 2; + + // Push pointers to larger subarray on stack, + // process smaller subarray immediately. + + if (ir - i + 1 >= j - l) { + stack[stackp] = ir; + stack[stackp - 1] = i; + ir = j - 1; + } else { + stack[stackp] = j - 1; + stack[stackp - 1] = l; + l = i; + } + } + } +} + +int verify_qsort(int n, int* test) { + int i; + int result = 0; + + for (i = 0; i < n - 1; i++) { + int t0 = test[i], t1 = test[i + 1]; + if (t0 > t1) + return 1; + + result += t0; + } + + return result; +} + +int run_qsort(int dummy_0, int nonce) { + qsort_data_init(nonce); + qsort(16384, input_qsort_data); + + return verify_qsort(16384, input_qsort_data); +} diff --git a/bench/rsort.c b/bench/rsort.c new file mode 100644 index 0000000..737d924 --- /dev/null +++ b/bench/rsort.c @@ -0,0 +1,117 @@ +//************************************************************************** +// Radix Sort benchmark +//-------------------------------------------------------------------------- +// +// This benchmark uses radix sort to sort an array of integers. The +// implementation is largely adapted from Numerical Recipes for C. + +int input_rsort_data[2048]; + +void rsort_data_init(int nonce) { + int i; + int x = nonce; + + for (i = 0; i < 2048; i++) { + x = (x * 97 + 17) % 10000007; + input_rsort_data[i] = x; + } +} + +int fetch_add(int* ptr, int inc) { + return (*ptr += inc) - inc; +} + +void memcpy_int(int* dest, int* src, int size) { + int i; + + for (i = 0; i < size; i++) { + dest[i] = src[i]; + } +} + +int bucket[256]; + +void rsort(int n, int* arrIn, int* scratchIn) { + int log_exp = 0; + int *arr = arrIn, *scratch = scratchIn; + int p; + int b; + + while (log_exp < 8 * sizeof(int)) { + for (b = 0; b < (1 << 8); b++) + bucket[b] = 0; + + for (p = 0; p < n - 3; p += 4) { + int a0 = arr[p + 0]; + int a1 = arr[p + 1]; + int a2 = arr[p + 2]; + int a3 = arr[p + 3]; + fetch_add(&bucket[(a0 >> log_exp) % (1 << 8)], 1); + fetch_add(&bucket[(a1 >> log_exp) % (1 << 8)], 1); + fetch_add(&bucket[(a2 >> log_exp) % (1 << 8)], 1); + fetch_add(&bucket[(a3 >> log_exp) % (1 << 8)], 1); + } + for (; p < n; p++) + bucket[(arr[p] >> log_exp) % (1 << 8)]++; + + int prev = bucket[0]; + prev += fetch_add(&bucket[1], prev); + for (b = 2; b < (1 << 8); b += 2) { + prev += fetch_add(&bucket[b + 0], prev); + prev += fetch_add(&bucket[b + 1], prev); + } + + for (p = n - 1; p >= 3; p -= 4) { + int a0 = arr[p - 0]; + int a1 = arr[p - 1]; + int a2 = arr[p - 2]; + int a3 = arr[p - 3]; + int* pb0 = &bucket[(a0 >> log_exp) % (1 << 8)]; + int* pb1 = &bucket[(a1 >> log_exp) % (1 << 8)]; + int* pb2 = &bucket[(a2 >> log_exp) % (1 << 8)]; + int* pb3 = &bucket[(a3 >> log_exp) % (1 << 8)]; + int s0 = fetch_add(pb0, -1); + int s1 = fetch_add(pb1, -1); + int s2 = fetch_add(pb2, -1); + int s3 = fetch_add(pb3, -1); + scratch[s0 - 1] = a0; + scratch[s1 - 1] = a1; + scratch[s2 - 1] = a2; + scratch[s3 - 1] = a3; + } + for (; p >= 0; p--) + scratch[--bucket[(arr[p] >> log_exp) % (1 << 8)]] = arr[p]; + + int* tmp = arr; + arr = scratch; + scratch = tmp; + + log_exp += 8; + } + if (arr != arrIn) + memcpy_int(arr, scratch, n); +} + +int verify_rsort(int n, int* test) { + int i; + int result = 0; + + for (i = 0; i < n - 1; i++) { + int t0 = test[i], t1 = test[i + 1]; + if (t0 > t1) + return 1; + + result += t0; + } + + return result; +} + +int scratch[2048]; + +int run_rsort(int dummy_0, int nonce) { + rsort_data_init(nonce); + rsort(2048, input_rsort_data, scratch); + + return verify_rsort(2048, input_rsort_data); +} diff --git a/bench/spmv.c b/bench/spmv.c new file mode 100644 index 0000000..6179bf3 --- /dev/null +++ b/bench/spmv.c @@ -0,0 +1,90 @@ +//************************************************************************** +// Double-precision sparse matrix-vector multiplication benchmark +//-------------------------------------------------------------------------- + +double val[2399]; +int idx[2399]; + +double x[500]; +int ptr[501] = { + 0, 4, 8, 10, 15, 22, 29, 33, 34, 36, 39, 44, 44, 47, 55, 61, 66, 68, 75, 82, 86, 91, 98, 104, 109, 113, 126, 131, 134, + 136, 143, 153, 159, 168, 170, 174, 176, 180, 187, 192, 198, 200, 204, 211, 213, 222, 225, 228, 233, 241, 247, 253, 256, + 262, 264, 270, 274, 277, 283, 288, 294, 301, 307, 312, 315, 319, 325, 329, 332, 338, 340, 342, 348, 353, 359, 362, 366, + 368, 374, 387, 393, 400, 403, 406, 412, 420, 425, 428, 433, 441, 442, 448, 456, 462, 468, 469, 477, 479, 485, 490, 495, + 501, 508, 513, 518, 524, 532, 535, 538, 542, 546, 552, 561, 563, 567, 571, 574, 576, 581, 584, 588, 592, 593, 597, 599, + 607, 612, 615, 619, 626, 633, 640, 646, 650, 653, 659, 665, 670, 673, 678, 685, 691, 697, 703, 708, 712, 717, 719, 722, + 725, 732, 736, 738, 742, 747, 753, 757, 763, 767, 769, 769, 777, 780, 784, 790, 797, 807, 810, 813, 815, 817, 822, 829, + 830, 835, 844, 848, 851, 854, 862, 864, 873, 876, 881, 884, 888, 895, 899, 901, 904, 908, 912, 919, 927, 931, 937, 941, + 944, 948, 950, 955, 960, 963, 970, 975, 979, 983, 985, 992, 993, 998, 1001, 1008, 1012, 1014, 1018, 1023, 1030, 1036, + 1040, 1045, 1052, 1058, 1061, 1066, 1069, 1071, 1077, 1080, 1084, 1087, 1090, 1092, 1095, 1100, 1102, 1110, 1117, 1122, + 1130, 1133, 1138, 1142, 1144, 1146, 1153, 1158, 1160, 1167, 1172, 1176, 1179, 1183, 1188, 1191, 1193, 1196, 1204, 1210, + 1216, 1219, 1221, 1225, 1229, 1234, 1236, 1239, 1244, 1248, 1253, 1256, 1264, 1268, 1271, 1272, 1275, 1278, 1284, 1287, + 1291, 1296, 1300, 1304, 1306, 1313, 1317, 1322, 1326, 1332, 1336, 1344, 1349, 1356, 1363, 1368, 1369, 1378, 1381, 1385, + 1388, 1395, 1399, 1407, 1414, 1422, 1425, 1433, 1435, 1438, 1439, 1445, 1448, 1450, 1453, 1456, 1470, 1472, 1475, 1481, + 1487, 1491, 1494, 1497, 1498, 1503, 1507, 1513, 1517, 1524, 1529, 1534, 1542, 1547, 1550, 1550, 1552, 1553, 1556, 1559, + 1563, 1571, 1577, 1580, 1585, 1590, 1594, 1598, 1600, 1602, 1610, 1615, 1620, 1628, 1634, 1637, 1649, 1652, 1656, 1662, + 1664, 1670, 1674, 1678, 1687, 1697, 1704, 1709, 1715, 1720, 1725, 1728, 1736, 1740, 1747, 1750, 1754, 1760, 1763, 1765, + 1773, 1781, 1783, 1788, 1795, 1802, 1810, 1815, 1820, 1824, 1829, 1836, 1839, 1843, 1847, 1849, 1854, 1859, 1863, 1873, + 1880, 1882, 1891, 1895, 1899, 1904, 1909, 1914, 1919, 1923, 1927, 1932, 1938, 1943, 1949, 1954, 1960, 1965, 1968, 1974, + 1980, 1983, 1990, 1992, 1995, 2002, 2011, 2017, 2024, 2028, 2035, 2037, 2048, 2055, 2063, 2067, 2069, 2078, 2081, 2085, + 2086, 2090, 2097, 2101, 2107, 2110, 2112, 2116, 2119, 2122, 2129, 2136, 2143, 2146, 2156, 2162, 2171, 2175, 2179, 2186, + 2189, 2194, 2198, 2206, 2211, 2215, 2222, 2228, 2237, 2241, 2245, 2256, 2259, 2269, 2272, 2275, 2278, 2279, 2281, 2287, + 2292, 2297, 2304, 2311, 2316, 2319, 2322, 2327, 2333, 2340, 2343, 2345, 2350, 2358, 2365, 2365, 2368, 2373, 2379, 2388, + 2394, 2399}; + +void spmv_init(int nonce) { + int i; + int t1 = nonce; + int t2 = nonce; + + for (i = 0; i < 2399; i++) { + t1 = (t1 * 97 + 17) % 1000; + t2 = (t2 * 17 + 23) % 500; + val[i] = (double) t1; + idx[i] = t2; + } + + for (i = 0; i < 500; i++) { + t1 = (t1 * 17 + 23) % 1000; + x[i] = (double) t1; + } +} + +void spmv(int r, double* val, int* idx, double* x, int* ptr, double* y) { + int i; + + for (i = 0; i < r; i++) { + int k; + double yi0 = 0, yi1 = 0, yi2 = 0, yi3 = 0; + for (k = ptr[i]; k < ptr[i + 1] - 3; k += 4) { + yi0 += val[k + 0] * x[idx[k + 0]]; + yi1 += val[k + 1] * x[idx[k + 1]]; + yi2 += val[k + 2] * x[idx[k + 2]]; + yi3 += val[k + 3] * x[idx[k + 3]]; + } + for (; k < ptr[i + 1]; k++) { + yi0 += val[k] * x[idx[k]]; + } + y[i] = (yi0 + yi1) + (yi2 + yi3); + } +} + +int verifyDouble(int n, double* test) { + int i; + int result = 0; + + for (i = 0; i < n; i++) { + result += (int) (test[i]); + } + + return result; +} + +double y[500]; + +int run_spmv(int dummy_0, int nonce) { + spmv_init(nonce); + spmv(500, val, idx, x, ptr, y); + + return verifyDouble(500, y); +} diff --git a/bench/towers.c b/bench/towers.c new file mode 100644 index 0000000..9a97a19 --- /dev/null +++ b/bench/towers.c @@ -0,0 +1,193 @@ +//************************************************************************** +// Towers of Hanoi benchmark +//-------------------------------------------------------------------------- +// +// Towers of Hanoi is a classic puzzle problem. The game consists of +// three pegs and a set of discs. Each disc is a different size, and +// initially all of the discs are on the left most peg with the smallest +// disc on top and the largest disc on the bottom. The goal is to move all +// of the discs onto the right most peg. The catch is that you are only +// allowed to move one disc at a time and you can never place a larger +// disc on top of a smaller disc. +// +// This implementation starts with NUM_DISC discs and uses a recursive +// algorithm to solve the puzzle. + +struct Node { + int val; + struct Node* next; +}; + +struct List { + int size; + struct Node* head; +}; + +struct List g_nodeFreeList; +struct Node g_nodePool[7]; + +int list_getSize(struct List* list) { + return list->size; +} + +void list_init(struct List* list) { + list->size = 0; + list->head = 0; +} + +void list_push(struct List* list, int val) { + struct Node* newNode; + + // Pop the next free node off the free list + newNode = g_nodeFreeList.head; + g_nodeFreeList.head = g_nodeFreeList.head->next; + + // Push the new node onto the given list + newNode->next = list->head; + list->head = newNode; + + // Assign the value + list->head->val = val; + + // Increment size + list->size++; +} + +int list_pop(struct List* list) { + struct Node* freedNode; + int val; + + // Get the value from the->head of given list + val = list->head->val; + + // Pop the head node off the given list + freedNode = list->head; + list->head = list->head->next; + + // Push the freed node onto the free list + freedNode->next = g_nodeFreeList.head; + g_nodeFreeList.head = freedNode; + + // Decrement size + list->size--; + + return val; +} + +void list_clear(struct List* list) { + while (list_getSize(list) > 0) + list_pop(list); +} + +//-------------------------------------------------------------------------- +// Tower data structure and functions + +struct Towers { + int numDiscs; + int numMoves; + struct List pegA; + struct List pegB; + struct List pegC; +}; + +void towers_init(struct Towers* towers, int n, int nonce) { + int i; + + towers->numDiscs = n; + towers->numMoves = 0; + + list_init(&(towers->pegA)); + list_init(&(towers->pegB)); + list_init(&(towers->pegC)); + + for (i = 0; i < n; i++) + list_push(&(towers->pegA), nonce * (n - i)); +} + +void towers_clear(struct Towers* towers, int nonce) { + list_clear(&(towers->pegA)); + list_clear(&(towers->pegB)); + list_clear(&(towers->pegC)); + + towers_init(towers, towers->numDiscs, nonce); +} + +void towers_solve_h(struct Towers* towers, int n, struct List* startPeg, struct List* tempPeg, struct List* destPeg) { + int val; + + if (n == 1) { + val = list_pop(startPeg); + list_push(destPeg, val); + towers->numMoves++; + } else { + towers_solve_h(towers, n - 1, startPeg, destPeg, tempPeg); + towers_solve_h(towers, 1, startPeg, tempPeg, destPeg); + towers_solve_h(towers, n - 1, tempPeg, startPeg, destPeg); + } +} + +void towers_solve(struct Towers* towers) { + towers_solve_h(towers, towers->numDiscs, &(towers->pegA), &(towers->pegB), &(towers->pegC)); +} + +int towers_verify(struct Towers* towers, int nonce) { + struct Node* ptr; + int numDiscs = 0; + int result = 0; + + if (list_getSize(&towers->pegA) != 0) { + return 2; + } + + if (list_getSize(&towers->pegB) != 0) { + return 3; + } + + if (list_getSize(&towers->pegC) != towers->numDiscs) { + return 4; + } + + for (ptr = towers->pegC.head; ptr != 0; ptr = ptr->next) { + numDiscs++; + if (ptr->val != nonce * numDiscs) { + return 5; + } + result += ptr->val; + } + + if (towers->numMoves != ((1 << towers->numDiscs) - 1)) { + return 6; + } + + return 0; +} + +//-------------------------------------------------------------------------- +// Main + +int run_towers(int dummy_0, int nonce) { + struct Towers towers; + int i; + + // Initialize free list + + list_init(&g_nodeFreeList); + g_nodeFreeList.head = &(g_nodePool[0]); + g_nodeFreeList.size = 7; + g_nodePool[7 - 1].next = 0; + g_nodePool[7 - 1].val = 99; + for (i = 0; i < (7 - 1); i++) { + g_nodePool[i].next = &(g_nodePool[i + 1]); + g_nodePool[i].val = nonce * i; + } + + towers_init(&towers, 7, nonce); + + // Solve it + + towers_clear(&towers, nonce); + towers_solve(&towers); + + // Check the results + return towers_verify(&towers, nonce); +} diff --git a/bench/vvadd.c b/bench/vvadd.c new file mode 100644 index 0000000..adb0b3b --- /dev/null +++ b/bench/vvadd.c @@ -0,0 +1,48 @@ +//************************************************************************** +// Vector-vector add benchmark +//-------------------------------------------------------------------------- +// +// This benchmark uses adds to vectors and writes the results to a +// third vector. + +int input1_vvadd[1000]; +int input2_vvadd[1000]; +int results_vvadd[1000]; + +void vvadd_init(int nonce) { + int i; + int x = nonce; + int y = nonce; + + for (i = 0; i < 1000; i++) { + x = (x * 97 + 17) % 1009; + y = (x * 17 + 23) % 1007; + input1_vvadd[i] = x; + input2_vvadd[i] = y; + } +} + +void vvadd(int n, int a[1000], int b[1000], int c[1000]) { + int i; + + for (i = 0; i < n; i++) + c[i] = a[i] + b[i]; +} + +int verify_vvadd(int n, int* test) { + int i; + int result = 0; + + for (i = 0; i < n; i++) { + int v = test[i]; + result += v; + } + + return result; +} + +int run_vvadd(int dummy_0, int nonce) { + vvadd_init(nonce); + vvadd(1000, input1_vvadd, input2_vvadd, results_vvadd); + return verify_vvadd(1000, results_vvadd); +}