Newsgroup: it.comp.lang.perl
Titolo: Out of memory: gli undef servono a qualcosa?

Ciao a tutti, ho una domanda sulla gestione della memoria del perl.
La configurazione del mio perl e' la seguente:
Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration:
  Platform:
    osname=dec_osf, osvers=5.1, archname=alpha-dec_osf
    uname='osf1 jsbach v5.1 1885 alpha '
    config_args='-ds -e -Dprefix=/utenti/giuliani/myroot -Dcc=c89 -Dccflags= 
-O5'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef 
usemultiplicity=undef
    useperlio=undef d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=define use64bitall=define uselongdouble=undef
  Compiler:
    cc='c89', ccflags ='-O5 -std -fprm d -ieee -D_INTRINSICS 
-I/usr/local/include -DLANGUAGE_C',
    optimize='-O4',
    cppflags='-O5 -std -ieee -D_INTRINSICS -I/usr/local/include 
-DLANGUAGE_C'
    ccversion='V6.4-014', gccversion='', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', 
lseeksize=8
    alignbytes=8, usemymalloc=y, prototype=define
  Linker and Libraries:
    ld='ld', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc 
/usr/lib /var/shlib
    libs=-ldbm -ldb -lm -liconv -lutil
    perllibs=-lm -liconv -lutil
    libc=/usr/shlib/libc.so, so=so, useshrplib=true, libperl=libperl.so
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='  
-Wl,-rpath,/utenti/giuliani/myroot/lib/perl5/5.6.1/alpha-dec_osf/CORE'
    cccdlflags=' ', lddlflags='-shared -expect_unresolved "*" -O4 -msym -std 
-s -L/usr/local/lib'
Characteristics of this binary (from libperl):
  Compile-time options: USE_64_BIT_INT USE_64_BIT_ALL USE_LARGE_FILES
  Built under dec_osf
  Compiled at Mar 20 2002 11:36:36
  @INC:
    /d61/giuliani/myroot/lib/perl5/5.6.1/alpha-dec_osf
    /d61/giuliani/myroot/lib/perl5/5.6.1
    /d61/giuliani/myroot/lib/perl5/site_perl/5.6.1/alpha-dec_osf
    /d61/giuliani/myroot/lib/perl5/site_perl/5.6.1
    /d61/giuliani/myroot/lib/perl5/site_perl
    .
Il mio script usa PDL (installato con CPAN) e PDL::NetCDF per leggere file
di dati meteo in quel formato. Il mio problema e' che dopo un poco il mio
programma schianta con il messaggio:
Out of memory during "large" request for 8392704 bytes, total sbrk() is 
127553856 bytes at ./
cloudfrac.pl
 line 42.
Ora, devo dire che sono stato attento a mettere le parti piu' dispendiose in
routines dove ho scialato con gli undef in uscita. Niente da fare, sembra 
che una successiva richiesta di memoria non utilizzi quella gia' del 
programma ma ne prenda di nuova. In giro ho trovato solo un messaggio del 
2001 che riportava questo come bug del perl (a partire dal 5.003).
E' cosa nota e sto parlando di vino in osteria?
C'e' modo di venirne a capo oppure cerco una soluzione diversa dal perl?
(frazionare piu' di cosi' non posso, i dati mi servono davvero in memoria!
E giuro che gli undef ci sono!).
Grazie mille a chi puo' dare una mano!
-- 
Graziano

senti... premetto che non so assolutamente un cappero del modulo che usi e
come lo usi, e come me, credo che forse tutti, (anche quelli che saprebbero
forse come risolverti il problema) non sanno nulla del modulo che usi,
quindi magari se spendi due parole per dirci cosa fa sto modulo e cosa fa il
tuo programma, chissà qualcuno potrebbe avere qualche idea alternativa.
Ad occhio e croce, a me sembra di capire che scarichi dei dati da qualche
parte e poi li devi utilizzare per farci qualche calcolo... solo che ne tiri
su talmente tanti che il programma si schianta. È così?
Non puoi fare un algoritmo che ne prenda su un po' alla volta e si diletti
con uno scratch disk? Magari da disco non andrà come una scheggia, ma (anche
non conoscendolo) mi sembra davvero che dovresti ottimizzare un po' il tuo
algoritmo....
Prova a fare qualcosa come fa ad esempio Photoshop (sperando che lo
conosca): quando apri un'immagine di centinaia di Mb con un PC che ha solo
50Mb liberi, mica ti dice che non può aprire l'immagine... ne apre un pezzo
alla volta e fa tutto quello che deve fare lo stesso, ovviamente un po' più
lentamente che se avesse più RAM, però funziona!
--
-.. --- -- .. --.. .. ---
-.. . -- .. -.-. .... . .-.. .. ...

ahh... prova un po' a fare
limit
in una command line e vedere cosa ti scrive... magari il problema non ha
nulla a che vedere con perl


comunque più ci penso e più mi convinco che stai facendo una pazzia. Se stai
facendo dei calcoli usando degli hash o degli array, puoi utilizzare memoria
su disco invece che memoria RAM! Dai uno sguardo a:
perldoc -f tie


o è che generi un output di alcuni Mb e lo tieni in RAM fino a quando
scoppia? :-)


 
Ripeto, l'idea e' la stessa, ma ogni volta che esco dalla sub dove ci sono i 
miei my $data, e alla fine ci metto pure gli undef $data, la memoria non 
viene restituita, e alla volta succesiva che rientro nella sub viene 
riallocata e non sovrascritta.
-- 
Graziano

 limit
