diff options
Diffstat (limited to 'src/benchmark.c')
| -rw-r--r-- | src/benchmark.c | 162 |
1 files changed, 91 insertions, 71 deletions
diff --git a/src/benchmark.c b/src/benchmark.c index d3427e4..b6410e3 100644 --- a/src/benchmark.c +++ b/src/benchmark.c @@ -1,12 +1,13 @@ #include "benchmark.h" #include "crossbar_generator.h" +#include "online_crossbar.h" #include "read_crossbar.h" #include "spires_interface.h" -#include "online_crossbar.h" #include <math.h> #include <plplot/plplot.h> #include <spires.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -21,8 +22,14 @@ int run_online_benchmark(const spires_reservoir_config *config, double *predictions_out) { if (!config || !reservoir || !input_series || num_timesteps == 0 || - !model_path || !subcircuit_name || !predictions_out) + config->num_neurons == 0 || config->num_inputs == 0 || + config->num_outputs == 0 || !model_path || !subcircuit_name || + !predictions_out) { return -1; + } + if (config->num_neurons > SIZE_MAX / sizeof(double)) { + return -1; + } Online_Crossbar_Config online_config = { .num_neurons = config->num_neurons, @@ -39,8 +46,9 @@ int run_online_benchmark(const spires_reservoir_config *config, Online_Crossbar *crossbar = NULL; double *state = malloc(config->num_neurons * sizeof(*state)); - if (!state) + if (!state) { return -1; + } if (spires_reservoir_reset(reservoir) != SPIRES_OK || online_crossbar_init(&online_config, reservoir, &crossbar) != 0 || online_crossbar_start(crossbar) != 0) { @@ -53,15 +61,19 @@ int run_online_benchmark(const spires_reservoir_config *config, const double *input = input_series + timestep * config->num_inputs; int output_ready = 0; - double *previous = timestep == 0 - ? NULL - : predictions_out + - (timestep - 1) * config->num_outputs; + double *previous = + timestep == 0 ? NULL + : predictions_out + + (timestep - 1) * config->num_outputs; if (spires_step(reservoir, input) != SPIRES_OK || - spires_read_reservoir_state(reservoir, state) != SPIRES_OK || + spires_read_reservoir_state(reservoir, state) != + SPIRES_OK || online_crossbar_submit(crossbar, timestep, state, previous, &output_ready) != 0 || output_ready != (timestep != 0)) { + fprintf(stderr, + "Online benchmark failed at timestep %zu\n", + timestep); free(state); online_crossbar_destroy(crossbar); return -1; @@ -69,8 +81,8 @@ int run_online_benchmark(const spires_reservoir_config *config, } int status = online_crossbar_finish( - crossbar, predictions_out + - (num_timesteps - 1) * config->num_outputs); + crossbar, + predictions_out + (num_timesteps - 1) * config->num_outputs); free(state); online_crossbar_destroy(crossbar); return status; @@ -81,26 +93,38 @@ int run_benchmark(const spires_reservoir_config *config, Reservoir_State_Matrix *state_matrix, const char *model_path, const char *subcircuit_name, double *predictions_out) { - // copy readout weights and convert to conductances + if (!config || !reservoir || !state_matrix || !state_matrix->states || + state_matrix->num_samples == 0 || state_matrix->num_features == 0 || + state_matrix->num_features != config->num_neurons || + config->num_outputs == 0 || !model_path || !subcircuit_name || + !predictions_out) { + return -1; + } + if (state_matrix->num_samples > SIZE_MAX / state_matrix->num_features || + state_matrix->num_samples * state_matrix->num_features > + SIZE_MAX / sizeof(double)) { + return -1; + } + double *initial_resistances = NULL; + double *row_voltages = NULL; + Crossbar_Output_Matrix crossbar_output = {0}; conductance_mapping mapping; + int status = -1; if (convert_weights_to_resistances( reservoir, config->num_neurons, config->num_outputs, 1000.0, 100000.0, &initial_resistances, &mapping) != 0) { - return -1; + goto cleanup; } - double *row_voltages = + row_voltages = malloc(state_matrix->num_features * state_matrix->num_samples * - sizeof(double)); + sizeof(*row_voltages)); - if (row_voltages == NULL) { - fprintf(stderr, "Failed to allocate spikes voltages"); - free(initial_resistances); - free_reservoir_state_matrix(state_matrix); - spires_reservoir_destroy(reservoir); - return -1; + if (!row_voltages) { + fprintf(stderr, "Failed to allocate row voltages\n"); + goto cleanup; } for (size_t sample = 0; sample < state_matrix->num_samples; sample++) { @@ -125,60 +149,49 @@ int run_benchmark(const spires_reservoir_config *config, .subcircuit_name = subcircuit_name, .time_step = 1e-6, .stop_time = state_matrix->num_samples * 1e-6, - .print_state_nodes = 0}; // state nodes is not acutally implemented + .print_state_nodes = 0}; if (generate_crossbar("output/crossbar.cir", &crossbar_config) < 0) { - fprintf(stderr, "failed to create crossbar config"); - free(initial_resistances); - return -1; + fprintf(stderr, "Failed to generate crossbar netlist\n"); + goto cleanup; } - printf("Generated crossbar!!"); - // call ngspice for crossbar if (run_ngspice("output/crossbar.cir") < 0) { - fprintf(stderr, "Failed to run_ngspice"); - free(initial_resistances); - return -1; + fprintf(stderr, "Failed to run ngspice\n"); + goto cleanup; } - printf("ran ngspice!!"); - - // crossbar parameters needed for reading - Crossbar_Output_Matrix crossbar_output = { - // .num_samples = state_matrix->num_samples, - // .num_outputs = config->num_outputs * 2, - .time = NULL, - .voltages = NULL}; if (read_crossbar("output/crossbar_output.dat", config->num_outputs * 2, &crossbar_output) < 0) { - fprintf(stderr, "Failed to read crossbar output file"); - free(initial_resistances); - free_crossbar_output_matrix(&crossbar_output); - return -1; + fprintf(stderr, "Failed to read crossbar output\n"); + goto cleanup; } - printf("read the crossbar outputs!!\n"); if (convert_output_to_software( config->num_neurons, config->num_outputs, state_matrix->num_samples, crossbar_output.voltages, initial_resistances, crossbar_config.load_resistance, &mapping, row_voltages, SPIKE_AMPLITUDE, predictions_out) < 0) { - fprintf(stderr, - "Failed to convert crossbar outputs back to software"); - return -1; + fprintf(stderr, "Failed to decode crossbar output\n"); + goto cleanup; } - printf("YAY IT WORKED!!! Cleaning up :)\n"); + status = 0; + +cleanup: free(initial_resistances); free(row_voltages); free_crossbar_output_matrix(&crossbar_output); - - return 0; + return status; } double calculate_MSE(const double *expected, const double *predicted, const size_t num_steps, const size_t num_outputs) { + if (!expected || !predicted || num_steps == 0 || num_outputs == 0) { + return NAN; + } + double aggregate = 0.0; for (size_t output = 0; output < num_outputs; output++) { for (size_t timestep = 0; timestep < num_steps; timestep++) { @@ -197,15 +210,11 @@ double calculate_MSE(const double *expected, const double *predicted, int plot_raster(const Reservoir_State_Matrix *matrix, const size_t neurons_to_plot, const double spike_threshold) { - if (!matrix || !matrix->states || matrix->num_samples == 0) { + if (!matrix || !matrix->states || matrix->num_samples == 0 || + matrix->num_features == 0 || neurons_to_plot == 0 || + neurons_to_plot > matrix->num_features) { return -1; } - - // if (neurons_to_plot > matrix->num_features) { - // neurons_to_plot = matrix->num_features; - // } - - // count spikes size_t spike_count = 0; for (size_t t = 0; t < matrix->num_samples; t++) { for (size_t n = 0; n < neurons_to_plot; n++) { @@ -231,7 +240,6 @@ int plot_raster(const Reservoir_State_Matrix *matrix, return -1; } - // fill spike coordinates size_t k = 0; for (size_t t = 0; t < matrix->num_samples; t++) { for (size_t n = 0; n < neurons_to_plot; n++) { @@ -293,9 +301,10 @@ int plot_reservoir_predictions(const double *expected, const double *predicted, PLFLT y_min; PLFLT y_max; - if (!expected || !predicted || num_samples == 0 || - output_to_plot >= num_outputs) + if (!expected || !predicted || !model_path || num_samples == 0 || + num_outputs == 0 || output_to_plot >= num_outputs) { return -1; + } x = malloc(num_samples * sizeof(*x)); y_expected = malloc(num_samples * sizeof(*y_expected)); @@ -320,17 +329,21 @@ int plot_reservoir_predictions(const double *expected, const double *predicted, y_expected[sample] = (PLFLT)expected[index]; y_predicted[sample] = (PLFLT)predicted[index]; - if (y_expected[sample] < y_min) + if (y_expected[sample] < y_min) { y_min = y_expected[sample]; + } - if (y_expected[sample] > y_max) + if (y_expected[sample] > y_max) { y_max = y_expected[sample]; + } - if (y_predicted[sample] < y_min) + if (y_predicted[sample] < y_min) { y_min = y_predicted[sample]; + } - if (y_predicted[sample] > y_max) + if (y_predicted[sample] > y_max) { y_max = y_predicted[sample]; + } } { @@ -338,8 +351,9 @@ int plot_reservoir_predictions(const double *expected, const double *predicted, margin = (y_max - y_min) * 0.1; - if (margin == 0.0) + if (margin == 0.0) { margin = 1.0; + } y_min -= margin; y_max += margin; @@ -347,8 +361,6 @@ int plot_reservoir_predictions(const double *expected, const double *predicted, plsdev("svg"); - // parses real model name - // written by chatGPT char filename[256]; char model_name[128]; const char *base; @@ -361,8 +373,9 @@ int plot_reservoir_predictions(const double *expected, const double *predicted, dot = strrchr(base, '.'); len = dot ? (size_t)(dot - base) : strlen(base); - if (len >= sizeof(model_name)) + if (len >= sizeof(model_name)) { len = sizeof(model_name) - 1; + } memcpy(model_name, base, len); model_name[len] = '\0'; @@ -371,6 +384,9 @@ int plot_reservoir_predictions(const double *expected, const double *predicted, "output/reservoir_prediction_%s.svg", model_name) >= (int)sizeof(filename)) { fprintf(stderr, "Output filename is too long\n"); + free(x); + free(y_expected); + free(y_predicted); return -1; } @@ -433,8 +449,9 @@ int plot_model_delta(const double *fixed, const double *model, size_t len; if (!fixed || !model || !model_path || num_samples == 0 || - output_to_plot >= num_outputs) + num_outputs == 0 || output_to_plot >= num_outputs) { return -1; + } x = malloc(num_samples * sizeof(*x)); delta = malloc(num_samples * sizeof(*delta)); @@ -453,14 +470,16 @@ int plot_model_delta(const double *fixed, const double *model, x[sample] = (PLFLT)sample; delta[sample] = (PLFLT)fabs(model[index] - fixed[index]); - abs_delta = (PLFLT)fabs(delta[sample]); + abs_delta = delta[sample]; - if (abs_delta > max_abs_delta) + if (abs_delta > max_abs_delta) { max_abs_delta = abs_delta; + } } - if (max_abs_delta == 0.0) + if (max_abs_delta == 0.0) { max_abs_delta = 1.0e-6; + } max_abs_delta *= 1.1; @@ -470,8 +489,9 @@ int plot_model_delta(const double *fixed, const double *model, dot = strrchr(base, '.'); len = dot ? (size_t)(dot - base) : strlen(base); - if (len >= sizeof(model_name)) + if (len >= sizeof(model_name)) { len = sizeof(model_name) - 1; + } memcpy(model_name, base, len); model_name[len] = '\0'; |
