Re having an old PC - and rubbing salt into tybalt89's wounds -
please note that my (Haswell 4770K-powered) home PC
is unchanged from when I mentioned it over three years ago in The 10**21 Problem (Part 2) and so
is getting rather old and creaky now. Definitely due for an upgrade. :)
Though my ancient PC does have 32 GB of memory (and so there is no swapping),
given my very slow benchmark results with Game::Life::Infinite::Board,
I'm suspicious that my doddering, ancient memory is starting to fail, due to being so old.
This may be contributing to the significantly different results I am seeing.
When running:
perl tbench1.pl x.tmp 2
with my originally shortened Organism.pm:
package Organism;
use strict;
# use warnings;
sub count {
return scalar keys %{ shift->{Cells} };
}
# Input a list of [ x, y ] coords
sub insert_cells {
my $cells = shift->{Cells};
for my $r (@_) { $cells->{ pack 'i2', @{$r} } = undef }
}
# Return sorted list of cells in the Organism.
# Used for verification and testing the state of the organism.
sub get_live_cells {
sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] }
map { [ unpack 'i2', $_ ] }
keys %{ shift->{Cells} };
}
sub tick {
my $self = shift;
my $cells = $self->{Cells};
my ( $k1, $k2, $k3, $k4, $k5, $k6, $k7, $k8,
$x0, $x1, $x2, $y0, $y1, $y2, %new_cells );
for my $c (keys %{ $cells }) {
# Get the (up to 8) dead cells surrounding the cell
( $x0, $y0 ) = unpack 'i2', $c;
( $x1, $x2, $y1, $y2 ) = ( $x0 - 1, $x0 + 1, $y0 - 1, $y0 + 1 );
my @zcells = (
($k1 = pack 'i2', $x1, $y1) x !(exists $cells->{$k1}),
($k2 = pack 'i2', $x1, $y0) x !(exists $cells->{$k2}),
($k3 = pack 'i2', $x1, $y2) x !(exists $cells->{$k3}),
($k4 = pack 'i2', $x0, $y1) x !(exists $cells->{$k4}),
($k5 = pack 'i2', $x0, $y2) x !(exists $cells->{$k5}),
($k6 = pack 'i2', $x2, $y1) x !(exists $cells->{$k6}),
($k7 = pack 'i2', $x2, $y0) x !(exists $cells->{$k7}),
($k8 = pack 'i2', $x2, $y2) x !(exists $cells->{$k8}) );
# Check the live cell
# Note: next line equivalent to nlive == 2 || nlive == 3
@zcells == 5 || @zcells == 6 and $new_cells{$c} = undef;
# Check the dead cells
for my $z (@zcells) {
( $x0, $y0 ) = unpack 'i2', $z;
( $x1, $x2, $y1, $y2 ) = ( $x0 - 1, $x0 + 1, $y0 - 1, $y0 + 1
+ );
# Get num live
( ( exists $cells->{ pack 'i2', $x1, $y1 } )
+ ( exists $cells->{ pack 'i2', $x1, $y0 } )
+ ( exists $cells->{ pack 'i2', $x1, $y2 } )
+ ( exists $cells->{ pack 'i2', $x0, $y1 } )
+ ( exists $cells->{ pack 'i2', $x0, $y2 } )
+ ( exists $cells->{ pack 'i2', $x2, $y1 } )
+ ( exists $cells->{ pack 'i2', $x2, $y0 } )
+ ( exists $cells->{ pack 'i2', $x2, $y2 } )
) == 3 and $new_cells{$z} = undef;
}
}
$self->{Cells} = \%new_cells;
}
sub new {
my $class = shift;
my %init_self = ( Cells => {} );
bless \%init_self, $class;
}
1;
I get 62 seconds, while after making the excellent improvements
suggested by
tybalt89 I get 80 seconds.
package Organism;
use strict;
# use warnings;
sub count {
return scalar keys %{ shift->{Cells} };
}
# Input a list of [ x, y ] coords
sub insert_cells {
my $cells = shift->{Cells};
for my $r (@_) { $cells->{ pack 'i2', @{$r} } = undef }
}
# Return sorted list of cells in the Organism.
# Used for verification and testing the state of the organism.
sub get_live_cells {
sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] }
map { [ unpack 'i2', $_ ] }
keys %{ shift->{Cells} };
}
sub tick {
my $self = shift;
my $cells = $self->{Cells};
my ( $k1, $k2, $k3, $k4, $k5, $k6, $k7, $k8,
$x0, $x1, $x2, $y0, $y1, $y2, %new_cells, %dead_cells );
for my $c (keys %{ $cells }) {
# Get the (up to 8) dead cells surrounding the cell
( $x0, $y0 ) = unpack 'i2', $c;
( $x1, $x2, $y1, $y2 ) = ( $x0 - 1, $x0 + 1, $y0 - 1, $y0 + 1 );
$dead_cells{$_}++ for my @zcells = (
($k1 = pack 'i2', $x1, $y1) x !(exists $cells->{$k1}),
($k2 = pack 'i2', $x1, $y0) x !(exists $cells->{$k2}),
($k3 = pack 'i2', $x1, $y2) x !(exists $cells->{$k3}),
($k4 = pack 'i2', $x0, $y1) x !(exists $cells->{$k4}),
($k5 = pack 'i2', $x0, $y2) x !(exists $cells->{$k5}),
($k6 = pack 'i2', $x2, $y1) x !(exists $cells->{$k6}),
($k7 = pack 'i2', $x2, $y0) x !(exists $cells->{$k7}),
($k8 = pack 'i2', $x2, $y2) x !(exists $cells->{$k8}) );
# Check the live cell
# Note: next line equivalent to nlive == 2 || nlive == 3
@zcells == 5 || @zcells == 6 and $new_cells{$c} = undef;
}
$dead_cells{$_} == 3 and $new_cells{$_} = undef for keys %dead_cell
+s;
$self->{Cells} = \%new_cells;
}
sub new {
my $class = shift;
my %init_self = ( Cells => {} );
bless \%init_self, $class;
}
1;
Update: These tests were run with perl v5.24.0:
This is perl 5, version 24, subversion 0 (v5.24.0) built for MSWin32-x
+64-multi-thread
Need to upgrade that ancient Perl. :)
Update: After upgrading to perl v5.26.0, both are faster: (62 secs, 80 secs) improved to (53 secs, 71 secs).
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.