<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>AR &#8211; Aptech</title>
	<atom:link href="https://www.aptech.com/blog/tag/ar/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.aptech.com</link>
	<description>GAUSS Software - Fastest Platform for Data Analytics</description>
	<lastBuildDate>Mon, 22 Jan 2024 15:19:30 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>Make your time series computations up to 20 times faster</title>
		<link>https://www.aptech.com/blog/make-your-time-series-computations-up-to-20-times-faster/</link>
					<comments>https://www.aptech.com/blog/make-your-time-series-computations-up-to-20-times-faster/#respond</comments>
		
		<dc:creator><![CDATA[aptech]]></dc:creator>
		<pubDate>Thu, 11 Oct 2018 19:37:54 +0000</pubDate>
				<category><![CDATA[Time Series]]></category>
		<category><![CDATA[AR]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[speed]]></category>
		<category><![CDATA[vectorization]]></category>
		<guid isPermaLink="false">https://www.aptech.com/?p=17487</guid>

					<description><![CDATA[The key to getting the most performance from a matrix language is to vectorize your code as much as possible. Vectorized code performs operations on large sections of matrices and vectors in a single operation, rather than looping over the elements one-by-one. In this blog, we learn how to use the GAUSS recserar function to vectorize code and simulate a time series AR(1) model.]]></description>
										<content:encoded><![CDATA[<h3 id="introduction">Introduction</h3>
<p>The key to getting the most performance from a <a href="https://www.aptech.com/blog/gauss-basics-3-introduction-to-matrices/" target="_blank" rel="noopener">matrix</a> language is to vectorize your code as much as possible. Vectorized code performs operations on large sections of matrices and vectors in a single operation, rather than looping over the elements one-by-one.</p>
<p>For example, we could scale a vector by looping over each element:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Create a random normal vector
// with 10 elements
x = rndn(10,1);

// NOT Vectorized
// Loop through each element
// in 'x' and multiply by 3
for i(1, rows(x), 1);
    x[i] = x[i] * 3;
endfor;</code></pre>
<p>or we could perform all of the multiplications in a single call:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Vectorized
// Scale each element of 'x'
// with a single operation
x = x * 3;</code></pre>
<p>Not only is the second version much shorter, but it is also approximately 10 times faster.</p>
<h2 id="challenges-to-vectorizing-time-series-code">Challenges to vectorizing time series code</h2>
<p>Our initial example cut the lines of code by one third and ran 10 times more quickly. Clearly, this technique is valuable, but not all cases are as simple. Let's start by looking at the standard AR(1) model for <a href="https://www.aptech.com/blog/introduction-to-the-fundamentals-of-time-series-data-and-analysis/" target="_blank" rel="noopener">time series data</a>:</p>
<p>$$y_t = C + \rho y_{t-1} + \epsilon_t$$</p>
<p>Let's start by writing a non-vectorized version of this equation:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Number of observations to simulate
nobs = 5;

// Constant initial value
C = 1;

// AR parameter
rho = 0.3;

// Set random seed for repeatable random numbers
rndseed 5423;

// Pre-allocate vector for the output 'y'
y = C | zeros(nobs, 1);

// Create error term
epsilon = rndn(rows(y), 1);

// Simulate the AR(1) process
for t(2, nobs + 1, 1);
    y[t] = y[t-1] * rho + epsilon[t];
endfor;</code></pre>
<h2 id="loop-carried-dependencies">Loop-carried dependencies</h2>
<p>The problem which prevents us from vectorizing the AR(1) simulation (or parallelizing it) is that each iteration of the loop depends upon the result from the previous iteration. This is the definition of a loop-carried dependence.</p>
<h2 id="vectorizing-an-ar-process-with-recserar">Vectorizing an AR process with recserar</h2>
<p>Fortunately, <a href="https://www.aptech.com/blog/introducing-gauss-24/" target="_blank" rel="noopener">GAUSS</a> has a built-in function for exactly this type of problem, <a href="https://docs.aptech.com/gauss/recserar.html" target="_blank" rel="noopener"><code>recserar</code></a>. In terms of an AR(1) model, <code>recserar</code> has the following inputs:</p>
<hr>
<dl>
<dt>epsilon</dt>
<dd>A Tx1 matrix, the error term.</dd>
<dt>C</dt>
<dd>A scalar, the initial value of the time series.</dd>
<dt>rho</dt>
<dd>A scalar, the AR parameter.</dd>
</dl>
<hr>
<p>Using <code>recserar</code> the code would look like this:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">
// Number of observations to simulate
nobs = 5;

// Constant initial value
C = 1;

// AR parameter
rho = 0.3;

// Set random seed for repeatable random numbers
rndseed 5423;

// Create error term
epsilon = rndn(nobs+1, 1);

// Simulate the AR(1) process
y_vec = recserar(epsilon, C, rho);</code></pre>
<div style="text-align:center;background-color:#f0f2f4"><hr>Ready to speed up your time series analysis? <a href="https://www.aptech.com/request-demo/">Start your GAUSS demo today!<hr></a></div>
<h2 id="results">Results</h2>
<p><a href="https://www.aptech.com/wp-content/uploads/2018/10/recserar_speedup_07_2018.png"><img src="https://www.aptech.com/wp-content/uploads/2018/10/recserar_speedup_07_2018.png" alt="Speed increases from simulating AR process with recserar in GAUSS." width="400" height="300" class="aligncenter size-full wp-image-17494" /></a></p>
<p>The speed-up that you see from this change is mainly a function of the length of the number of elements in the vector. In the testing for this post, the <code>recserar</code> version ran up to around 20 times faster as shown in the graph above.</p>
<h3 id="conclusion">Conclusion</h3>
<p>In this post we saw how the GAUSS <code>recserar</code> function can be used to vectorize code with loop-carried dependencies like the simulation of an AR(1) model, giving speed-ups of up to 20 times. </p>
<p>This pattern comes up often in other time series models such as <a href="https://docs.aptech.com/gauss/tsmt/garchfit.html" target="_blank" rel="noopener">GARCH</a>. However, it is not exclusive to time series, so keep it in mind whenever you find a loop that is difficult to vectorize.</p>
<p>Code and data from this blog can be found <a href="https://github.com/aptech/gauss_blog/tree/master/programming/faster-time-series-10.11.18">here</a>.</p>
    <!-- MathJax configuration -->
    <style>
        .mjx-svg-href {
            fill: "inherit" !important;
            stroke: "inherit" !important;
        }
    </style>
    <script type="text/x-mathjax-config">
        MathJax.Hub.Config({ TeX: { equationNumbers: {autoNumber: "AMS"} } });
    </script>
    <script type="text/javascript">
window.MathJax = {
  tex2jax: {
    inlineMath: [ ['$','$'] ],
    displayMath: [ ['$$','$$'] ],
    processEscapes: true,
    processEnvironments: true
  },
  // Center justify equations in code and markdown cells. Elsewhere
  // we use CSS to left justify single line equations in code cells.
  displayAlign: 'center',
  "HTML-CSS": {
    styles: {'.MathJax_Display': {"margin": 0}},
    linebreaks: { automatic: false }
  },
  "SVG": {
    styles: {'.MathJax_SVG_Display': {"margin": 0}},
    linebreaks: { automatic: false }
  },
  showProcessingMessages: false,
  messageStyle: "none",
  menuSettings: { zoom: "Click" },
  AuthorInit: function() {
    MathJax.Hub.Register.StartupHook("End", function() {
            var timeout = false, // holder for timeout id
            delay = 250; // delay after event is "complete" to run callback
            var shrinkMath = function() {
              //var dispFormulas = document.getElementsByClassName("formula");
              var dispFormulas = document.getElementsByClassName("MathJax_SVG_Display");
              if (dispFormulas){
                // caculate relative size of indentation
                var contentTest = document.getElementsByTagName("body")[0];
                var nodesWidth = contentTest.offsetWidth;
                // if you have indentation
                var mathIndent = MathJax.Hub.config.displayIndent; //assuming px's
                var mathIndentValue = mathIndent.substring(0,mathIndent.length - 2);
                for (var i=0; i<dispFormulas.length; i++){
                  var dispFormula = dispFormulas[i];
                  var wrapper = dispFormula;
                  //var wrapper = dispFormula.getElementsByClassName("MathJax_Preview")[0].nextSibling;
                  var child = wrapper.firstChild;
                  wrapper.style.transformOrigin = "center"; //or top-left if you left-align your equations
                  var oldScale = child.style.transform;
                  //var newValue = Math.min(0.80*dispFormula.offsetWidth / child.offsetWidth,1.0).toFixed(2);
                  var newValue = Math.min(dispFormula.offsetWidth / child.offsetWidth,1.0).toFixed(2);
                  var newScale = "scale(" + newValue + ")";
                  if(newValue != "NaN" && !(newScale === oldScale)){
                    wrapper.style.transform = newScale;
                    wrapper.style["margin-left"]= Math.pow(newValue,4)*mathIndentValue + "px";
                    var wrapperStyle = window.getComputedStyle(wrapper);
                    var wrapperHeight = parseFloat(wrapperStyle.height);
                    wrapper.style.height = "" + (wrapperHeight * newValue) + "px";
                    if(newValue === "1.00"){
                      wrapper.style.cursor = "";
                      wrapper.style.height = "";
                    }
                    else {
                      wrapper.style.cursor = "zoom-in";
                    }
                  }

                }
            }
            };
            shrinkMath();
            window.addEventListener('resize', function() {
              clearTimeout(timeout);
              timeout = setTimeout(shrinkMath, delay);
            });
          });
  }
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-AMS_SVG"></script>]]></content:encoded>
					
					<wfw:commentRss>https://www.aptech.com/blog/make-your-time-series-computations-up-to-20-times-faster/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
