[Risolto] Magagna incomprensibile (per me) C++/Makefiles
Ciao,
sto facendo un progettino in C++ è ho una magagna veramente strana. Allora sto realizzando una piccola libreria di calcolo SEM e ho creato una cartella con una serie di test e uno script che li esegue in successione e dovrebbe matchare i risultati ottenuti con dei valori di riferimento. Nel Makefile ho inserito un target check che non fa altro che lanciare tale script controllando che i file siano stati già compilati (altrimenti chiama il target di compilazione).
La cosa incredibile è che lo stesso identico codice mi calcola valori completamente diversi a seconda che io lanci lo script dal make o "a mano". Questo avviene sotto Linux, ma non sotto OS-X dove il risultato è indipendente da come ho lanciato il codice... Io non ho proprio idea del perché... su entrambi uso GNU/make, ma la versione sotto MAC è la 3.80 (ovviamente la Apple se non usa librerie ultra-antiquate...), mentre sotto Linux ho la 3.81 che veniva con Gentoo (con tutto il patchset di Gentoo).
Boh di seguito allego i file in gioco... l'intera libreria no perché sarebbe troppo.
Ecco lo script "regtest.sh", per ora non fa praticamente nulla:
Qui abbiamo il Makefile:
e qui il config.mk per Linux (è un symlink a config.mk.linux).
quello per mac è analogo, cambiano le posizioni delle librerie...
Infine il sorgente del test che si comporta in maniera così bizzarra:
Se qualcuno ha una qualche, anche vaghissima, idea di quale potrebbe essere la causa...
sto facendo un progettino in C++ è ho una magagna veramente strana. Allora sto realizzando una piccola libreria di calcolo SEM e ho creato una cartella con una serie di test e uno script che li esegue in successione e dovrebbe matchare i risultati ottenuti con dei valori di riferimento. Nel Makefile ho inserito un target check che non fa altro che lanciare tale script controllando che i file siano stati già compilati (altrimenti chiama il target di compilazione).
La cosa incredibile è che lo stesso identico codice mi calcola valori completamente diversi a seconda che io lanci lo script dal make o "a mano". Questo avviene sotto Linux, ma non sotto OS-X dove il risultato è indipendente da come ho lanciato il codice... Io non ho proprio idea del perché... su entrambi uso GNU/make, ma la versione sotto MAC è la 3.80 (ovviamente la Apple se non usa librerie ultra-antiquate...), mentre sotto Linux ho la 3.81 che veniva con Gentoo (con tutto il patchset di Gentoo).
Boh di seguito allego i file in gioco... l'intera libreria no perché sarebbe troppo.
Ecco lo script "regtest.sh", per ora non fa praticamente nulla:
#!/bin/bash TESTS="integration polytest" function die { echo "\$@" exit 1 } for i in \${TESTS}; do ./\$i || die "\$i test failed". done
Qui abbiamo il Makefile:
# User defined flags: include config.mk LIBDIR = ./lib LIBNAME = spectral LIB = \$(LIBDIR)/lib\$(LIBNAME).a M_CPPFLAGS = \$(CPPFLAGS) \ \$(HUMFPACK) \ \$(HBOOST) \ -I./src \ -DMPICH_IGNORE_CXX_SEEK M_CXXFLAGS = \$(CXXFLAGS) M_LDFLAGS = -L\$(LIBDIR) -l\$(LIBNAME) \ \$(LDFLAGS) \ \$(LAMD) \ \$(LUMFPACK) HDRSOBJ = src/adptproblem.hpp \ src/domain.hpp \ src/elementbase.hpp \ src/extdata.hpp \ src/integrator.hpp \ src/fem-mesh.hpp \ src/fem-integrator.hpp \ src/fem-solver.hpp \ src/functions.hpp \ src/mesh.hpp \ src/poly.hpp \ src/problem.hpp \ src/subproblem.hpp \ src/triangle.hpp HDRSNOOBJ = src/fem-base.hpp \ src/mapping.hpp \ src/point.hpp \ src/spectral \ src/typedefs.hpp TESTFILES = test/integration.cpp \ test/polytest.cpp HDRS = \$(HDRSOBJ) \ \$(HDRSNOOBJ) SRCS = \$(HDRSOBJ:.hpp=.cpp) OBJS = \$(SRCS:.cpp=.o) TESTOBJS = \$(TESTFILES:.cpp=.o) TESTEXECS = \$(TESTFILES:.cpp=) all : \$(HDRS) \$(LIB) clean : -\rm \$(OBJS) -\rm \$(LIB) -\rm \$(MAIN:.cpp=.o) -\rm \$(EXEC) -\rm \$(TESTOBJS) -\rm \$(TESTEXECS) -\cd doc && rm -rf html latex doc : Doxyfile \$(SRCS) \$(HDRS) doxygen Doxyfile cd doc/latex && \$(MAKE) lib : \$(LIB) check : test cd test && ./regtest.sh test : \$(LIB) \$(TESTOBJS) \$(TESTEXECS) install : \$(LIB) \$(HDRS) doc mkdir -p \$(DESTDIR)/lib mkdir -p \$(DESTDIR)/share/doc mkdir -p \$(DESTDIR)/include/mpi-spectral \install -m 644 \$(HDRS) \$(DESTDIR)/include/mpi-spectral \install -m 644 \$(LIB) \$(DESTDIR)/lib cp -R doc/latex doc/html \$(DESTDIR)/share/doc \$(LIB) : \$(OBJS) \$(HDRS) ar ru \$(LIB) \$(OBJS) \$(OBJS) : %.o: %.cpp \$(CXX) -c \$(M_CPPFLAGS) \$(M_CXXFLAGS) \$< -o \$@ \$(TESTOBJS) : %.o: %.cpp \$(CXX) -c \$(M_CPPFLAGS) \$(M_CXXFLAGS) \$< -o \$@ \$(TESTEXECS) : % : %.o \$(CXX) \$< \$(M_LDFLAGS) -o \$@ \$(STRIP) \$@
e qui il config.mk per Linux (è un symlink a config.mk.linux).
# User defined flags # =================================================================== # Basic Options # =================================================================== # ------------------------------------------------------------------- # C++ Compiler # ------------------------------------------------------------------- CXX = g++ # MPICH2: #CXX = mpicxx # Other MPI2 implementations like OpenMPI (not tested!) #CXX = mpiCC # ------------------------------------------------------------------- # Stripping options # ------------------------------------------------------------------- # Don't strip, just touch... :) STRIP = touch # Strip to remove all symbols #STRIP = strip # ------------------------------------------------------------------- # C++ preprocessor options # ------------------------------------------------------------------- # Standard CPPFLAGS = # Don't Debug #CPPFLAGS = -DNDEBUG # ------------------------------------------------------------------- # C++ compiler options # ------------------------------------------------------------------- # Debug CXXFLAGS = -Wall -g -p # Optimization: #CXXFLAGS = -O3 -Wall -march=prescott -pipe # Unsafe optimization: #CXXFLAGS = -O3 -march=nocona -pipe -ffast-math # ------------------------------------------------------------------- # C++ linker options # ------------------------------------------------------------------- LDFLAGS = # ------------------------------------------------------------------- # Install directory # ------------------------------------------------------------------- DESTDIR = /usr/local # =================================================================== # External Libraries # =================================================================== # ------------------------------------------------------------------- # AMD Library linker instruction # ------------------------------------------------------------------- LAMD = -lamd # ------------------------------------------------------------------- # UMFPACK Library linker instruction # ------------------------------------------------------------------- LUMFPACK = -lumfpack # =================================================================== # External Headers # =================================================================== # ------------------------------------------------------------------- # UMFPACK Headers: # ------------------------------------------------------------------- HUMFPACK = -I/usr/include/umfpack # ------------------------------------------------------------------- # BOOST Headers: # ------------------------------------------------------------------- HBOOST = -I/usr/include/boost # vim: set ft=make :
quello per mac è analogo, cambiano le posizioni delle librerie...
Infine il sorgente del test che si comporta in maniera così bizzarra:
/* MPI-spectral lib. solves elliptic problems using two level Schwartz domain decomposition method for SEM. Copyright (C) 2007, Proverbio Alessandro and Radice David This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ # include<cassert> # include<cmath> # include<cstdlib> # include<iostream> # include<spectral> # ifndef EPSILON # undef EPSILON # endif # ifndef EPSILON2 # undef EPSILON2 # endif # define EPSILON 1e-16 # define EPSILON2 1e-7 using namespace std; using namespace spectral; int compare(const void * a, const void * b) { double x( *(double*)a - *(double*)b ); return (x<0)?(-1):(1); }; struct Constant { double operator()(double x,double y) const {return 1.0;} }; int main() { cout << "--------------------------------------------------------------\n"; cout << " integrator.cpp " << endl; cout << "--------------------------------------------------------------\n"; // ================================================ // Controllo generazione L10 // ================================================ Poly L(10); legendre(L); cout << "L10(x) = " << L << endl; // Coefficienti tabulati double coefficienti[] = { 46189.0/256.0 , - 109395.0/256.0 , 90090.0/256.0 , - 30030.0/256.0 , 3465.0/256.0 , - 63.0/256.0 }; for(int i=0;i<=5;++i) { assert(abs(L[10-2*i]-coefficienti[i])<EPSILON); }; for(int i=0;i<5;++i) { assert(abs(L[2*i+1])<EPSILON); }; // ================================================ // Controllo zeri di L10 // ================================================ double * roots; horner(L,1e-15,1e-15,roots); qsort(roots,10,sizeof(double),&(compare)); cout << endl << "roots: " << endl; for(int i=0;i<10;++i) { cout << roots[i] << endl; } for(int i=0;i<5;++i) { assert(abs(roots[i]+roots[9-i])<EPSILON2); } // Zeri tabulati double zeri[] = { 0.148874338 , 0.433395394 , 0.679409568 , 0.865063366 , 0.973906528 }; for(int i=0;i<5;++i) { assert(abs(roots[i+5]-zeri[i])<EPSILON2); } // ================================================ // Controllo zeri di dL // ================================================ L.setdegree(9); legendre(L); Poly dL(L.differentiate()); cout << endl; cout << "L(x) = " << L << endl; cout << "dL(x) = " << dL << endl; cout << "Roots: " << endl; horner(dL,1e-10,1e-10,roots,(int)1e6); qsort(roots,8,sizeof(double),&(compare)); for(int i=0;i<8;++i) { cout << roots[i] << "\t"; cout << "L(" << roots[i] << ")=" << L(roots[i]) << "\t \t"; cout << "dL(" << roots[i] << ")=" << dL(roots[i]) << endl; } cout << "L(1)=" << L(1.0) << endl; cout << "L(-1)=" << L(-1.0) << endl; for(int i=0;i<8;++i) { assert(abs(dL(roots[i]))<EPSILON2); assert(abs(L(roots[i]))>EPSILON2); } // ================================================ // Controllo Integrazione costante // ================================================ Integrator Int(10,1e-16,1e-16,(int)1e4); cout << endl; Point<double> A(-1.0,-1.0); Point<double> B(1.0,1.0); Constant c; cout << Int(c,A,B) << endl; // assert(abs(Int(c,A,B)-4)<EPSILON2); }
Se qualcuno ha una qualche, anche vaghissima, idea di quale potrebbe essere la causa...
Risposte
Risolto... era una mancata inizializzazione di un vettore che creava strani problemi. Il make non c'entrava nulla, semplicemente leggeva dati spazzatura dalla memoria.