Gia controllato, ho unlimited su tutto (la macchina e' un alphaserver 4800
con 4 processori Alpha e 2GB di RAM).
-- 
Graziano

 ho il messaggio di errore sulla memoria.
OK, che ne dici se posti qui SOLO le linee di code responsabili
dell'overload, cosě vediamo le cazzate che hai scritto :-)
comunque mi punge vaghezza che hai usato "undef" in modo sbagliato. Prova un
po' a leggere
perldoc -f undef
e facci sapere


###############################################################################
#
# Required modules
#
use strict;
use PDL;
use PDL::NetCDF;
use PDL::Char;
use Getopt::Std;
#
# Debug flag. Set it to 1 to have debug printout
#
my $debug = 0;
#
# All arguments are piddles i.e. PDL objects
#
sub calc_pressure
{
  my $ptop = shift(@_);
  my $sigma_level = shift(@_);
  my $pstarcross = shift(@_);
  my $pp = shift(@_);
  my @fdims = $pp->dims;
  my $ps3d = $pstarcross->dummy(-1, $fdims[2]);
  my $level2d = $sigma_level->dummy(0, $fdims[1]);
  my $level3d = $level2d->dummy(0, $fdims[0]);
  my $pridro = $level3d*$ps3d;
  my $pressure = $pridro + ($pp + $ptop);
  undef @fdims;
  undef $ps3d;
  undef $level2d;
  undef $level3d;
  undef $pridro;
  return $pressure;
}
#
# All arguments are piddles (PDL objects)
#
sub calc_rh
{
  my $t = shift(@_);
  my $q = shift(@_);
  my $pressure = shift(@_);
  my $d1 = (($t - 273.15)/($t - 29.65)*17.67;
  $d1->inplace->exp;
  my $d2 = 22.514-(6150.0/$t);
  $d2->inplace->exp;
  my $es = ($t >= 273.15) * (6.112 * $d1) + ($t <  273.15) * (6.112 * $d2);
  my $qs = (62.2 * $es) / ($pressure - $es);
  my $rh = 100.0 * ($q/$qs);
  undef $d1;
  undef $d2;
  undef $es;
  undef $qs;
  return $rh;
}
#############################################################################
Il resto legge i dati dal file di input e scrive il file di output. Ho altre 
cinque routines tipo queste, ma per il concetto dovrebbero bastare. Quello che 
mi aspetto e' che ogni volta che rientro nelle sub, la memoria venga 
riutilizzata. Quello che non mi aspetto e' che ogni volta venga riallocata.
--
Graziano

 }
   A mio modestissimo avviso, e` del tutto inutile undef-inire gli 
oggetti poco prima dell'uscita dal loro scope di visibilita`: il garbage 
collector dovrebbe comunque recuperare la memoria da essi occupata 
all'uscita dalla sub... a meno che, come sospetto, gli oggetti $d1, 
ecc., siano solo riferimenti agli oggetti veri e propri, nel quale caso 
e` ugualmente inutile undef-inirli in quanto il GC e` "reference-count 
based", cioe` non distrugge gli oggetti allocati finche` qualche 
riferimento punta loro (e quello all'interno della funzione non e` 
certamente l'ultimo).
-- 
Alla prossima,
Marco

 certamente l'ultimo).
Suona molto ragionevole...
la risposta mi soddisfa e mi incasina allo stesso tempo.
Grazie mille!
-- 
Graziano

 la risposta mi soddisfa e mi incasina allo stesso tempo.
   Forse non ti incasina troppo: basta scoprire dove si alloca la 
memoria per sti' benedetti piddles e provvedere a recuperarla in quella 
sede, quando cio` sia possibile.
-- 
Alla prossima,
Marco

   undef $pridro;
e l'effetto sarà identico, oltretutto come già detto, se i vari parametri
sono oggetti, non serve a nulla undefinirli in una sub. Mi hai detto che hai
un loop da qualche parte che utilizza le funzioni di calcolo: scommetto che
è proprio in quel loop che sta il problema. Se lo scrivi qui vedrai che
qualcuno te lo trova :-).
ciao


my ($ptop, $sigma_level, $pstarcross, $pp) = @_;
E` piu` semplice, ma attenzione al fatto che non sono due scritture
equivalenti. Infatti, mentre:
my $ptop = shift; # Personalmente preferisco questo 
                  # rispetto a my $ptop = shift( @_ )
modifica l'array @_, la scrittura:
my ($ptop, $sigma_level, $pstarcross, $pp) = @_;
lo lascia invariato.
Scusate se sono pedante :)
ciao
Stefano

 Scusate se sono pedante :)
non sei pendante e dici una profonda verità, tant'è vero che prima di
scrivere ho verificato che nelle sub in questione @_ non veniva utilizzato
direttamente come array né come elemento $_[n], quindi in quel contesto è
esattamente la stessa cosa.
In ogni caso sebbene può essere utile sapere che @_ viene modificato con
shift, in pratica è necessario saperlo SOLO se fai un loop direttamente su
@_ o se usi i vari elementi $_[n] direttamente (senza assegnarli a variabili
locali). Se assegni alle variabili puoi tranquillamente ignorarlo.
