<?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: How to Better Vectorize Block Bootstrap? in SAS/IML Software and Matrix Computations</title>
    <link>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707966#M5376</link>
    <description>&lt;P&gt;It seems the case above isn't good enough to see the performance gain—the following substantially shows the gain instead. Thanks.&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc iml;
	i=j(500,10);
	call randseed(1);
	do j=1 to 5000;
		call randgen(i,"normal");
		if j=1 then k=vech(cov(i));
		else k=k||vech(cov(i));
	end;
quit;
proc iml;
	i=j(500,10);
	call randseed(1);
	k=j(55,5000);
	do j=1 to 5000;
		call randgen(i,"normal");
		k[,j]=vech(cov(i));
	end;
quit;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;And the results.&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;1    proc iml;
NOTE: IML Ready
2        i=j(500,10);
3        call randseed(1);
4        do j=1 to 5000;
5            call randgen(i,"normal");
6            if j=1 then k=vech(cov(i));
7            else k=k||vech(cov(i));
8        end;
9    quit;
NOTE: Exiting IML.
NOTE: PROCEDURE IML used (Total process time):
      real time           4.17 seconds
      cpu time            4.18 seconds


10   proc iml;
NOTE: IML Ready
11       i=j(500,10);
12       call randseed(1);
13       k=j(55,5000);
14       do j=1 to 5000;
15           call randgen(i,"normal");
16           k[,j]=vech(cov(i));
17       end;
18   quit;
NOTE: Exiting IML.
NOTE: PROCEDURE IML used (Total process time):
      real time           1.60 seconds
      cpu time            1.60 seconds&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;The latter is about 60% faster than the former. Significant.&lt;/P&gt;</description>
    <pubDate>Wed, 23 Dec 2020 19:51:04 GMT</pubDate>
    <dc:creator>Junyong</dc:creator>
    <dc:date>2020-12-23T19:51:04Z</dc:date>
    <item>
      <title>How to Better Vectorize Block Bootstrap?</title>
      <link>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707615#M5369</link>
      <description>&lt;P&gt;The raw time-series data are a 636×10 matrix as follows.&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have;
	infile "http://global-q.org/uploads/1/2/2/6/122679606/
portf_me_monthly_2019a.csv" url firstobs=2 dsd;
	input year month portfolio number return;
run;

proc transpose prefix=return out=have;
	by year month;
	id portfolio;
	var return;
run;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;And each block bootstrap samples a&amp;nbsp;636×10 matrix&lt;/P&gt;&lt;P&gt;(1) starting at a random point between 1 and 636 and&lt;/P&gt;&lt;P&gt;(2) shifting to another random point with 90% probability or if the ending observation (i.e., if the index reaches 636) as follows.&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc iml;
	use have(keep=return:);
	read all var _all_ into a;
	t=nrow(a);
	n=ncol(a);
	call streaminit(1);
	do b=1 to 2500;
/*----------------------------the bottleneck parts----------------------------*/
		do u=1 to t;
			if u=1 then v=rand("integer",1,t);
			else if v[u-1]=t then v=v//rand("integer",1,t);
			else if rand("uniform")&amp;gt;0.9 then v=v//rand("integer",1,t);
			else v=v//v[u-1]+1;
		end;
		if b=1 then bootstrap=j(t,1)||a[v,];
		else bootstrap=bootstrap//(j(t,1,b)||a[v,]);
/*----------------------------------------------------------------------------*/
	end;
	create bootstrap from bootstrap[c="a"];
	append from bootstrap;
