Intro ==== Yesterday I posted [this question](https://codereview.stackexchange.com/q/107621/84610). Since then, I've updated my code to incorporate [these](https://codereview.stackexchange.com/a/107726/84610) suggestions. I've also removed the dependence on C++11. Finally, I've made the following changes that get me closer to my overall goal: * Rather than iterate over different values for `dt` within my script, I have `dt` specified on the command line. Specifically, an integer is specified on the command line that corresponds to (1 +) an index in `dt_array`. This allows me to process different values of `dt` in parallel using the Sun Grid Engine. * Rather than use a single value for `I_syn_bar`, I now iterate over 100 values of `I_syn_bar`. If you read through the current state of my script below, you'll see that I'm writing to disk 100 text files per `dt`. When I set `n_x` to 2 instead of 100, the script is very fast: 6 s on my machine. But when I set `n_x` to 100, and submit the script as a job to the SGE, it takes ~1 hour to complete (more than 6 s * 50). Hence, there seems to be some penalty being imposed on me for the heavy file I/O I'm using (in addition to the general SGE overhead). **My goal now is to change the code so that I'm writing the data for all 100 values of `I_syn_bar`, but in fewer files.** I have a 2D matrix for each value of `I_syn_bar`. In order to write data for multiple values of `I_syn_bar` to the same text file, I need a 3D object of some kind (and a strategy for writing this object to file). Another constraint I have is that I need these files to be able to be read into Python. Code === #include <math.h> #include <vector> #include <string> #include <fstream> #include <iostream> #include <iterator> #include <Eigen/Dense> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <stdlib.h> #include <sstream> using Eigen::MatrixXd; using Eigen::ArrayXd; bool save_mat(const MatrixXd& pdata, const std::stringstream& file_path) { std::ofstream os(file_path.str().c_str()); if (!os.is_open()) { std::cout << "Failure!" << std::endl; return false; } os.precision(11); const int n_rows = pdata.rows(); const int n_cols = pdata.cols(); for (int i = 0; i < n_rows; i++) { for (int j = 0; j < n_cols; j++) { os << pdata(i, j); if (j + 1 == n_cols) { os << std::endl; } else { os << ","; } } } os.close(); return true; } std::string get_save_file() { std::string dan_dir; struct stat statbuf; if (stat("/home/daniel", &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) { dan_dir = "/home/daniel/Science"; } else if (stat("/home/dan", &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) { dan_dir = "/home/dan/Science"; } else if (stat("/home/despo", &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) { dan_dir = "/home/despo/dbliss"; } std::string save_file = "/dopa_net/results/hansel/test/test_hansel"; save_file = dan_dir + save_file; return save_file; } double f(const double t, const double tau_1, const double tau_2) { return tau_2 / (tau_1 - tau_2) * (exp(-t / tau_1) - exp(-t / tau_2)); } ArrayXd set_initial_V(const double tau, const double g_L, const double I_0, const double theta, const double V_L, const int N, const double c) { const double T = -tau * log(1 - g_L / I_0 * (theta - V_L)); ArrayXd V(N); for (int i = 0; i < N; i++) { V(i) = V_L + I_0 / g_L * (1 - exp(-c * (i - 1) / N * T / tau)); } return V; } int main(int argc, char *argv[]) { // Declare variables set inside loops below. double t; double I_syn_bar; int i; std::stringstream complete_save_file; // Declare and initialize constant parameters. const int n_x = 100; const double x_min = 0; // uA / cm^2. const double x_max = 1; // uA / cm^2. const double x_step = (x_max - x_min) / (n_x - 1); // uA / cm^2. const double tau_1 = 3.0; // ms. const double tau_2 = 1.0; // ms. const int N = 128; const double dt_array[3] = {0.25, 0.1, 0.01}; // ms. const char* task_id = argv[argc - 1]; const int task_id_int = task_id[0] - '0'; const double dt = dt_array[task_id_int - 1]; const double tau = 10; // ms. const double g_L = 0.1; // mS / cm^2. const double I_0 = 2.3; // uA / cm^2. const double theta = -40; // mV. const double V_L = -60; // mV. const double c = 0.5; const double C = 1; // uF / cm^2. const int sim_t = 10000; // ms. const int n_t = sim_t / dt; const std::string save_file = get_save_file(); // Save V for each I_syn_bar, for the dt specified on the command line. for (double I_syn_bar = x_min; I_syn_bar < x_max; I_syn_bar += x_step) { MatrixXd V(N, n_t); V.col(0) = set_initial_V(tau, g_L, I_0, theta, V_L, N, c); double I_syn = 0; // uA / cm^2. ArrayXd t_spike_array = ArrayXd::Zero(N); i = 1; for (double t = dt; t < sim_t; t += dt) { ArrayXd prev_V = V.col(i - 1).array(); ArrayXd current_V = prev_V + dt * (-g_L * (prev_V - V_L) + I_syn + I_0) / C; V.col(i) = current_V; I_syn = 0; for (int j = 0; j < N; j++) { if (current_V(j) > theta) { t_spike_array(j) = t; V(j, i) = V_L; } I_syn += I_syn_bar / N * f(t - t_spike_array(j), tau_1, tau_2); } i++; } complete_save_file << save_file << dt << "_" << I_syn_bar << ".txt"; save_mat(V, complete_save_file); complete_save_file.str(""); complete_save_file.clear(); } return 0; } Timing Information ===== --------------------------------------------- | n_x | command-line arg | SGE? | Time | --------------------------------------------- | 2 | 1 | no | 6 s | --------------------------------------------- | 2 | 1 | yes | 30 s | --------------------------------------------- | 100 | 1 | no | 10 m 16 s | --------------------------------------------- | 100 | 1 | yes | 53 m 5 s | ---------------------------------------------