<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body bgcolor="#ffffff" text="#000000">
<div class="moz-text-flowed"
 style="font-family: -moz-fixed; font-size: 12px;" lang="x-western">Let
me refine my earlier posting in this regard.&nbsp; The code below has two
different implementations of convolution,&nbsp; The first implementation
runs marginally faster than a straightforward C implementation using
nested for loops.&nbsp; This is of course a delightful result, especially
given the declarative style of the code.<br>
<br>
The second implementation (my attempt to imitate the nested 'for' loops
of a 'straightforward' convolution) runs 4x slower.&nbsp; Are there any
general principles of Clean programming that would allow me to
understand -- on inspection of the code -- why the second
implementation does not achieve equivalence with the corresponding C
code?
<br>
<br>
Regards,
<br>
David
<br>
----
<br>
module myconvolve
<br>
<br>
import StdEnv
<br>
<br>
// When compiled with clm -fusion, this implementation proves to be
<br>
// marginally faster than gcc -O2 compiled C using nested for loops
<br>
// as in:
<br>
//&nbsp;&nbsp; for(i=0; i&lt;na; i++){
<br>
//&nbsp;&nbsp;&nbsp;&nbsp; for(j=0; j&lt;nb; j++){
<br>
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ab[i+j] += a[i] * b[j];
<br>
//&nbsp;&nbsp;&nbsp;&nbsp; }
<br>
//&nbsp;&nbsp; }
<br>
convolve :: (ar e) (ar e) -&gt; (ar e) | Array ar e &amp; Arith e
<br>
convolve a b = {let start = max 0 (i-m)
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end&nbsp;&nbsp; = min i n
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foldl (+) zero [ a.[i-k] * b.[k] \\ k &lt;-
[start..end] ]
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \\ i &lt;- [0..(m+n)]}
<br>
where
<br>
&nbsp;&nbsp; m = size a - 1
<br>
&nbsp;&nbsp; n = size b - 1
<br>
<br>
<br>
// Why does this implementation (imitating the C code above) run 4x
slower?
<br>
// It used to run 30x slower, but:
<br>
// (1) Adding a type for iconvolve`, including uniqueness for ab
<br>
//&nbsp;&nbsp;&nbsp;&nbsp; and strictness for {i,j,k}, produced a 5x speedup.
<br>
// (2) Adding a and b to the parameter list of iconvolve gave another
2x.
<br>
iconvolve :: !{#Real} !{#Real} -&gt; *{#Real}
<br>
iconvolve a b = iconvolve` ab a b 0 0 0
<br>
where
<br>
&nbsp;&nbsp; na = size a
<br>
&nbsp;&nbsp; nb = size b
<br>
&nbsp;&nbsp; nab = na + nb - 1
<br>
&nbsp;&nbsp; ab :: *{#Real}
<br>
&nbsp;&nbsp; ab = createArray nab 0.0
<br>
&nbsp;&nbsp; iconvolve` :: !*{#Real} !{#Real} !{#Real} !Int !Int !Int -&gt;
*{#Real}
<br>
&nbsp;&nbsp; iconvolve` ab=:{[k]=ab_k} a b i j k&nbsp; // constraint k==i+j is
maintained
<br>
&nbsp;&nbsp; | i &gt;= na&nbsp;&nbsp; = ab
<br>
&nbsp;&nbsp; | j &gt;= nb&nbsp;&nbsp; = iconvolve` ab a b (i+1) 0 (i+1)
<br>
&nbsp;&nbsp; | otherwise = iconvolve` ab` a b i (j+1) (i+j+1)
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ab` = {ab &amp; [k] = ab_k + a.[i] * b.[j]}
<br>
<br>
<br>
Start :: Real
<br>
Start = (iconvolve a b).[m+n-2]
<br>
//Start = (convolve a b).[m+n-2]
<br>
where
<br>
&nbsp;&nbsp; m = 10000
<br>
&nbsp;&nbsp; n = 6000
<br>
&nbsp;&nbsp; a :: {#Real}
<br>
&nbsp;&nbsp; a = {fromInt x \\ x &lt;- [1..m]}
<br>
&nbsp;&nbsp; b :: {#Real}
<br>
&nbsp;&nbsp; b = {fromInt x \\ x &lt;- [1..n]}
<br>
<br>
<br>
</div>
</body>
</html>