quit;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;For example, the bootstrap picks the random starting point from 1 to 636, say 235, and continues with a 90% probability to 236, 237, 238, ..., 241, and 242 and shifts with a 10% probability to another random point, say 7, and then continues again to 8, 9, 10, etc. until it completes one bootstrap with 636 observations. So the average block length becomes 10.&lt;/P&gt;&lt;P&gt;The bottleneck problem is that these random time indices are therefore somewhat path-dependent and cannot be generated via RAND or RANDGEN. I wonder whether there is a more efficient way to cleverly vectorize this part.&lt;/P&gt;</description>
      <pubDate>Tue, 22 Dec 2020 08:23:19 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707615#M5369</guid>
      <dc:creator>Junyong</dc:creator>
      <dc:date>2020-12-22T08:23:19Z</dc:date>
    </item>
    <item>
      <title>Re: How to Better Vectorize Block Bootstrap?</title>
      <link>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707644#M5370</link>
      <description>&lt;P&gt;Yes. Since you know that the final result will contain&amp;nbsp;&lt;SPAN&gt;636 rows, allocate pre-allocate arrays of that length. This avoids concatenating inside the loop, which is very inefficient.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;See&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://blogs.sas.com/content/iml/2011/06/20/pre-allocate-arrays-to-improve-efficiency.html" target="_self"&gt;&lt;SPAN&gt;"Pre-allocate arrays to improve efficiency"&lt;/SPAN&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;and&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://blogs.sas.com/content/iml/2015/02/16/friends-dont-let-friends-concatenate-results-inside-a-loop.html" target="_self"&gt;&lt;SPAN&gt;"Friends don't let friends concatenate results inside a loop"&lt;/SPAN&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You also know that the final bootstrap array will have 2500*636 rows. However, if the only purpose of the outer loop (do b = 1 to 2500) is to get values that you will write to a file, you can save a LOT of time and space by writing each bootstrap sample DIRECTLY to a SAS data set instead of building up the 'bootstrap' array. See &lt;A href="https://blogs.sas.com/content/iml/2019/05/13/write-results-inside-iml-loop.html" target="_self"&gt;"Write to a SAS data set from inside a SAS/IML loop."&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Tue, 22 Dec 2020 12:12:54 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707644#M5370</guid>
      <dc:creator>Rick_SAS</dc:creator>
      <dc:date>2020-12-22T12:12:54Z</dc:date>
    </item>
    <item>
      <title>Re: How to Better Vectorize Block Bootstrap?</title>
      <link>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707662#M5371</link>
      <description>&lt;P&gt;For example, I suspect this code will run much faster:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc iml;
   /* Use Sashelp.Air for example */
	use Sashelp.Air;
	read all var 'Air' into a;
   close;
	t=nrow(a);
	call streaminit(1);

   /* allocate and tell output data set how many cols to expect */
   bootstrap = j(t,1,.) || a;
   create bootstrap from bootstrap[c={"SampleID" "a"}];

   v = j(t,1,.);
	do b=1 to 2500;
/*----------------------------the bottleneck parts----------------------------*/
		do u=1 to t;
			if u=1 then v[u]=rand("integer",1,t);
			else if v[u-1]=t then v[u]=rand("integer",1,t);
			else if rand("uniform")&amp;gt;0.9 then v[u]=rand("integer",1,t);
			else v[u]=v[u-1]+1;
		end;
		bootstrap = j(t,1,b) || a[v,];
/*----------------------------------------------------------------------------*/
	   append from bootstrap;
	end;
   close;
quit;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Tue, 22 Dec 2020 14:11:35 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707662#M5371</guid>
      <dc:creator>Rick_SAS</dc:creator>
      <dc:date>2020-12-22T14:11:35Z</dc:date>
    </item>
    <item>
      <title>Re: How to Better Vectorize Block Bootstrap?</title>
      <link>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707741#M5372</link>
      <description>&lt;P&gt;Thanks for your advice, but can you check this out? This is your version.&lt;/P&gt;&lt;PRE&gt;&lt;CODE class="language-sas"&gt;proc iml;
   /* Use Sashelp.Air for example */
	use Sashelp.Air;
	read all var 'Air' into a;
   close;
	t=nrow(a);
	call streaminit(1);

   /* allocate and tell output data set how many cols to expect */
   bootstrap = j(t,1,.) || a;
   create bootstrap from bootstrap[c={"SampleID" "a"}];

   v = j(t,1,.);
	do b=1 to 2500;
/*----------------------------the bottleneck parts----------------------------*/
		do u=1 to t;
			if u=1 then v[u]=rand("integer",1,t);
			else if v[u-1]=t then v[u]=rand("integer",1,t);
			else if rand("uniform")&amp;gt;0.9 then v[u]=rand("integer",1,t);
			else v[u]=v[u-1]+1;
		end;
		bootstrap = j(t,1,b) || a[v,];
/*----------------------------------------------------------------------------*/
	   append from bootstrap;
	end;
   close;
