On Thu, 8 Sep 2011, Riccardo (Jack) Lucchetti wrote:
On Thu, 8 Sep 2011, Allin Cottrell wrote:
> On Thu, 8 Sep 2011, Allin Cottrell wrote:
>
>> [...] The operation Artur mentions, namely assigning a
>> scalar value to a single element of a matrix, is a special
>> case of assignment to a sub-matrix, which has the general
>> form:
>>
>> M[r1:r2,c1:c2] = <expression>
>>
>> where the r's and c's are expressions that evaluate to row
>> and column indices. This demands a lot more parsing effort
>> than assigning a scalar value to a place in a series (where
>> the only valid specifier on the left is a single observation
>> number).
>>
>> We could maybe write a dedicated, faster function for the
>> special case, but even then we first have to figure out that
>> we're actually in that special case.
>
> In fact quite a nice speed-up was available here. Things
> should look better in current CVS.
Small testcase:
<hansl>
matrix tt = {}
loop foreach k 1000 2000 4000 --quiet
n = $k
X = mnormal(n, n)
set stopwatch
loop i=1..n --quiet
loop j=1..n --quiet
scalar a = X[i,j]
end loop
end loop
tt |= $stopwatch
end loop
print tt
</hansl>
Before:
? print tt
tt (3 x 1)
1.8
7.21
29.04
After:
tt (3 x 1)
1.73
7.03
28.63
Not bad at all, I say.
Maybe, but that improvement seems marginal to me. I was really
talking about the exact case raised by Artur, where the
often-repeated operation is assigment from some scalar value to a
single element within a pre-existing matrix, and in that case the
improvement is dramatic:
<hansl>
set echo off
set messages off
nulldata 10000
series x = normal()
matrix m = zeros($nobs,1)
set stopwatch
loop for i = 1..$nobs --quiet
m[i,1] = x[i]
endloop
printf "elapsed: %g seconds\n", $stopwatch
</hansl>
On an admittedly kinda slow machine here at home I'm getting:
Before, elapsed: 1.33 seconds
After, elapsed: 0.03 seconds
Allin