<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Vectorizing Rather Than Looping in IML in SAS/IML Software and Matrix Computations</title>
    <link>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/Vectorizing-Rather-Than-Looping-in-IML/m-p/617439#M4958</link>
    <description>&lt;P&gt;It is possible to represent these operations in terms of matrix multiplication, but if you have N observations the matrix will be NxN, which will get big.&amp;nbsp; I suspect the main performance bottleneck is not the loop but the fact that you are evaluating the normal PDF so many times. For N observations, you are evaluating the PDF N(N+1)/2 times.&amp;nbsp; This is unnecessary. You only need to evaluate the PDF at N locations. You can then use the properties of the normal PDF to reuse the values. (You also can compute x^2 once instead of multiple times.)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Let f be the normal PDF with standard deviation sigma=100. let f(x; mu) be the PDF for N(mu, 100) evaluated at x.&lt;/P&gt;
&lt;P&gt;You are currently evaluating&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;s=1&amp;nbsp; &amp;nbsp;f(1; 1)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;s=2&amp;nbsp; &amp;nbsp;f(1; 2)&amp;nbsp; f(2; 2)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;s=3&amp;nbsp; &amp;nbsp;f(1; 3)&amp;nbsp; f(2; 3)&amp;nbsp; f(3; 3)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;s=4&amp;nbsp; &amp;nbsp;f(1; 4)&amp;nbsp; f(2; 4)&amp;nbsp; f(3; 4)&amp;nbsp; f(4; 4)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;...&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;s=N&amp;nbsp; &amp;nbsp;f(1; N)&amp;nbsp; f(2; N)&amp;nbsp; f(3; N)&amp;nbsp; ...&amp;nbsp; &amp;nbsp; &amp;nbsp;f(N; N)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;However, notice that f(1; 1) = f(2; 2) = f(3; 3) = .... = f(N; N).&lt;/P&gt;
&lt;P&gt;Similarly,&amp;nbsp;f(1; 2) = f(2; 3) = .... = f(N-1; N).&lt;/P&gt;
&lt;P&gt;and f(1; 3) = f(2; 4) = ... = f(N-2; N).&lt;/P&gt;
&lt;P&gt;In general, the triangular matrix above is banded because the values depend only on the distance between x and N.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If you reuse the PDF values, you can save a lot of time. On my computer, the original loop for N=8000 takes 3.4 seconds whereas the improved loop takes 0.2 seconds, (Only 5% of the original time.)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%let N = 8000;

data series;
do t=1 to &amp;amp;N;
x=rannor(1);
output;
end;
run;


proc iml;
use series;
read all var _all_;
close;

x2 = x##2;      /* form x^2 one time */

/* original loop */
t0 = time();
s2 = j(1, &amp;amp;N, .);
do s=1 to &amp;amp;N;
   w = pdf("norm",1:s,s,100);
   s2[s] = w * x2[1:s] / sum(w);
end;
tLoop = time() - t0;
s0 = s2;     /* save the oringal values */

/* new loop */
t0 = time();
w0 = pdf("norm", 1:&amp;amp;N, &amp;amp;N, 100);  /* eval the PDF once */
do s = 1 to &amp;amp;N;
   w = w0[ , (&amp;amp;N-s+1):&amp;amp;N];
   s2[s] = w * x2[1:s] / sum(w);
end;
tVec = time() - t0;
print tLoop tVec;

print (max(abs(s0-s2)))[L="Max Diff"];  /* show that the answers are the same */
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Wed, 15 Jan 2020 14:03:02 GMT</pubDate>
    <dc:creator>Rick_SAS</dc:creator>
    <dc:date>2020-01-15T14:03:02Z</dc:date>
    <item>
      <title>Vectorizing Rather Than Looping in IML</title>
      <link>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/Vectorizing-Rather-Than-Looping-in-IML/m-p/616833#M4957</link>
      <description>&lt;P&gt;I have a time-series variable &lt;EM&gt;x&lt;/EM&gt; as follows.&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data series;
