<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4503331028356521241</id><updated>2012-02-12T19:48:43.366-05:00</updated><category term='computer science'/><category term='math'/><category term='algorithms'/><category term='http'/><category term='wifi'/><category term='assembly'/><category term='haskell'/><category term='cpu'/><category term='programming'/><category term='e-book'/><category term='c'/><title type='text'>Holden's Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://voigtkampff.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4503331028356521241/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://voigtkampff.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jason Schulz</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-k3_hVIfKx_o/AAAAAAAAAAI/AAAAAAAABfY/xyNnlt_zUSs/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>4</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4503331028356521241.post-6448463546216301825</id><published>2012-02-05T11:46:00.000-05:00</published><updated>2012-02-12T19:32:41.862-05:00</updated><title type='text'>Address Changed</title><content type='html'>As of 2012-02-12 I'll be changing the address of my blog from voigtkampff.blogspot.com to lucidswingset.blogspot.com. &amp;nbsp;After that, you'll still be able to read old posts using the voigtkampff address. &amp;nbsp;Nothing new will be posted to it though. &amp;nbsp;Everything new will be posted to lucidswingset.&lt;br /&gt;&lt;br /&gt;I plan on keeping voigtkampff accessible, but I do eventually want to give the name back to Blogger. &amp;nbsp;So if you're a Blade Runner fan and you're looking for a place to speak your mind, let me know.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4503331028356521241-6448463546216301825?l=voigtkampff.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://voigtkampff.blogspot.com/feeds/6448463546216301825/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://voigtkampff.blogspot.com/2012/02/as-of-2012-02-12-ill-be-changing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4503331028356521241/posts/default/6448463546216301825'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4503331028356521241/posts/default/6448463546216301825'/><link rel='alternate' type='text/html' href='http://voigtkampff.blogspot.com/2012/02/as-of-2012-02-12-ill-be-changing.html' title='Address Changed'/><author><name>Jason Schulz</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-k3_hVIfKx_o/AAAAAAAAAAI/AAAAAAAABfY/xyNnlt_zUSs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4503331028356521241.post-8476513992767131882</id><published>2012-01-25T12:48:00.000-05:00</published><updated>2012-02-12T19:31:58.492-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='http'/><category scheme='http://www.blogger.com/atom/ns#' term='e-book'/><category scheme='http://www.blogger.com/atom/ns#' term='wifi'/><title type='text'>Wireless Book Management On The Sony PRS</title><content type='html'>The Sony &lt;a href="http://en.wikipedia.org/wiki/Sony_Reader"&gt;PRS&lt;/a&gt;&amp;nbsp;is an excellent e-reader for the price. &amp;nbsp;However, there was one minor thing that bothered me. &amp;nbsp;Every time I wanted to read something on it, I needed to start a computer, connect the USB cable, start the management software, and finally copy over the book. &amp;nbsp;Since the&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Sony_Reader"&gt;PRS&lt;/a&gt;&amp;nbsp;I have has a built-in 802.11g radio it seemed like there should be a less wired, less time consuming way of getting stuff to read onto the&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Sony_Reader"&gt;PRS&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;All of the&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Sony_Reader"&gt;PRS&lt;/a&gt;&amp;nbsp;e-readers have built-in web browsers. &amp;nbsp;So, exposing the files via HTTP seemed like the most probable solution. &amp;nbsp;However, Sony's browser only supports downloading HTML files via HTTP GET. &amp;nbsp;For example if you try downloading an epub or pdf from&amp;nbsp;&lt;a href="http://www.gutenberg.org/"&gt;project gutenberg&lt;/a&gt;,&amp;nbsp;you'll get a message about the file type not being supported. &amp;nbsp; Thankfully though, the underlying operating system for the&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Sony_Reader"&gt;PRS&lt;/a&gt;&amp;nbsp;is&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/MontaVista"&gt;montavista linux&lt;/a&gt;. &amp;nbsp;That means compiling additional software for it, like&amp;nbsp;&lt;a href="http://lynx.browser.org/"&gt;lynx&lt;/a&gt;&amp;nbsp;or&amp;nbsp;&lt;a href="http://www.gnu.org/software/wget/"&gt;wget&lt;/a&gt;,&amp;nbsp;is possible.&lt;br /&gt;&lt;br /&gt;This is exactly what the&amp;nbsp;&lt;a href="http://code.google.com/p/prs-plus/"&gt;PRS+&lt;/a&gt;&amp;nbsp;project has done*. &amp;nbsp;Like the name suggests, it adds a number of features to the stock Sony firmware. &amp;nbsp;One of the features is the ability to download files via HTTP using the built-in web browser (friendly warning, only un-authenticated HTTP currently works).&lt;br /&gt;&lt;br /&gt;The last thing necessary was an&amp;nbsp;&lt;a href="http://httpd.apache.org/"&gt;apache&lt;/a&gt;&amp;nbsp;webserver (any webserver&amp;nbsp;with directory indexing should work though)**. &amp;nbsp;Once setup, &lt;a href="http://httpd.apache.org/docs/current/mod/mod_autoindex.html"&gt;mod_autoindex&lt;/a&gt;&amp;nbsp;will generate HTML listings for any directories configured to be indexed.&lt;br /&gt;&lt;br /&gt;Et, voila...&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-2onA06vCn_g/Tx96kaspHRI/AAAAAAAABeU/sOHOlHED8D8/s1600/prs_plus_browser_root.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://4.bp.blogspot.com/-2onA06vCn_g/Tx96kaspHRI/AAAAAAAABeU/sOHOlHED8D8/s200/prs_plus_browser_root.png" width="116" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://2.bp.blogspot.com/-YHUvE7AVDcY/Tx96lN-M_MI/AAAAAAAABek/oSNQalbtjac/s1600/prs_plus_home_new.png" imageanchor="1" style="clear: left; display: inline !important; margin-bottom: 1em; margin-right: 1em; text-align: left;"&gt;&lt;img border="0" height="200" src="http://2.bp.blogspot.com/-YHUvE7AVDcY/Tx96lN-M_MI/AAAAAAAABek/oSNQalbtjac/s200/prs_plus_home_new.png" width="116" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;*&amp;nbsp;Installing&amp;nbsp;&lt;a href="http://code.google.com/p/prs-plus/"&gt;PRS+&lt;/a&gt;&amp;nbsp;almost certainly voids the warranty on the&amp;nbsp;&lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Sony_Reader"&gt;&lt;span style="font-size: x-small;"&gt;PRS&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;. &amp;nbsp;You can potentially turn it into an expensive paper weight. &amp;nbsp;If you're still willing to install&amp;nbsp;&lt;a href="http://code.google.com/p/prs-plus/"&gt;PRS+&lt;/a&gt;, the&amp;nbsp;&lt;a href="http://code.google.com/p/prs-plus/wiki/InstallGuide"&gt;install guide&lt;/a&gt;&amp;nbsp;will walk you through the process.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;** Web servers are probably the biggest security exploit route. &amp;nbsp;if you plan on running a personal web server, consider&amp;nbsp;reading up on securing it (i.e. authentication, authorization, minimal privileges, etc...).&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4503331028356521241-8476513992767131882?l=voigtkampff.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://voigtkampff.blogspot.com/feeds/8476513992767131882/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://voigtkampff.blogspot.com/2012/01/sony-prs-excellent-e-reader-for-price.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4503331028356521241/posts/default/8476513992767131882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4503331028356521241/posts/default/8476513992767131882'/><link rel='alternate' type='text/html' href='http://voigtkampff.blogspot.com/2012/01/sony-prs-excellent-e-reader-for-price.html' title='Wireless Book Management On The Sony PRS'/><author><name>Jason Schulz</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-k3_hVIfKx_o/AAAAAAAAAAI/AAAAAAAABfY/xyNnlt_zUSs/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-2onA06vCn_g/Tx96kaspHRI/AAAAAAAABeU/sOHOlHED8D8/s72-c/prs_plus_browser_root.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4503331028356521241.post-8131565710834712209</id><published>2011-11-01T12:47:00.000-04:00</published><updated>2012-02-12T19:30:51.358-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='algorithms'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='computer science'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>The Importance of Algorithmic Complexity</title><content type='html'>So, it's been a while since the last time I updated the blog and I figured I'd do a basic writeup just to keep it from falling into abysmal obscurity. &amp;nbsp;I'm not sure how many people are following this. &amp;nbsp;Still, even if nobody is reading it, I find it cathartic to do writeups from time to time.&lt;br /&gt;&lt;br /&gt;Recently, I was faced with a problem that required less of a focus on low-level performance than an efficient algorithm. &amp;nbsp;My first attempt at a solution seemed to be caught in an infinite loop. &amp;nbsp;At first I thought there may be a bug, but after reading over the code I realized that the algorithm just had horrific asymptotic growth. &amp;nbsp;Ultimately, I had to come up with a more efficient algorithm.&lt;br /&gt;&lt;br /&gt;I thought it was interesting to be able to apply some of the theoretical aspects of computer science to a tangible problem. So, I figured I would talk a little about&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Analysis_of_algorithms"&gt;algorithm complexity&lt;/a&gt;, as a bit of a refresher for me, and hopefully to spark an interest an anybody who might happen to be read this.&lt;br /&gt;&lt;br /&gt;Most of us probably remember algorithm complexity as &lt;i&gt;&lt;b&gt;Big O&lt;/b&gt; &lt;/i&gt;(asymptotic upper bound)&lt;i&gt;, &lt;/i&gt;with the canonical example being&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Quicksort"&gt;quicksort&lt;/a&gt;&lt;i&gt;&amp;nbsp;f(n) = O(n&lt;/i&gt;&lt;sup style="font-style: italic;"&gt;2&lt;/sup&gt;&lt;i&gt;)&lt;/i&gt;&amp;nbsp;for&amp;nbsp;run-time complexity.  There are corresponding asymptotic lower bounds, &lt;b&gt;&lt;i&gt;Big&amp;nbsp;&lt;/i&gt;&lt;i&gt;Ω&lt;/i&gt;&lt;/b&gt;, and upper and lower bounds, &lt;i&gt;&lt;b&gt;Big&amp;nbsp;&lt;/b&gt;&lt;/i&gt;&lt;b&gt;Θ&lt;/b&gt;. &amp;nbsp;Asymptotic growth can also be used to describe spatial complexity (&lt;i&gt;f(n) =O(n)&lt;/i&gt; for in-place quicksort IIRC). &amp;nbsp;However, I wanted to focus on run-time complexity since most of the problems I've seen are typically constrained by time, not space.&lt;br /&gt;&lt;br /&gt;In order to talk about complexity, I figured I would work through one of the&amp;nbsp;&lt;a href="http://projecteuler.net/"&gt;project euler&lt;/a&gt;&amp;nbsp;problems. &amp;nbsp;If you haven't already been to the project euler site, it's great place&amp;nbsp;for finding mathematical problems that can be solved with code. &amp;nbsp;Occasionally, you can solve them without it, but typically you need a computer. &amp;nbsp;Most of the problems tend to be intractable via brute force, which is why I thought it would make a good example for demonstrating the effect of complexity on realized run-time.&lt;br /&gt;&lt;br /&gt;I've been learning &lt;a href="http://haskell.org/haskellwiki/Haskell"&gt;haskell&lt;/a&gt;&amp;nbsp;recently, which seems to be a succinct language for solving these types of problems. &amp;nbsp;So, all of the following code examples will be expressed therein. &amp;nbsp;If you don't know the language, the examples should still be very intuitive, due to haskell's brevity.&lt;br /&gt;&lt;br /&gt;The specific &lt;a href="http://projecteuler.net/problem=12"&gt;problem&lt;/a&gt;&amp;nbsp;I'll be using has to do with&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Triangle_number"&gt;triangle numbers&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large; font-style: italic;"&gt;"What is the value of the first triangle number to have over five hundred divisors?"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So, the first algorithm that comes to mind is to simply compute each of the triangle numbers, and iterate over the integers from one to the number, counting each of the divisors. &amp;nbsp;The code to do this is pretty simple, and looks something like this:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;i&gt;&lt;a href="http://1.bp.blogspot.com/-r805uu1l8Ac/Tq-cW4nmbyI/AAAAAAAABZI/G4dhRqQV7hs/s1600/eulern2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="100" src="http://1.bp.blogspot.com/-r805uu1l8Ac/Tq-cW4nmbyI/AAAAAAAABZI/G4dhRqQV7hs/s400/eulern2.png" width="400" /&gt;&lt;/a&gt;&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;It's a simple algorithm, but unfortunately it is also horribly inefficient. &amp;nbsp;It should give a good starting point to developing the real solution though. &amp;nbsp;Looking at the code tells us the algorithm to compute triangle number n, and determine the number of divisors it has is &lt;i style="font-style: italic;"&gt;O(n&lt;/i&gt;&lt;i&gt;√n&lt;/i&gt;&lt;i&gt;)&lt;/i&gt;, n being the triangle number&lt;i&gt;.&lt;/i&gt; &amp;nbsp;Actually, the algorithm is also&lt;i&gt;&amp;nbsp;Ω(&lt;/i&gt;&lt;i&gt;n&lt;/i&gt;&lt;i&gt;√n&lt;/i&gt;&lt;i&gt;)&lt;/i&gt;, which is even worse. &amp;nbsp;Consider the fact we're looking for a number with over 500 divisors, and you can see how the run-time explodes. &amp;nbsp;This algorithm sadly wouldn't find the correct answer even if it were given a month.&lt;br /&gt;&lt;br /&gt;So, the obvious solution doesn't cut it. &amp;nbsp;How can the algorithm be changed so the correct triangle number can be found in a reasonable amount of time? &amp;nbsp;Well, at the core of the algorithm there are two algorithms, namely the algorithm to compute triangle numbers, and the algorithm to determine the number of divisors. &amp;nbsp;Computing the triangle numbers is&amp;nbsp;&lt;i&gt;Ω(&lt;/i&gt;&lt;i&gt;√n&lt;/i&gt;&lt;i&gt;)&lt;/i&gt;, and finding divisors is&amp;nbsp;&lt;i&gt;Ω(&lt;/i&gt;&lt;i&gt;n&lt;/i&gt;&lt;i&gt;). &amp;nbsp;&lt;/i&gt;So, the asymptotic growth of one or both of those functions needs to be improved. &amp;nbsp;It just so happens that there is a very simple modification that can be made to change the run-time of one of the algorithms to &lt;i&gt;O(1).&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;i&gt;&lt;a href="http://4.bp.blogspot.com/-fHMUzRqc_AY/Tq-cgeorDwI/AAAAAAAABZQ/Ph52Xw3oYr4/s1600/eulern.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="100" src="http://4.bp.blogspot.com/-fHMUzRqc_AY/Tq-cgeorDwI/AAAAAAAABZQ/Ph52Xw3oYr4/s400/eulern.png" width="400" /&gt;&lt;/a&gt;&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;The change to the algorithm computes each triangle number using a simple &lt;i style="font-style: italic;"&gt;O(1)&lt;/i&gt;&amp;nbsp;calculation. &amp;nbsp;This calculation is a corollary of a formula, anecdotally attributed to &lt;a href="http://en.wikipedia.org/wiki/Carl_Friedrich_Gauss"&gt;Gauss&lt;/a&gt;&lt;span style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;. &amp;nbsp;The formula is&amp;nbsp;&lt;/span&gt;Σ (k) {k: 1,n} = n(n + 1) / 2&lt;/span&gt;, which&amp;nbsp;is easily verified through&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Mathematical_induction"&gt;induction&lt;/a&gt;&lt;span style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;. &amp;nbsp;This is an order of magnitude better than the first iteration, but the overall algorithm is still&amp;nbsp;&lt;/span&gt;Ω(n)&lt;/span&gt;, which would likely take more than a few minutes to run. &amp;nbsp;Surely there must be a way to further cut down asymptotic growth; Of course, there is:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-JlrKADfFDsE/TrKcqQjN-fI/AAAAAAAABZo/9EmAH-sBYrw/s1600/eulersqn.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="332" src="http://1.bp.blogspot.com/-JlrKADfFDsE/TrKcqQjN-fI/AAAAAAAABZo/9EmAH-sBYrw/s400/eulersqn.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The final algorithm has a run-time growth of &lt;i style="font-style: italic;"&gt;O(√n)&lt;/i&gt;, which I suspect is optimal for this particular problem. It takes advantage of the fact that all divisors of a number, consist of a combination of its prime factors (&lt;a href="http://en.wikipedia.org/wiki/Fundamental_theorem_of_arithmetic"&gt;fundamental theorem of arithmetic&lt;/a&gt;). &amp;nbsp;Searching for prime factors of an integer is &lt;i style="font-style: italic;"&gt;O(√n)&lt;/i&gt;, since no integer can consist of primes larger than its square root.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;br /&gt;So, starting out, we only had a simple, but asymptotically horrible,&amp;nbsp;&lt;i&gt;Ω(n&lt;/i&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;√n&lt;/span&gt;&lt;i&gt;)&lt;/i&gt; &lt;span style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;algorithm that would take a tremendous amount of time to finish. &amp;nbsp;However, by taking advantage of a few simple properties of integers, a simple&amp;nbsp;&lt;/span&gt;O(√n)&lt;/span&gt;&amp;nbsp;algorithm that finishes in a reasonable amount of time could be easily derived.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4503331028356521241-8131565710834712209?l=voigtkampff.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://voigtkampff.blogspot.com/feeds/8131565710834712209/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://voigtkampff.blogspot.com/2011/11/importance-of-algorithmic-complexity.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4503331028356521241/posts/default/8131565710834712209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4503331028356521241/posts/default/8131565710834712209'/><link rel='alternate' type='text/html' href='http://voigtkampff.blogspot.com/2011/11/importance-of-algorithmic-complexity.html' title='The Importance of Algorithmic Complexity'/><author><name>Jason Schulz</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-k3_hVIfKx_o/AAAAAAAAAAI/AAAAAAAABfY/xyNnlt_zUSs/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-r805uu1l8Ac/Tq-cW4nmbyI/AAAAAAAABZI/G4dhRqQV7hs/s72-c/eulern2.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4503331028356521241.post-3896143987655823423</id><published>2011-06-28T00:48:00.000-04:00</published><updated>2012-02-12T19:30:51.345-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cpu'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><category scheme='http://www.blogger.com/atom/ns#' term='assembly'/><title type='text'>Enumerating Intel 64 Topology</title><content type='html'>First, if anyone is stumbled here through facebook, let me apologize for misleading you. &amp;nbsp;IA-64 is actually Intel's first 64 bit architecture, Itanium. &amp;nbsp;I don't plan on running on Itanium. &amp;nbsp;Having said that, if someone wants to send me the hardware, I'm sure I can figure something out :).&lt;br /&gt;&lt;br /&gt;So, one of the projects I'm working on is a performance sensitive application. &amp;nbsp;For this reason, I wanted to have a good way of understanding the inner workings of the CPU the software would be running on. &amp;nbsp;Just because something fits in a single line of code, doesn't always mean it's effective or efficient. &amp;nbsp;What hardware actually does with software has to be considered when the software functions in terms of milliseconds and microseconds. &amp;nbsp;More importantly, how the hardware is used becomes critical. &amp;nbsp;This is why I wrote a relatively simple app to give me some of the gory details about the actual system it's running against.&lt;br /&gt;&lt;br /&gt;There are kind of a few ways of getting information about hardware you plan on running on. &amp;nbsp;Hardware specifications are probably the most obvious, benchmarks are a little better, firsthand accounts are better still. &amp;nbsp;However, for what I wanted to know, these things really don't tell the whole story.&lt;br /&gt;&lt;br /&gt;I chose to take advantage of the CPUID instruction available in the x86 instruction set. &amp;nbsp;CPUID is kind of a treasure trove of data. &amp;nbsp;Actually, a more accurate description would be random piles of papers with random chunks of information spread across them. &amp;nbsp;CPUID seems to be somewhat of a historical architecture record at least for Intel.&lt;br /&gt;&lt;br /&gt;What I was trying to figure out was the actual topology of the logical CPUs in a system. &amp;nbsp;Since different CPUs will behave with different overall latencies, and typically different cache and memory latencies, knowing this information is important.&lt;br /&gt;&lt;br /&gt;Reading through the Intel Programmer Reference, I could only see a couple ways of accomplishing the task at hand. &amp;nbsp;CPUID leaf '0x4' (cache parameters), and leaf '0xb' (extended topology). &amp;nbsp;Leaf '0xb' is significantly easier to work with, but isn't available on older Intel CPUs (Intel Atom doesn't support it). &amp;nbsp;I expect to be running on older and newer processors, so I ended up writing the code for both. &amp;nbsp;The code to extract the info from '0xb' is trivial, and kind of not interesting. &amp;nbsp;However, using '0x4' required a little insight and some clever bit twiddling. &lt;br /&gt;&lt;br /&gt;&lt;img src="http://i.imgur.com/etVJo.png" title="Topology Code Snippet" /&gt;&lt;br /&gt;&lt;br /&gt;The code's a little messy, but essentially what it does is takes adjacent topology counts, and using both of them, generate a unique id for a level .  Using these id's, you can figure out precisely which siblings are closest to eachother, which CPUs potentially share L1 and/or L2 cache, so on and so on.&lt;br /&gt;&lt;br /&gt;This kind of information is almost always used by operating system schedulers. &amp;nbsp;In addition, compilers typically (hopefully) take this information into account when they generate the machine code that will actually run against the hardware. &amp;nbsp;Another possible use might be highly detailed, low level benchmarks.&lt;br /&gt;&lt;br /&gt;If anyone has any questions, please either drop it in the comments or let me know and I promise to answer it as time permits. &amp;nbsp;Also, if anyone has any corrections or additions, please drop it in the comments or let me know and I'll make an update.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4503331028356521241-3896143987655823423?l=voigtkampff.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://voigtkampff.blogspot.com/feeds/3896143987655823423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://voigtkampff.blogspot.com/2011/06/enumerating-intel-64-topology.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4503331028356521241/posts/default/3896143987655823423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4503331028356521241/posts/default/3896143987655823423'/><link rel='alternate' type='text/html' href='http://voigtkampff.blogspot.com/2011/06/enumerating-intel-64-topology.html' title='Enumerating Intel 64 Topology'/><author><name>Jason Schulz</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-k3_hVIfKx_o/AAAAAAAAAAI/AAAAAAAABfY/xyNnlt_zUSs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry></feed>
