[Charlotte.PM] Help me tune this for speed
Steven Bush
steven at knowmad.com
Wed Jul 27 06:16:07 PDT 2005
Hi Drew,
I've found one point that I think will help speed your process up.
When you loop through all found unique edges from smallest to largest
and again through all previously found edges in order, you build an
array ref each time ($points_ref). When you are populating this array
with data, the first two things you put into it do not use any
information that is generated by the second loop. So you are basically
preforming a pair of calculations 90300 times that only needs to be
calculated 1778 times. I've re-written the associated area of code
(lines 84-87, 94 in my code) to fix this problem, and it is included
below. I have not yet tried to run this code, so I'm not sure how much
help it will be, but I think it should help some.
~Steven
#!/usr/bin/perl
######################################################################
# CPAN modules
######################################################################
use YAML qw(Dump Load);
use Carp;
use Benchmark;
use Math::Geometry::Planar;
use strict;
######################################################################
# A few globals
######################################################################
my $points; # hash ref holding the raw data {'1' => [X,Y], '2' => [X,Y], ...}
my @edges; # Array to keep refrences to all edges [edge, X1, Y1, X2, Y2] ...
my $neighborEdges; # hash ref to hold sorted neighbor edges {'1' => edge1, '2' => edge2, ...}
######################################################################
#
# MAIN
#
######################################################################
# Read in the X,Y coordinates from supplied data
{
local $/;
open(my $fh, "dump_301.dat") or die "Unable to open file: $!\n";
$points = Load( <$fh> );
croak($@) if $@;
close($fh);
}
# Find all the unique edges
eval {
my $start_distance = Benchmark->new;
my $found = {};
# p1 is starting or anchor point of the line segment
foreach my $p1 (@{$points}) {
# p1 is end point of the line segment
foreach my $p2 (@{$points}) {
# We don't need to caculate if anchor and end are the same
# or we have already seen these two pairs [reversed] before
unless ( ($p1 == $p2) || $found->{$p2}->{$p1} ) {
# Compute the edge
my $edge = sqrt(
($p1->[0] - $p2->[0])**2 +
($p1->[1] - $p2->[1])**2
);
# Push a ref of the whole thing on a stack
push (@edges, [ $edge, $p1->[0], $p1->[1], $p2->[0], $p2->[1] ]);
# Keep track of the edges we've already computed (no need to do so twice)
$found->{$p2}->{$p1} = 1;
}
}
}
print "Found unique Edges = ", scalar(@edges), "\n";
print timestr(timediff(Benchmark->new, $start_distance)), "\n";
};
croak($@) if ($@);
# Compute the neighboors
my $start_intersect = Benchmark->new;
# Need an integer to keep our sort order
my $neighboorCNT = 1;
# Loop trough all found unique edges from smallest to largest
foreach my $aref ( sort {$a->[0] <=> $b->[0] } @edges) {
my $neighbor = 1; # default true
my $line_1_ref = [];
push (@{$line_1_ref}, [$aref->[1],$aref->[2]]); # line 1 point A X,Y
push (@{$line_1_ref}, [$aref->[3],$aref->[4]]); # line 1 point B X,Y
# Loop through all previously found edges in order
for (my $n=1;$n<=$neighboorCNT;$n++) {
if ($neighborEdges->{$n}) {
my $points_ref = []; # Data structure to pass to SegmentIntersection
push (@{$points_ref}, @{$line_1_ref}); # line 1 points
push (@{$points_ref}, [$neighborEdges->{$n}->[1],$neighborEdges->{$n}->[2]]); # line 2 point A X,Y
push (@{$points_ref}, [$neighborEdges->{$n}->[3],$neighborEdges->{$n}->[4]]); # line 2 point B X,Y
my @p = SegmentIntersection($points_ref);
# If a intersect is found, set false and quit checking
if (SegmentIntersection($points_ref)) {
$neighbor = 0;
last;
}
}
}
if ($neighbor) {
$neighborEdges->{$neighboorCNT} = $aref;
$neighboorCNT++;
}
}
print "Unintersected edges ", scalar(keys %{$neighborEdges}), "\n";
print timestr(timediff(Benchmark->new, $start_intersect)), "\n";
More information about the charlotte
mailing list