do t=1 to 5000;
x=rannor(1);
output;
end;
run;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;For each &lt;EM&gt;t&lt;/EM&gt;, I want to estimate &lt;EM&gt;x&lt;/EM&gt;'s second moment using observations from 1 to &lt;EM&gt;t&lt;/EM&gt;&amp;nbsp;and a normal kernel as follows.&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc iml;
use series;
read all var _all_;
close;
s2=1:5000;
do s=1 to 5000;
s2[s]=pdf("norm",1:s,s,100)*x[1:s]##2/sum(pdf("norm",1:s,s,100));
end;
create series var{t x s2};
append;
close;
quit;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;So I load &lt;EM&gt;series&lt;/EM&gt; and apply this recursive loop since the second moment at &lt;EM&gt;t&lt;/EM&gt; requires observations from 1 to &lt;EM&gt;t&lt;/EM&gt;&amp;nbsp;(&lt;EM&gt;x&lt;/EM&gt;[1:&lt;EM&gt;s&lt;/EM&gt;]) as well as the kernel weighting information (pdf("norm",1:&lt;EM&gt;s&lt;/EM&gt;,&lt;EM&gt;s&lt;/EM&gt;,100)). Is there any way to wisely alter this do loop by its equivalent vectorized method? This way takes too much time for a large &lt;EM&gt;T&lt;/EM&gt;&amp;gt;5000. Thanks.&lt;/P&gt;</description>
      <pubDate>Sun, 12 Jan 2020 23:21:48 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/Vectorizing-Rather-Than-Looping-in-IML/m-p/616833#M4957</guid>
      <dc:creator>Junyong</dc:creator>
      <dc:date>2020-01-12T23:21:48Z</dc:date>
    </item>
    <item>
      <title>Re: Vectorizing Rather Than Looping in IML</title>
      <link>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/Vectorizing-Rather-Than-Looping-in-IML/m-p/617439#M4958</link>
      <description>&lt;P&gt;It is possible to represent these operations in terms of matrix multiplication, but if you have N observations the matrix will be NxN, which will get big.&amp;nbsp; I suspect the main performance bottleneck is not the loop but the fact that you are evaluating the normal PDF so many times. For N observations, you are evaluating the PDF N(N+1)/2 times.&amp;nbsp; This is unnecessary. You only need to evaluate the PDF at N locations. You can then use the properties of the normal PDF to reuse the values. (You also can compute x^2 once instead of multiple times.)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Let f be the normal PDF with standard deviation sigma=100. let f(x; mu) be the PDF for N(mu, 100) evaluated at x.&lt;/P&gt;
&lt;P&gt;You are currently evaluating&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;s=1&amp;nbsp; &amp;nbsp;f(1; 1)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;s=2&amp;nbsp; &amp;nbsp;f(1; 2)&amp;nbsp; f(2; 2)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;s=3&amp;nbsp; &amp;nbsp;f(1; 3)&amp;nbsp; f(2; 3)&amp;nbsp; f(3; 3)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;s=4&amp;nbsp; &amp;nbsp;f(1; 4)&amp;nbsp; f(2; 4)&amp;nbsp; f(3; 4)&amp;nbsp; f(4; 4)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;...&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;s=N&amp;nbsp; &amp;nbsp;f(1; N)&amp;nbsp; f(2; N)&amp;nbsp; f(3; N)&amp;nbsp; ...&amp;nbsp; &amp;nbsp; &amp;nbsp;f(N; N)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;However, notice that f(1; 1) = f(2; 2) = f(3; 3) = .... = f(N; N).&lt;/P&gt;
&lt;P&gt;Similarly,&amp;nbsp;f(1; 2) = f(2; 3) = .... = f(N-1; N).&lt;/P&gt;
&lt;P&gt;and f(1; 3) = f(2; 4) = ... = f(N-2; N).&lt;/P&gt;
&lt;P&gt;In general, the triangular matrix above is banded because the values depend only on the distance between x and N.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If you reuse the PDF values, you can save a lot of time. On my computer, the original loop for N=8000 takes 3.4 seconds whereas the improved loop takes 0.2 seconds, (Only 5% of the original time.)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%let N = 8000;

data series;
do t=1 to &amp;amp;N;
x=rannor(1);
output;
end;
run;


proc iml;
use series;
read all var _all_;
close;

x2 = x##2;      /* form x^2 one time */

/* original loop */
t0 = time();
s2 = j(1, &amp;amp;N, .);
do s=1 to &amp;amp;N;
   w = pdf("norm",1:s,s,100);
   s2[s] = w * x2[1:s] / sum(w);
end;
tLoop = time() - t0;
s0 = s2;     /* save the oringal values */

/* new loop */
t0 = time();
w0 = pdf("norm", 1:&amp;amp;N, &amp;amp;N, 100);  /* eval the PDF once */
do s = 1 to &amp;amp;N;
   w = w0[ , (&amp;amp;N-s+1):&amp;amp;N];
   s2[s] = w * x2[1:s] / sum(w);
end;
tVec = time() - t0;
print tLoop tVec;

print (max(abs(s0-s2)))[L="Max Diff"];  /* show that the answers are the same */
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 15 Jan 2020 14:03:02 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/Vectorizing-Rather-Than-Looping-in-IML/m-p/617439#M4958</guid>
      <dc:creator>Rick_SAS</dc:creator>
      <dc:date>2020-01-15T14:03:02Z</dc:date>
    </item>
  </channel>
</rss>

