Hi David,

Sorry it's taken me so long to get back to this; I went on vacation the day I got my program working, and I got sick as soon as I got back.

Anyway, here's a script that can reproduce the recusion limit error (even under PDL v2.4.11). It starts threads, generates lists of random numbers and undefs, makes them into piddles using the undef->bad idiom I'd started out with, takes their averages, and repeats, with evals to catch the crashes.

I hope 2013 has gotten off to a good start for you.

-- Erich

#!/usr/bin/perl

use 5.014;
use warnings;
use threads;
use Thread::Queue;
use PDL::LiteF;

# Create PDL where input could be undef, using a weird badness idiom
sub pdlify {
    my @in  = map {ref eq 'ARRAY' ? @$_ : $_} @_;
    my @out = map {defined($_) ? pdl($_) : pdl(0)->setbadat(0)} @in;
    return cat(@out);
}

# Start threads
my $maxthreads = shift // 2;       # take number of threads to start as arg
my $queue = Thread::Queue->new();  # for communicating between threads
my %threads;
foreach (1..$maxthreads) {
    my $new = threads->create({'context' => 'list'},\&thread_stuff,$queue);
    my $tid = $new->tid();
    say "Starting thread $tid";
    $threads{$tid} = $new;    # %threads stores refs to running threads
}

# Wait for threads to return
while (%threads) {
    my $tid = $queue->dequeue();              # read which thread has finished
    my ($spot,$rep,$error) = $threads{$tid}->join();  # read return values
    if ($error) {
        # got an error, so die
        die "Thread $tid $spot rep $rep: $error\n";
    } else {
        # thread finished normally, so remove from set of running threads
        delete $threads{$tid};
    }
}
say "All $maxthreads threads got through 100,000 iterations without crashing.";

# In each thread, we'll generate lists of 1000 random numbers, some undef,
# make them into piddles, and take their means
sub thread_stuff {

    my $queue = shift;
    my $tid   = threads->tid();
    my $reps  = 0;

    my $exit = sub {
        $queue->enqueue($tid);  # tell the main program which thread died
        return @_;              # pass back the error message
    };

    while ($reps++ < 100_000) {
        my (@rawdata,$pdl,$mean);
        # make a list of 1000 random values, some will be undef
        foreach (1..1000) {
            my $x = rand(100);
            push @rawdata, ($x > 99 ? undef : $x);
        }
        # turn the list into a piddle with undef -> BAD
        eval {$pdl = pdlify(@rawdata)};
        return $exit->('pdlify',$reps,$@) if $@;  # note kaboom
        # get the mean of the piddle
        eval {$mean = $pdl->avg()};
        return $exit->('mean',$reps,$@) if $@;  # note kaboom
    }
    return $exit->();   # thread finishing without incident

}

_______________________________________________
Perldl mailing list
[email protected]
http://mailman.jach.hawaii.edu/mailman/listinfo/perldl

Reply via email to