Memory error in c++ (armadillo) -
i wanted solve kind of ordinary differential equation (master equation) , wrote following program in c++ of armadillo:
#include <iostream> #include <armadillo> #include <iomanip> using namespace std; using namespace arma; cx_mat tens( cx_mat a1,cx_mat a2,cx_mat a3,cx_mat a4,cx_mat a5,cx_mat a6,cx_mat a7,cx_mat a8,cx_mat a9,cx_mat a10,cx_mat a11,cx_mata12,cx_mat a13,cx_mat a14,cx_mat a15,cx_mat a16,cx_mat a17,cx_mat a18,cx_mat a19,cx_mat a20,cx_mat a21) {return kron(kron(kron(kron(kron(kron(kron(kron(kron(kron(kron(kron(kron(kron(kron(kron(kron(kron(kron(kron(a1,a2),a3),a4),a5),a6),a7),a8),a9),a10),a11),a12),a13),a14),a15),a16),a17),a18),a19),a20),a21);} cx_mat ii(2,2,fill::eye);// make 2*2 identify cx_matrix cx_mat ee = ii.col(0); // extract column vector cx_mat gg = ii.col(1); cx_mat a1 =tens(ee,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg); cx_mat a2 =tens(gg,ee,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg); cx_mat a3 =tens(gg,gg,ee,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg); cx_mat a4 =tens(gg,gg,gg,ee,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg); cx_mat a5 =tens(gg,gg,gg,gg,ee,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg); cx_mat a6 =tens(gg,gg,gg,gg,gg,ee,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg); cx_mat a7 =tens(gg,gg,gg,gg,gg,gg,ee,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg); cx_mat a8 =tens(gg,gg,gg,gg,gg,gg,gg,ee,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg); cx_mat a9 =tens(gg,gg,gg,gg,gg,gg,gg,gg,ee,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg); cx_mat a10=tens(gg,gg,gg,gg,gg,gg,gg,gg,gg,ee,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg); cx_mat a11=tens(gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,ee,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg); cx_mat a12=tens(gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,ee,gg,gg,gg,gg,gg,gg,gg,gg,gg); cx_mat a13=tens(gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,ee,gg,gg,gg,gg,gg,gg,gg,gg); cx_mat a14=tens(gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,ee,gg,gg,gg,gg,gg,gg,gg); cx_mat a15=tens(gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,ee,gg,gg,gg,gg,gg,gg); cx_mat a16=tens(gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,ee,gg,gg,gg,gg,gg); cx_mat a17=tens(gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,ee,gg,gg,gg,gg); cx_mat a18=tens(gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,ee,gg,gg,gg); cx_mat a19=tens(gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,ee,gg,gg); cx_mat a20=tens(gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,ee,gg); cx_mat a21=tens(gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,gg,ee); cx_mat sink=a21*a20.t(); cx_mat h0(cx_mat a){ return a*a.t();} cx_mat h1(cx_mat a,cx_mat b){ return a*b.t()+b*a.t();} cx_mat h00=h0(a1)+h0(a2)+h0(a3)+h0(a4)+h0(a5)+h0(a6)+h0(a7); cx_mat h11=h1(a1,a2)+h1(a1,a3)+h1(a1,a4)+h1(a1,a5)+h1(a1,a6)+h1(a1,a7)+h1(a1,a8)+h1(a1,a9)+h1(a1,a10)+h1(a1,a11)+h1(a1,a12)+h1(a1,a13)+h1(a1,a14)+h1(a1,a15)+h1(a1,a16)+h1(a1,a17)+h1(a1,a18)+h1(a1,a19)+h1(a1,a20); cx_mat h=h00+h11;//system hamiltonian cx_mat rhot(float t,cx_mat y){ return complex<double>(0, 1)*(-h*y+y*h)+0.5*(2*sink*y*sink.t()-sink.t()*sink*y-y*sink.t()*sink);}//master equation int rk4(cx_mat y,float dt,float tmax)//runge kutta 4th order {float t = 0.;cx_mat ydot1, ydot2, ydot3, ydot4; while (t < tmax) { ydot1 = rhot(t, y); ydot2 = rhot(t+0.5*dt, y+0.5*dt*ydot1); ydot3 = rhot(t+0.5*dt, y+0.5*dt*ydot2); ydot4 = rhot(t+dt, y+dt*ydot3); cout<<t<< real(a21.t()*y*a21) ; y=y+ (dt/6.0)*(ydot1 + 2.0*ydot2 + 2.0*ydot3 + ydot4); t=t+ dt; } return 0; } int main() { rk4(a1*a1.t(),0.01,40.); return 0; }
i run program typying following comment on ubuntu terminal:
g++ -std=c++0x psinkt.cpp -o ./psinkt.out -o3 -march=native -larmadillo
but encountered following memory error:
error: arma::memory::acquire(): out of memory terminate called after throwing instance of 'std::bad_alloc' what(): std::bad_alloc aborted (core dumped)
generally, there way solve such problem? if yes, please tell me key word ! need solve problem.
step 1: identify happens.
compile with
$ g++ -std=c++0x -wall -o0 -g3 psinkt.cpp -o ./psinkt.out
and debug with
$ gdb ./psinkt.out gdb> run
or use valgrind
$ yum install valgrind # or $ apt-get install valgrind $ valgrind --tool=memcheck ./psinkt.out
step 2: improve c++
i'd encourage visit book store , skim c++ books , find more readable style. current code hard penetrate , coming python c++ going introduce level of hurt - c++ language full of stupidly sharp edges , loaded hand cannons; it's c++, not :)
for example, horrible kron thing you're doing... rethink you're trying do, , things this:
cx_mat h11=h1(a1,a2)+h1(a1,a3)+h1(a1,a4)+h1(a1,a5)+h1(a1,a6)+h1(a1,a7)+h1(a1,a8)+h1(a1,a9)+h1(a1,a10)+h1(a1,a11)+h1(a1,a12)+h1(a1,a13)+h1(a1,a14)+h1(a1,a15)+h1(a1,a16)+h1(a1,a17)+h1(a1,a18)+h1(a1,a19)+h1(a1,a20);
here's bad news: you're going have write more code in c++ , use less direct paths compared how write in python. when more familiar language, idioms, etc, paths seem more obvious , natural, coming python, stuff going seem backwards.
you have provide lot more detail system, specificity cost of performance.
for example, might want consider putting "a"s std::vector
can things like:
cx_mat h11; (auto = as.begin() + 1; != as.end() - 1; ++it) { h11 += h1(a1, *it); // (a1,a2) ... (a1, a20) }
you refactor kron nesting this:
cx_mat tens(const cx_mat& background, size_t posn, const cx_mat& foreground, size_t width) { std::vector<cx_mat*> mats; mats.resize(width); std::fill(mats.begin(), mats.end(), &background); mats[posn] = &foreground; cx_mat accum = *mats[0]; (size_t = 1; < width; ++i) { accum = kron(accum, *mats[i]); } return accum; } cx_mat a1 = tens(gg, 0, ee, 21); cx_mat a2 = tens(gg, 1, ee, 21); cx_mat a3 = tens(gg, 2, ee, 21); ...
const cx_mat&
says pass value reference, don't know whether cx_mat
trivial object or whether passing value expensive (pass value requires deep copy).
or write this:
void tens(cx_mat& into, cx_mat& background, size_t posn, cx_mat& foreground, size_t width) { std::vector<cx_mat*> mats; mats.resize(width); std::fill(mats.begin(), mats.end(), &background); mats[posn] = &foreground; = *mats[0]; (size_t = 1; < width; ++i) { accum = kron(accum, *mats[i]); } } enum { width = 21 }; std::vector<mat> amats; amats.reserve(width); (size_t = 0; < width; ++i) { tens(amats[i], gg, i, ee, width); }
or use c++11 templates:
cx_mat tens(const cx_mat& lhs, const cx_mat& rhs) { return kron(lhs, rhs); } template<typename args...> cx_mat tens(const cx_mat& lhs, const cx_mat& rhs, args&&... rest) { return tens(kron(lhs, rhs), std::forward<args>(rest)...); } cx_mat a1 = tens(ee, gg, gg, gg, gg, gg, gg, gg, gg, gg, gg, gg, gg, gg, gg, gg, gg, gg, gg, gg, gg);
but that's least favorite of options. note: elipsis (...) not me leaving stuff out, that's actual c++11 variadic template syntax: see http://ideone.com/vgfmvb
i don't know above code examples solve problem or preferable in case, i'm hoping between 2 i've equipped make progress.
Comments
Post a Comment