Baris wrote:
> Looping through the matrix elements is probably most common thing people
do
> in matrix computation. And because of some weird reason I am not aware of,
> the only way to do this efficiently is to write your program in C. So
> everybody I know sooner or later switches to C because of the speed
issues.
> In perl this is very very inefficient. In matlab at least (even though a
> double for loop takes 100 times more time) it is possible to implement it
> in finite time. So people ended up using matlab loops despite its slowness
> because writing in C is painful, time consuming and requires a C compiler,
> which not always exist in every platform.
>
An excellent point. Many switch to FORTRAN too...
One way around this issue is to provide as much _implicit_ looping as
possible, and to build in functions that know how to loop efficiently. For
instance, from RFC 82:
<quote>
=head1 IMPLEMENTATION
These operators and functions should be evaluated lazily. For instance:
@b = (1,2,3);
@c = (2,4,6);
@d = (-2,-4,-6);
$sum = reduce ^_+^_, @b * @c + @d;
should be evaluated as if it read:
$sum = 0;
$sum += $b[$_] * $c[$_] + $d[_] for (0..$#a-1));
That is, no temporary list is created, and only one loop is required.
</quote>
This way, we use Perl's internal looping mechanisms, which can be at full C
speed.
Tuomas pointed out on PDL Porters a little while ago that explicit looping
is still sometimes required for more complex manipulation. For this reason
we do still need to consider fast explicit loops, as Baris suggests.
Ideally, we would find ways of using 'foreach' that -internals could easily
optimise. What are the attributes of a loop that would allow it to be
optimised? Obviously the structure looped over should be an (n-dim) array of
basic types. The array size should not change. What else?
Perhaps the '@*' notation we've been discussing can be used. This might help
us to write loops over dimensions other than the first:
foreach (@a) {$tmp += $a[$_];} # optimised if @a array of simple types
# Loop over columns of @mat, adding the total of each col of $tmp:
foreach my $*[1] (@mat) {$tmp += sum(@mat[0..; $*[1]]); }
I'm still not quite sure how this magic @* quite works... Any other
suggestions for how an explicit loop over matrix columns should look?