quit;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Here is the log.&lt;/P&gt;&lt;PRE&gt;&lt;CODE class="language-sas"&gt;1    proc iml;
NOTE: IML Ready
2       /* Use Sashelp.Air for example */
3        use Sashelp.Air;
4        read all var 'Air' into a;
5       close;
NOTE: Closing SASHELP.AIR
6        t=nrow(a);
7        call streaminit(1);
8
9       /* allocate and tell output data set how many cols to expect */
10      bootstrap = j(t,1,.) || a;
11      create bootstrap from bootstrap[c={"SampleID" "a"}];
12
13      v = j(t,1,.);
14       do b=1 to 2500;
15   /*----------------------------the bottleneck parts----------------------------*/
16           do u=1 to t;
17               if u=1 then v[u]=rand("integer",1,t);
18               else if v[u-1]=t then v[u]=rand("integer",1,t);
19               else if rand("uniform")&amp;gt;0.9 then v[u]=rand("integer",1,t);
20               else v[u]=v[u-1]+1;
21           end;
22           bootstrap = j(t,1,b) || a[v,];
23   /*----------------------------------------------------------------------------*/
24          append from bootstrap;
25       end;
26      close;
NOTE: Closing WORK.BOOTSTRAP
NOTE: The data set WORK.BOOTSTRAP has 360000 observations and 2 variables.
27   quit;
NOTE: Exiting IML.
NOTE: PROCEDURE IML used (Total process time):
      real time           1.18 seconds
      cpu time            1.17 seconds&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;And the following does not pre-allocate.&lt;/P&gt;&lt;PRE&gt;&lt;CODE class="language-sas"&gt;proc iml;
   /* Use Sashelp.Air for example */
	use Sashelp.Air;
	read all var 'Air' into a;
   close;
	t=nrow(a);
	call streaminit(1);

   /* allocate and tell output data set how many cols to expect */
   bootstrap = j(t,1,.) || a;
   create bootstrap from bootstrap[c={"SampleID" "a"}];

/*   v = j(t,1,.);*/
	do b=1 to 2500;
/*----------------------------the bottleneck parts----------------------------*/
		do u=1 to t;
			if u=1 then v=rand("integer",1,t);
			else if v[u-1]=t then v=v//rand("integer",1,t);
			else if rand("uniform")&amp;gt;0.9 then v=v//rand("integer",1,t);
			else v=v//v[u-1]+1;
		end;
		bootstrap = j(t,1,b) || a[v,];
/*----------------------------------------------------------------------------*/
	   append from bootstrap;
	end;
   close;
quit;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;And the log.&lt;/P&gt;&lt;PRE&gt;&lt;CODE class="language-sas"&gt;28   proc iml;
NOTE: IML Ready
29      /* Use Sashelp.Air for example */
30       use Sashelp.Air;
31       read all var 'Air' into a;
32      close;
NOTE: Closing SASHELP.AIR
33       t=nrow(a);
34       call streaminit(1);
35
36      /* allocate and tell output data set how many cols to expect */
37      bootstrap = j(t,1,.) || a;
38      create bootstrap from bootstrap[c={"SampleID" "a"}];
39
40   /*   v = j(t,1,.);*/
41       do b=1 to 2500;
42   /*----------------------------the bottleneck parts----------------------------*/
43           do u=1 to t;
44               if u=1 then v=rand("integer",1,t);
45               else if v[u-1]=t then v=v//rand("integer",1,t);
46               else if rand("uniform")&amp;gt;0.9 then v=v//rand("integer",1,t);
47               else v=v//v[u-1]+1;
48           end;
49           bootstrap = j(t,1,b) || a[v,];
50   /*----------------------------------------------------------------------------*/
51          append from bootstrap;
52       end;
53      close;
NOTE: Closing WORK.BOOTSTRAP
NOTE: The data set WORK.BOOTSTRAP has 360000 observations and 2 variables.
54   quit;
NOTE: Exiting IML.
NOTE: PROCEDURE IML used (Total process time):
      real time           1.17 seconds
      cpu time            1.17 seconds&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;It seems there is no performance difference—I also tried 25,000 rather than 2,500 but found no difference.&lt;/P&gt;</description>
      <pubDate>Tue, 22 Dec 2020 19:31:22 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707741#M5372</guid>
      <dc:creator>Junyong</dc:creator>
      <dc:date>2020-12-22T19:31:22Z</dc:date>
    </item>
    <item>
      <title>Re: How to Better Vectorize Block Bootstrap?</title>
      <link>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707749#M5373</link>
      <description>&lt;P&gt;Right. The actual bottleneck in your program was the concatenation of the 'bootstrap' matrix within the outer loop. In your new test, both programs avoid that concatenation, which is why both programs run much faster than your first version.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 22 Dec 2020 20:26:24 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707749#M5373</guid>
      <dc:creator>Rick_SAS</dc:creator>
      <dc:date>2020-12-22T20:26:24Z</dc:date>
    </item>
    <item>
      <title>Re: How to Better Vectorize Block Bootstrap?</title>
      <link>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707755#M5374</link>
      <description>&lt;P&gt;So the takeaway is to use CREATE once and then APPEND repeatedly rather than // repeatedly then CREATE APPEND once—more than the pre-allocation issue (I will check this out in detail later). Thank you!&lt;/P&gt;</description>
      <pubDate>Tue, 22 Dec 2020 20:41:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707755#M5374</guid>
      <dc:creator>Junyong</dc:creator>
      <dc:date>2020-12-22T20:41:11Z</dc:date>
    </item>
    <item>
      <title>Re: How to Better Vectorize Block Bootstrap?</title>
      <link>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707758#M5375</link>
      <description>&lt;P&gt;They are both important. For this example, appending within the loop made a bigger impact on performance.&lt;/P&gt;</description>
      <pubDate>Tue, 22 Dec 2020 20:47:10 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707758#M5375</guid>
      <dc:creator>Rick_SAS</dc:creator>
      <dc:date>2020-12-22T20:47:10Z</dc:date>
    </item>
    <item>
      <title>Re: How to Better Vectorize Block Bootstrap?</title>
      <link>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707966#M5376</link>
      <description>&lt;P&gt;It seems the case above isn't good enough to see the performance gain—the following substantially shows the gain instead. Thanks.&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc iml;
	i=j(500,10);
	call randseed(1);
	do j=1 to 5000;
		call randgen(i,"normal");
		if j=1 then k=vech(cov(i));
		else k=k||vech(cov(i));
	end;
