简体   繁体   中英

C++ error code: std::bad_alloc at memory location

I am using Visual studio now and I have a question about an error message that I got.

It says 'std::bad_alloc at memory location'.

I guess this means that I don't have enough memory. I am using arrays for computation and I think the problem arises from the size of each array.

First I used stack instead of heap so I allocate every array dynamically. But still, I got the same error message.

If I reduce the size of the array, I could run this code but I need to use this with a bigger size of arrays.

If I use a better computer, can I run this code? I am not sure how to reduce the memory required to run this code.... should I use fewer arrays?

Below, I put the entire code just in case....

Thanks in advance.

include <iostream>
#include <cstdio>
#include <chrono>
#include <vector>
#include <math.h>       // power
#include <cmath>        // abs
#include <fstream>
#include <omp.h>

using namespace std;
using namespace chrono;

// Dynamically allocation with values(double)
void dallo_fn(double**** pMat, int Na, int Nd, int Ny) {
    double*** Mat = new double** [Na];
    for (int i = 0; i < Na; i++) {
        Mat[i] = new double* [Nd];
        for (int j = 0; j < Nd; j++) {
            Mat[i][j] = new double[Ny];
            fill_n(Mat[i][j], Ny, 1);
        }
    }
    *pMat = Mat;
}

// Dynamically allocation without values(double)
void dallo_fn0(double**** pMat, int Na, int Nd, int Ny) {
    double*** Mat = new double** [Na];
    for (int i = 0; i < Na; i++) {
        Mat[i] = new double* [Nd];
        for (int j = 0; j < Nd; j++) {
            Mat[i][j] = new double[Ny];
        }
    }
    *pMat = Mat;
}

// Dynamically allocation without values(int)
void dallo_fn1(int**** pMat, int Na, int Nd, int Ny) {
    int*** Mat = new int** [Na];
    for (int i = 0; i < Na; i++) {
        Mat[i] = new int* [Nd];
        for (int j = 0; j < Nd; j++) {
            Mat[i][j] = new int[Ny];
        }
    }
    *pMat = Mat;
}

// Utility function
double utility(double a, double a_f, double d, double d_f, double y, double sig, double psi, double delta, double R) {
    double C;
    C = y + a - a_f / R - (d_f - (1 - delta) * d);
    double result;
    if (C > 0) {
        result = 1 / (1 - 1 / sig) * pow(pow(C, psi) * pow(d_f, 1 - psi), (1 - 1 / sig));
    }
    else {
        result = -999999;
    }
    return result;
}


