PDL::Tips - Small tidbits of useful arcana. Programming tidbits and such.
use PDL;
# Whatever happens here.
This page documents useful idioms, helpful hints and tips for using Perl Data
Language v2.0.
Use "help help" within
perldl or
pdl2 or use the
"pdldoc" program from the command line for access to the PerlDL
documentation. HTML versions of the pages should also be present, in the
HtmlDocs/PDL directory of the PDL distribution. To find this directory,
try the following
pdl> foreach ( map{"$_/PDL/HtmlDocs"}@INC ) { p "$_\n" if -d $_ }
The following code normalizes a bunch of vectors in $x. This works regardless of
the dimensionality of $x.
$x /= $x->sumover->dummy(0);
If you want to see what the code is actually doing, try the command
PDL::Core::set_debugging(1);
somewhere. This spews out a huge amount of debug info for PDL into STDOUT. Plans
for the future include making it possible to redirect the output, and also
making it possible to select messages with more precision.
Many of the messages come from "Basic/Core/pdlapi.c" and you can look
at the source to see what is going on.
If you have any extra time to work on these mechanisms, inform the pdl-porters
mailing list.
If you are running recursively something that selects certain indices of a large
ndarray, like
while(1) {
$inds = where($x>0);
$x = $x->index($inds);
$y = $y->index($inds);
func($y,$x);
}
If you are not writing to $y, it saves a lot of memory to change this to
$y = $y->index($inds)->sever;
The new method "sever" is a causes the write-back relation to be
forgotten. It is like copy except it changes the original ndarray and returns
it).
Of course, the probably best way to do the above is
$inds = xvals ($x->long);
while(1) {
$inds0 = where($x>0);
$inds1 = $inds->index($inds)->sever;
$x = $a0->index($inds1);
$y = $y->index($inds1)->sever;
func($y,$x);
}
which doesn't save all the temporary instances of $x in memory. See
"mandel.pl" in the Demos subdirectory of the PerlDL distribution for
an example.
If you really want to write speedy PP code, the first thing you need to do is to
make sure that your C compiler is allowed to do the necessary optimizations.
What this means is that you have to allow as many variables as possible to go
into registers:
loop(a) %{
$a() += $COMP(foo_member) * $b()
%}
expands to
for(i=0; i<10000; i++) {
a[i] += __privtrans->foo_member * b[i];
}
is about the worst you can do, since your C compiler is not allowed to assume
that "a" doesn't clobber "foo_member" which completely
inhibits vectorization. Instead, do
float foo = $COMP(foo_member);
loop(a) %{
$a() += foo * $b();
%}
This is not a restriction caused by PP but by ANSI C semantics. Of course, we
could copy the struct into local variables and back but that could cause very
strange things sometimes.
There are many other issues on organizing loops.
We are currently planning to make PP able to do fixed-width things as well as
physical ndarrays (where looping over the first dimensions would be cheaper as
there are less distinct increments, which might make a difference on machines
with a small number of registers).
Copyright (C) Tuomas J. Lukka 1997. All rights reserved. Duplication in the same
form and printing a copy for yourself allowed.