More on speeding things up
- To: uiucuxc!yoda.ncsa.uiuc.edu!mathgroup
- Subject: More on speeding things up
- From: uiucuxc!cello.hpl.hp.com!jacobson
- Date: Wed, 14 Mar 90 08:33:19 PST
Suppose foo is a list.
If possible avoid
Do[ ... foo[[i]] ..., {i,1,Length[foo]}]
Instead use
Scan[(... # ....)&,foo]
which we be much faster. If you need to know the index you are at for
any reason, initialize a counter to 0 and increment it at the
beginning of the function in Scan.
On big arrays subscripting is VERY slow, and the reason is that
foo[[i]] is really Part[foo,i] and Part[] evaluates it arguments.
So at every access it looks over the *entire* array for something that
might expand to something else. You can avoid this by making the list
be something that won't evaluate. I've speeding things up by orders
of magnitude (yes) with the following trick:
First execute
SetAttributes[HoldList,HoldAll]
Suppose some code that I'll abbreviate xxxxxxx generates foo.
Instead of writing
foo = xxxxxxxx
I write
foo = Apply[HoldList,xxxxxxxxx]
Now when I write foo[[i]], the Part function tries to evalute foo, but
since it has the HoldAll attributed, it goes no farther. Most list
manipulating functions will work on these homemade HoldList objects.
But be careful with /. and Map because the subitituions/transformations
will be made but not evaluated.
I've reported this idea to WRI's support people. I'd like to see them
make it official and fix the few places that requrire real List
objects to accept HoldList objects as well.
-- David Jacobson