Beefy Boxes and Bandwidth Generously Provided by pair Networks Frank
There's more than one way to do things
 
PerlMonks  

Optimization Help

by jmmitc06 (Acolyte)
on Aug 01, 2013 at 23:06 UTC ( #1047512=perlquestion: print w/ replies, xml ) Need Help??
jmmitc06 has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks:

I am a bioinformatics programmer and I am currently running a very large calculation looking for subgraph isomorphisms. I have optimized it to the best of my abilities (I'm limited to the scale of my rewriting since the underlying objects/modules are used in much of my other code)

Below is a subroutine that currently consumes 74% of the time in my multiday calculation, even when using a cluster with torque. I have tried various different things, but I cannot beat what I have and any improvement would save me considerable time.

sub equate2 { my ($self, $other, $mapping) = @_; foreach my $row_index (0..$#$mapping) { return 0 if (grep { $$self{Matrix}[$row_index][$_] != $$other{Matr +ix}[$$mapping[$row_index]][$$mapping[$_]]); } (0..$#$mapping)); } return 1; }

I can provide more information if necessary, but in short this subroutine finds if elements of two matrices, i and j determined by a vector: $mapping.

Any advice and any tips for improving performance would be greatly appreciated. I have tried switching out the grep and foreach with for statements to no avail.

Thanks to all the monks for the help you have given in the past.

Comment on Optimization Help
Download Code
Re: Optimization Help
by BrowserUk (Pope) on Aug 01, 2013 at 23:24 UTC

    Your first problem is that your posted code doesn't compile. You have unbalanced parens and mismatched curlies:

    if (grep { $$self{Matrix}[$row_index][$_] != $$other{Matrix}[$$mapping +[$row_index]][$$mapping[$_]]); } (0..$#$mapping)); ( { + ^ } ( ))

    What are the dimensions of your matrices and the mapping array?


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Sorry, I typed it in by hand, here is the correct code ;)

      sub equate2 { my ($self, $other, $mapping) = @_; foreach my $row_index (0..$#$mapping) { return 0 if (grep { ($$self{Matrix}[$row_index][$_] != $$other{Mat +rix}[$$mapping[$row_index]][$$mapping[$_]]); } (0..$#$mapping)); } return 1; }
      Oh and all the matrices are 2D and the mapping vector is 1D

        Try:

        sub equate2 { my ($self, $other, $mapping) = @_; my $sm = $self->{Matrix}; my $om = $other->{Matrix}; for my $row ( 0 .. $#$mapping ) { my $smrow = $sm->[ $row ]; my $omrow = $om->[ $mapping->[ $row ] ]; for my $col ( 0 .. $#$mapping ) { return 0 if $smrow->[ $col ] != $omrow->[ $mapping->[ $col + ] ]; } } return 1; }

        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Optimization Help
by choroba (Abbot) on Aug 01, 2013 at 23:25 UTC
    grep iterates over all the numbers from 0 to $#mapping. Stopping the loop as soon as the first inequality is found might speed the subroutine up, especially if the array is large and inequalities are not very rare. You can use a simple for loop instead:
    for (0 .. $#mapping) { return 0 if $self->{Matrix}[$row_index][$_] != $other->{Matrix}[$mapping->[$row_index]][$mapping->[$_ +]]; } return 1;

    Update: The hash dereference could also take some microseconds if repeated many times. As $row_index does not change, you can assign the values to variables:

    my $self_row = $self->{Matrix}[$row_index]; my $other_row = $other->{Matrix}[$mapping->[$row_index]]; for (0 .. $#mapping) { return 0 if $self_row->[$_] != $other_row->[$mapping->[$_]]; } return 1;
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1047512]
Approved by BrowserUk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (17)
As of 2014-04-17 20:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (455 votes), past polls