Monday, June 8, 2015

Perl Matrix Multiplication

Here's the Perl script for matrix multiplication. It's derived from the RosettaCode site with slight modifications ... I didn't like some things about their way of doing things, but it's much the same in the end.

#! /usr/bin/perl5.20.2

use 5.020;
use warnings; 
use strict;
use English;
use Time::HiRes qw(gettimeofday tv_interval);
use autodie;
use Data::Dumper;

# -------------------------------------------------------
# SUBROUTINES
#
# ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯
# matmult - multiple matrices. Copied from
#    RosettaCode.orgwiki/Matrix_multiplication#Perl.
#
sub matmult {
    my ( $M, $N ) = @_;

    my ( $rows, $cols ) = (scalar @$M, scalar @{$N->[0]} );
    my $prod = [];
    my $k = @$N - 1;

    for my $i ( 0..$rows - 1 ) {
        for my $j ( 0 .. $cols - 1 ) {
            $prod->[$i][$j] += $M->[$i][$_]
                                * $N->[$_][$j]
                for 0..$k;
        }
    }
    return $prod;
}
# ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯
# readMatrix - read file data -> array of array of int.
#
sub readMatrix {
    my ( $filename ) = @_;

    open my $infile, '<', $filename;
    local $/ = undef;
    my ($matrix) = [map { [split / +/, $_] }
                      split / *\n/, <$infile>
                   ];

    return $matrix;
}
# ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯
# main line of processing
#
sub main {
   die( "USAGE: $PROGRAM_NAME reps file1 file1" )
      unless 3 == @ARGV 
          && $ARGV[0] > 0
          && -e $ARGV[1] && -r _
          && -e $ARGV[2] && -r _;

   my ($M, $N) = (readMatrix($ARGV[1]),
                  readMatrix($ARGV[2]));

#    say Data::Dumper::Dumper [$M, $N];

    my $t0 = [ gettimeofday ];
    my $prod;
    for my $reps ( 1 .. $ARGV[0] ) {
        $prod = matmult( $M, $N );
    }
    my $delta = tv_interval($t0);
    say "Multiplying matrices $ARGV[0] times takes ",
        "$delta seconds.";
#    say Data::Dumper::Dumper [$prod];
}
# -----------------------------------------------------

main();



Inverting the numbers to look at millions of multiplications per second, we see that overhead on small matrices degrades performance, but larger matrices enable 5.5 million multiplications per second.


No comments: