summaryrefslogtreecommitdiff
path: root/src/benchmark.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/benchmark.c')
-rw-r--r--src/benchmark.c162
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';