quit;
proc iml;
	i=j(500,10);
	call randseed(1);
	k=j(55,5000);
	do j=1 to 5000;
		call randgen(i,"normal");
		k[,j]=vech(cov(i));
	end;
quit;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;And the results.&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;1    proc iml;
NOTE: IML Ready
2        i=j(500,10);
3        call randseed(1);
4        do j=1 to 5000;
5            call randgen(i,"normal");
6            if j=1 then k=vech(cov(i));
7            else k=k||vech(cov(i));
8        end;
9    quit;
NOTE: Exiting IML.
NOTE: PROCEDURE IML used (Total process time):
      real time           4.17 seconds
      cpu time            4.18 seconds


10   proc iml;
NOTE: IML Ready
11       i=j(500,10);
12       call randseed(1);
13       k=j(55,5000);
14       do j=1 to 5000;
15           call randgen(i,"normal");
16           k[,j]=vech(cov(i));
17       end;
18   quit;
NOTE: Exiting IML.
NOTE: PROCEDURE IML used (Total process time):
      real time           1.60 seconds
      cpu time            1.60 seconds&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;The latter is about 60% faster than the former. Significant.&lt;/P&gt;</description>
      <pubDate>Wed, 23 Dec 2020 19:51:04 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707966#M5376</guid>
      <dc:creator>Junyong</dc:creator>
      <dc:date>2020-12-23T19:51:04Z</dc:date>
    </item>
    <item>
      <title>Re: How to Better Vectorize Block Bootstrap?</title>
      <link>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707975#M5377</link>
      <description>&lt;P&gt;Yes. The articles that I linked to in my initial reply have similar examples.&lt;/P&gt;</description>
      <pubDate>Wed, 23 Dec 2020 20:13:31 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/707975#M5377</guid>
      <dc:creator>Rick_SAS</dc:creator>
      <dc:date>2020-12-23T20:13:31Z</dc:date>
    </item>
    <item>
      <title>Re: How to Better Vectorize Block Bootstrap?</title>
      <link>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/715027#M5392</link>
      <description>&lt;P&gt;This topic inspired me to write a few articles about various ways to perform block bootstraps in SAS:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="https://blogs.sas.com/content/iml/2021/01/06/simple-block-bootstrap-sas.html" target="_self"&gt;The simple block bootstrap for time series in SAS&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://blogs.sas.com/content/iml/2021/01/13/moving-block-bootstrap-sas.html" target="_self"&gt;The moving block bootstrap for time series&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://blogs.sas.com/content/iml/2021/01/20/stationary-bootstrap-sas.html" target="_self"&gt;The stationary block bootstrap in SAS&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;</description>
      <pubDate>Thu, 28 Jan 2021 15:33:41 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/How-to-Better-Vectorize-Block-Bootstrap/m-p/715027#M5392</guid>
      <dc:creator>Rick_SAS</dc:creator>
      <dc:date>2021-01-28T15:33:41Z</dc:date>
    </item>
  </channel>
</rss>