int main()
{
#if defined _OPENMP
    omp_set_num_threads(8);
#endif

    double duration;

    // Iteration Parameters
    double tol = 0.000001;
    double itmax = 200;
    double H = 15;

    // Model Parameters and utility function
    double sig = 0.75;
    double beta = 0.95;
    double psi = 0.5;
    double delta = 0.1;
    double R = 1 / beta - 0.00215;

    // =============== 2. Discretizing the state space =========================

    // Size of arrays
    const int Na = 2 * 91;
    const int Nd = 1 * 71;
    const int Ny = 3;

    // Variables for discretization of state space
    const double amin = -2;
    const double amax = 7;
    const double dmin = 0.01;
    const double dmax = 7;
    const double ymin = 0.5;
    const double ymax = 1.5;
    const double Ptrans[3] = { 0.2, 0.6, 0.2 };

    // Discretization of state space
    double ca = (amax - amin) / (Na - 1.0);
    double cd = (dmax - dmin) / (Nd - 1.0);
    double cy = (ymax - ymin) / (Ny - 1.0);

    double* A = new double[Na];
    double* Y = new double[Ny];
    double* D = new double[Nd];

    for (int i = 0; i < Na; i++) {
        A[i] = amin + i * ca;
    }
    for (int i = 0; i < Nd; i++) {
        D[i] = dmin + i * cd;
    }
    for (int i = 0; i < Ny; i++) {
        Y[i] = ymin + i * cy;
    }

    // === 3. Initial guesses, Variable initialization and Transition matrix ===

    // Initial guess for value function
    double*** V;
    dallo_fn(&V, Na, Nd, Ny);
    double*** Vnew;
    dallo_fn(&Vnew, Na, Nd, Ny);

    // Initialization of other variables
    double Val[Na][Nd];
    double Vfuture[Na][Nd];
    double** temphoward = new double* [Na];
    for (int i = 0; i < Na; i++)
    {
        temphoward[i] = new double[Nd];
    }
    
    double*** Vhoward;
    dallo_fn0(&Vhoward, Na, Nd, Ny);
    double*** tempdiff;
    dallo_fn0(&tempdiff, Na, Nd, Ny);
    int*** maxposition_a;
    dallo_fn1(&maxposition_a, Na, Nd, Ny);
    int*** maxposition_d;
    dallo_fn1(&maxposition_d, Na, Nd, Ny);

    double** mg_A_v = new double* [Na];
    for (int i = 0; i < Na; i++)
    {
        mg_A_v[i] = new double[Nd];
    }
    for (int j = 0; j < Nd; j++) {
        for (int i = 0; i < Na; i++) {
            mg_A_v[i][j] = A[i];
        }
    }

    double** mg_D_v = new double* [Na];
    for (int i = 0; i < Na; i++)
    {
        mg_D_v[i] = new double[Nd];
    }
    for (int j = 0; j < Nd; j++) {
        for (int i = 0; i < Na; i++) {
            mg_D_v[i][j] = D[j];
        }
    }

    double***** Uvec = new double**** [Na];
    for (int i = 0; i < Na; i++) {
        Uvec[i] = new double*** [Nd];
        for (int j = 0; j < Nd; j++) {
            Uvec[i][j] = new double** [Ny];
            for (int k = 0; k < Ny; k++) {
                Uvec[i][j][k] = new double* [Na];
                for (int l = 0; l < Na; l++) {
                    Uvec[i][j][k][l] = new double[Nd];
                }
            }
        }
    }

    for (int i = 0; i < Na; i++) {
        for (int j = 0; j < Nd; j++) {
            for (int k = 0; k < Ny; k++) {
                for (int l = 0; l < Na; l++) {
                    for (int m = 0; m < Nd; m++) {
                        Uvec[i][j][k][l][m] = utility(A[i], mg_A_v[l][m], D[j], mg_D_v[l][m], Y[k], sig, psi, delta, R);
                    }
                }
            }
        }
    }

    // Value function iteration
    int it;
    double dif;
    double max;
    it = 0;
    dif = 1;

    // ================ 4. Value function iteration ============================

    while (dif >= tol && it <= itmax) {
        system_clock::time_point start = system_clock::now();
        it = it + 1;
        // V = Vnew;
        for (int i = 0; i < Na; i++) {
            for (int j = 0; j < Nd; j++) {
                for (int k = 0; k < Ny; k++) {
                    V[i][j][k] = Vnew[i][j][k];
                }
            }
        }

        for (int i = 0; i < Na; i++) {
            for (int j = 0; j < Nd; j++) {
                Vfuture[i][j] = 0;
                for (int k = 0; k < Ny; k++) {
                    Vfuture[i][j] += beta * Ptrans[k] * Vnew[i][j][k]; // + beta * Ptrans[1] * Vnew[i][j][1] + beta * Ptrans[2] * Vnew[i][j][2]; // Why is this different from Vfuture[i][j] += beta * Vnew[i][j][k] * Ptrans[k]; with for k
                }
            }
        }
        #pragma omp parallel for private(Val)     
        for (int a = 0; a < Na; a++) {
            for (int b = 0; b < Nd; b++) {
                for (int c = 0; c < Ny; c++) {
                    max = -99999;
                    for (int d = 0; d < Na; d++) {
                        for (int e = 0; e < Nd; e++) {
                            Val[d][e] = Uvec[a][b][c][d][e] + Vfuture[d][e];
                            if (max < Val[d][e]) {
                                max = Val[d][e];
                                maxposition_a[a][b][c] = d;
                                maxposition_d[a][b][c] = e;
                            }
                        }
                    }
                    Vnew[a][b][c] = max;
                }
            }
        }

        // Howard improvement
        for (int h = 0; h < H; h++) {
            for (int i = 0; i < Na; i++) {
                for (int j = 0; j < Nd; j++) {
                    for (int k = 0; k < Ny; k++) {
                        Vhoward[i][j][k] = Vnew[i][j][k];
                    }
                }
            }

            for (int i = 0; i < Na; i++) {
                for (int j = 0; j < Nd; j++) {
                    for (int k = 0; k < Ny; k++) {
                        temphoward[i][j] = beta * Vhoward[maxposition_a[i][j][k]][maxposition_d[i][j][k]][0] * Ptrans[0]
                            + beta * Vhoward[maxposition_a[i][j][k]][maxposition_d[i][j][k]][1] * Ptrans[1]
                            + beta * Vhoward[maxposition_a[i][j][k]][maxposition_d[i][j][k]][2] * Ptrans[2];
                        Vnew[i][j][k] = temphoward[i][j] + Uvec[i][j][k][maxposition_a[i][j][k]][maxposition_d[i][j][k]];
                    }
                }
            }
        }


        // Calculate Diff
        dif = -100000;
        for (int i = 0; i < Na; i++) {
            for (int j = 0; j < Nd; j++) {
                for (int k = 0; k < Ny; k++) {
                    tempdiff[i][j][k] = abs(V[i][j][k] - Vnew[i][j][k]);
                    if (tempdiff[i][j][k] > dif) {
                        dif = tempdiff[i][j][k];
                    }
                }
            }
        }

        system_clock::time_point end = system_clock::now();
        std::chrono::duration<double> sec = end - start;


        cout << dif << endl;
        cout << it << endl;
        cout << sec.count() << endl;
    }

    for (int k = 0; k < Ny; k++) {
        for (int i = 0; i < Na; i++) {
            for (int j = 0; j < Nd; j++) {
                cout << Vnew[i][j][k];
            }
            cout << '\n';
        }
    }
    cout << omp_get_max_threads() << endl;

}

The code is admittedly pretty memory hungry, but works on my 8GB machine. Please make sure you are targetting x64 platform, otherwise you reach the 4GB inherent limit.

Yes, with enough memory you can run this code. I've tested it just now on my machine with 64GBs of RAM and it ran just fine.

One way to reduce the amount of memory required is to use float s instead of double s, as they take up half the size.

Moreover, as others suggested in the comments already you could represent the multidimensional structures as 1d arrays and compute the indices into the array instead of actually having nested arrays. The benefit is that you get rid of a huge number of pointers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM