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.