<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<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/"
	>

<channel>
	<title>tr1 &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://en.wordpress.com/tag/tr1/</link>
	<description>Feed of posts on WordPress.com tagged "tr1"</description>
	<pubDate>Sun, 29 Nov 2009 22:48:10 +0000</pubDate>

	<generator>http://en.wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[Cargo Cult Programming (part 1)]]></title>
<link>http://hbfs.wordpress.com/2009/10/13/cargo-cult-programming-part-1/</link>
<pubDate>Tue, 13 Oct 2009 10:47:54 +0000</pubDate>
<dc:creator>Steven Pigeon</dc:creator>
<guid>http://hbfs.wordpress.com/2009/10/13/cargo-cult-programming-part-1/</guid>
<description><![CDATA[Programmers aren&#8217;t always the very rational beings they please themselves to believe. Very oft]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Programmers aren&#8217;t always the very rational beings they please themselves to believe. Very often, we close our eyes and take decisions based on what we <em>think</em> we know, and based on what have been told by more or less reliable sources. Such as, for example, taking <a href="http://en.wikipedia.org/wiki/Red-black_tree" target="_blank">red-black</a> trees rather than <a href="http://en.wikipedia.org/wiki/AVL_tree" target="_blank">AVL</a> trees because they are faster, while not being able to quite justify in the details why it must be so. Programming using this kind of decision I call <em>cargo cult programming</em>.</p>
<p><a href="http://en.wikipedia.org/wiki/File:CMA_CGM_Balzac.jpg"><img src="http://hbfs.wordpress.com/files/2009/08/cargo.jpg?w=300" alt="cargo" title="cargo" width="400" height="179" class="aligncenter size-medium wp-image-1539" /></a></p>
<p>Originally, I wanted to talk about red-black <em>vs.</em> AVL trees and how they compare, but I&#8217;ll rather talk about the STL <tt>std::map</tt> that is implemented using red-black trees with G++ 4.2, and <tt>std::unordered_map</tt>, a <a href="http://en.wikipedia.org/wiki/Hash_table" target="_blank">hash-table</a> based container introduced in <a href="http://en.wikipedia.org/wiki/C%2B%2B_Technical_Report_1" target="_blank">TR1</a>.</p>
<p><!--more--></p>
<p>TR1 <tt>std::unordered_map</tt> is a map that does not maintain any particular order between the keys of the data it contains. It is therefore implemented as a <a href="http://en.wikipedia.org/wiki/Hash_table" target="_blank">hash table</a>. The <tt>std::map</tt> is implemented, at least in G++ 4.2, as a <a href="http://en.wikipedia.org/wiki/Red-black_tree" target="_blank">red-black tree</a>. Self-balancing trees change their shape with each insertion in order to maintain most leaves at an equal depth, ensuring an <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clg+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\lg n)' title='O(\lg n)' class='latex' /> access time. The difference between an AVL tree and a red-black tree is the way the tree is rebalanced, and the red-black tree does about half as much operations as an AVL tree on insertion, making somewhat faster&#8212;how much faster remains to be quantified.</p>
<p>So I ran a few simple experiments to compare <tt>std::unordered_map</tt> and <tt>std::map</tt>. First, I got hold of the Zingarelli word list, containing some 585,000 Italian words (I can&#8217;t find a working URL, but I got the list a few years ago on a <a href="http://en.wikipedia.org/wiki/Scrabble" target="_blank">Scrabble</a>-related page). I ran three tests: insertion, successful search, and failed search. The list is broken into two parts, one containing 90% of the words, to be inserted, and 10% of the words where kept for the unsuccessful search test.</p>
<p>The insertion test consisted into inserting all of Zingarelli&#8217;s list into both data structures, in the most simplistic way: scanning the list sequentially and inserting items one by one.</p>
<table align="center" border="1">
<tr>
<td></td>
<td>wall time</td>
<td>op/s</td>
</tr>
<tr>
<td><tt>std::map</tt></td>
<td>0.75s</td>
<td>~699000</td>
</tr>
<tr>
<td><tt>std::unordered_map</tt></td>
<td>0.76s</td>
<td>~690000</td>
</tr>
</table>
<p>Insertion times are about the same; so we cannot conclude anything special here except maybe that the insertion time is largely dominated by memory allocation and copy. For the successful search (10,000 tries in each case):</p>
<table align="center" border="1">
<tr>
<td></td>
<td>wall time</td>
<td>op/s</td>
</tr>
<tr>
<td><tt>std::map</tt></td>
<td>0.047s</td>
<td>~209000</td>
</tr>
<tr>
<td><tt>std::unordered_map</tt></td>
<td>0.006s</td>
<td>~1.6&#215;10<sup>6</sup></td>
</tr>
</table>
<p>Map look-up is <em>immensely</em> faster with <tt>std::unordered_map</tt>, a ratio of about 8:1! Failed searches exhibit the same behavior. For ~60,000 failed searches:</p>
<table align="center" border="1">
<tr>
<td></td>
<td>wall time</td>
<td>op/s</td>
</tr>
<tr>
<td><tt>std::map</tt></td>
<td>0.263s</td>
<td>~37700</td>
</tr>
<tr>
<td><tt>std::unordered_map</tt></td>
<td>0.037s</td>
<td>~268000</sup></td>
</tr>
</table>
<p>We see the same kind of differences here again, but the failed searches are much slower than the successful searches.</p>
<p>When we repeat the experiment with integers (with the same kind of numbers; 500,000 integers of which 10% are randomly chosen for the failed searches), we get essentially the same picture but a massive speedup as strings are rather costly to copy. Indeed, for the insertion:</p>
<table align="center" border="1">
<tr>
<td></td>
<td>wall time</td>
<td>op/s</td>
</tr>
<tr>
<td><tt>std::map</tt></td>
<td>0.19s</td>
<td>2.3&#215;10<sup>6</sup></td>
</tr>
<tr>
<td><tt>std::unordered_map</tt></td>
<td>0.10s</td>
<td>4.5&#215;10<sup>6</sup></td>
</tr>
</table>
<p>Now, we see the algorithmic difference between the two algorithms as the time spent allocating and copying strings is eliminated. For successful and failed searches, we get (again for 10,000 look-ups):</p>
<table align="center" border="1">
<tr>
<td></td>
<td>wall time</td>
<td>op/s</td>
</tr>
<tr>
<td><tt>std::map</tt></td>
<td>0.015s</td>
<td>0.7&#215;10<sup>6</sup></td>
</tr>
<tr>
<td><tt>std::unordered_map</tt></td>
<td>0.005s</td>
<td>2.0&#215;10<sup>6</sup></td>
</tr>
</table>
<p>and:</p>
<table align="center" border="1">
<tr>
<td></td>
<td>wall time</td>
<td>op/s</td>
</tr>
<tr>
<td><tt>std::map</tt></td>
<td>0.082s</td>
<td>0.1&#215;10<sup>6</sup></td>
</tr>
<tr>
<td><tt>std::unordered_map</tt></td>
<td>0.009s</td>
<td>1.1&#215;10<sup>6</sup></td>
</tr>
</table>
<p>The <tt>std::unordered_map</tt> therefore seems to be much faster than <tt>std::map</tt>. What have we lost in order to gain this speed? First, a lot of memory as hash table must retain a certain sparseness to sport their average constant-time look-ups; and the ordering of keys. Listing the items sorted in a hash map won&#8217;t produce an ordered list, but rather a randomized version of the list. <tt>std::map</tt> on the other hand, allow lexicographic enumeration of its contents.</p>
<p align="center">*<br />*&#8195;*</p>
<p>So you&#8217;re reading this and are thinking, <em>mmppfh, of course, it&#8217;s a hash table, you nitwit</em>. Well, yes. Maybe so.</p>
<p>But here&#8217;s what prompted me to do the test. Red-black trees offer <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clg+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\lg n)' title='O(\lg n)' class='latex' /> access. But that&#8217;s assuming (and quite wrongly) that comparing keys can be performed in constant time. This may be true for simple keys, such as machine-size integers (known in C and C++ as <tt>int</tt>) but not so for more complex data, like strings and other structures. For string, for example, comparison may still be very fast because the cost of comparing two string only depends on the longest common prefix; if two long strings have differences in the first few characters, comparison terminates rapidly and the cost is moderate. If, on the other hand, the string share a very long prefix, then the comparison algorithm must scan both strings until the end is reached or a difference is found; this can be very long. So, lets <img src='http://l.wordpress.com/latex.php?latex=p&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p' title='p' class='latex' /> be the average common prefix length. The expected search time is now <img src='http://l.wordpress.com/latex.php?latex=O%28p+%5Clg+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(p \lg n)' title='O(p \lg n)' class='latex' /> which can grow large if <img src='http://l.wordpress.com/latex.php?latex=p&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p' title='p' class='latex' /> is large.</p>
<p>For a hash table look-up, you must first compute the hash key which can be at best done in linear time in the average key length. In our first case, this length is the average string length. Let this average length be <img src='http://l.wordpress.com/latex.php?latex=h&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='h' title='h' class='latex' />. The number of probe is <img src='http://l.wordpress.com/latex.php?latex=c_n&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c_n' title='c_n' class='latex' /> a small constant that depends on the sparseness of the table and the number of items, <img src='http://l.wordpress.com/latex.php?latex=n&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='n' title='n' class='latex' />, it contains. For each of those <img src='http://l.wordpress.com/latex.php?latex=c_n&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c_n' title='c_n' class='latex' /> probes, a string comparison is performed, leading to an expected complexity of <img src='http://l.wordpress.com/latex.php?latex=O%28c_n+h+p%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(c_n h p)' title='O(c_n h p)' class='latex' />.</p>
<p>Now, it is not clear when <img src='http://l.wordpress.com/latex.php?latex=p+%5Clg+n+%5Cgeqslant+c_n+h+p&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p \lg n \geqslant c_n h p' title='p \lg n \geqslant c_n h p' class='latex' />. Both <img src='http://l.wordpress.com/latex.php?latex=p&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p' title='p' class='latex' /> cancel, which boils down to <img src='http://l.wordpress.com/latex.php?latex=%5Clg+n+%5Cgeqslant+c_n+h&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\lg n \geqslant c_n h' title='\lg n \geqslant c_n h' class='latex' />. So, in <em>some</em> conditions, it may be possible to make the tree appear faster than the hash table.</p>
<p>On the average, however, the hash map should win becase we expect <img src='http://l.wordpress.com/latex.php?latex=c_n+%26%2360%3B%26%2360%3B+%5Clg+n&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c_n &lt;&lt; \lg n' title='c_n &lt;&lt; \lg n' class='latex' />.</p>
<p align="center">*<br />*&#8195;*</p>
<p>A <a href="http://en.wikipedia.org/wiki/Cargo_cult" target="_blank">cargo cult</a> is described as:</p>
<blockquote><p>
A cargo cult is a type of religious practice that may appear in primitive tribal societies in the wake of interaction with technologically advanced, non-native cultures. The cults are focused on obtaining the material wealth of the advanced culture through magical thinking, religious rituals and practices, believing that the wealth was intended for them by their deities and ancestors.
</p></blockquote>
<p></p>
<p>Except from the part with ancestor spirits but especially when considering <a href="http://en.wikipedia.org/wiki/Magical_thinking" target="_blank">magical thinking</a>, cargo culting applies very often to how programmers write code and take decisions about data structures and algorithms. Choosing a red-black tree over an AVL, or over a <a href="http://en.wikipedia.org/wiki/Splay_tree" target="_blank">splay</a> tree, because we think that it is somehow always better&#8212;sometimes because Ancestor X (a more or less reliable source or authority, such as a more experience programmer, a teacher, or some Internet <a href="http://en.wikipedia.org/wiki/Dude" target="_blank">dude</a>) said so&#8212;is a form of cargo cult where the programmer does not use rationality to its full extent to make a decision.</p>
<p>When choosing data structures, one must be fully aware of the dual cost of data structures. The first cost is the run-time cost. Theoretical complexity and actual implementation-dependant run-times may be quite different. The second cost is memory usage. Memory is large on modern systems but not infinite. A particularly wasteful method that offers constant-time access to the data may use as much as, say, ten times the memory used by a method that gives you <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clg+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\lg n)' title='O(\lg n)' class='latex' /> access. If for small data set this 10&#215; memory usage pose no particular problem, it may be quite different with a largish data set. It&#8217;s all a very delicate balancing act between run-time performance and scalability.</p>
<p>It&#8217;s very hard to trust one&#8217;s gut feelings about a data structure and the data put in. Combined with the access patterns, the data structure may yield a very counter-intuitive performance. Rather than giving into magic thinking cargo cult programming, you should <em>always</em> take a little time to validate our assumptions and hypotheses about the data, the data structure, and the access patterns, as data structure behavior is clearly <em>not</em> independent from the data and the access patterns.</p>
<p>Consider this very simple example. We have a simple binary tree and a list of strings. Binary trees offer <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clg+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\lg n)' title='O(\lg n)' class='latex' /> insertion and access times, so it is, <i>a priori</i>, a good choice. Now, the list of string is composed of words, but it so happens it&#8217;s already sorted. If we insert the strings in the order they are in the list, we get a degenerate binary-tree that&#8217;s in fact a list! Indeed so: insertions are always performed at the far right of the tree, causing the tree to degenerate into something we could call a <em>vine</em> and then all operations degenerate to linear time. If we randomize the list and insert the words into the tree in that randomized order, we get a ragged tree, but about equally deep everywhere, leading to the expected <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clg+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\lg n)' title='O(\lg n)' class='latex' /> access and insertion time.</p>
<p>The sorted list / binary tree example is an over-simplistic one, I admit, but it gets to the point: the programmer used a data structure cargo-culted to offer <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clg+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\lg n)' title='O(\lg n)' class='latex' /> access time, but due to his incomplete comprehension of the data (the <em>sorted</em> list) and of the access pattern (inserting items sequentially from the list), the result was disastrous.</p>
<p>But the thing is, we <em>all</em> do that to a certain extent!</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[TR1 &#8211; How to use array class?]]></title>
<link>http://codereflect.com/2009/08/17/tr1-how-to-use-array-class/</link>
<pubDate>Mon, 17 Aug 2009 13:58:44 +0000</pubDate>
<dc:creator>Sarath</dc:creator>
<guid>http://codereflect.com/2009/08/17/tr1-how-to-use-array-class/</guid>
<description><![CDATA[The C++ Standard Template Library (STL) provides a framework for processing algorithms on different ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>The C++ Standard Template Library (STL) provides a framework for processing algorithms on different kind of containers. However, ordinary arrays don&#8217;t provide the interface of STL containers (although, they provide the iterator interface of STL containers). As replacement for ordinary arrays, the STL provides class <code><a href="http://msdn.microsoft.com/en-us/library/9xd04bzs(VS.71).aspx" target="_blank">std::vector</a></code>. However, <code>std</code><code>::vector&#60;&#62;</code> provides the semantics of dynamic arrays. It manages data to be able to change the number of elements. This results in some overhead in case only arrays with static size are needed.</p>
<p>New new C++ provides a new class called array which is static in usage but able use a standard C++ container. It also provides access to the underlying data. Thus it’s possible to use as raw array pointers. See the sample snippet below to too see how to use <a href="http://msdn.microsoft.com/en-us/library/bb983093.aspx" target="_blank">array class</a>. A better documentation can be found at <a href="http://www.boost.org/doc/libs/1_39_0/doc/html/array.html" target="_blank">boost::array</a> page.</p>
<pre class="brush: cpp;">
// using array class
void FooTR1Array()
{
	std::tr1::array arr = {1,2,3,4,5};

	using namespace std;

	cout &amp;#60;&amp;#60; &amp;#34;Contents of array &amp;#34; &amp;#60;&amp;#60;endl;
	copy( arr.begin(), arr.end(),
			ostream_iterator(std::cout,&quot;\t&quot;));
	cout &amp;#60;&amp;#60; &amp;#34;Size of array - &amp;#34; &amp;#60;&amp;#60; arr.size() &amp;#60;&amp;#60;endl;
	cout &amp;#60;&amp;#60; &amp;#34;Front of array - &amp;#34; &amp;#60;&amp;#60; arr.front() &amp;#60;&amp;#60;endl;
	cout &amp;#60;&amp;#60; &amp;#34;Front of back - &amp;#34; &amp;#60;&amp;#60; arr.back() &amp;#60;&amp;#60;endl;
	cout &amp;#60;&amp;#60; &amp;#34;Array max Size- &amp;#34; &amp;#60;&amp;#60; arr.max_size() &amp;#60;&amp;#60;endl;
	cout &amp;#60;&amp;#60; &amp;#34;Array [3] - &amp;#34; &amp;#60;&amp;#60; arr[3] &amp;#60;&amp;#60;endl;
	cout &amp;#60;&amp;#60; &amp;#34;First element using pointer - &amp;#34; &amp;#60;&amp;#60; *arr.data() &amp;#60;&amp;#60;endl;

	// array swapping - both arrays should have same properties and size
	std::tr1::array arrNew = {111,222,333,444,555};

	cout &amp;#60;&amp;#60; &amp;#34;Contents of array 2&amp;#34; &amp;#60;&amp;#60;endl;
	copy( arrNew.begin(), arrNew.end(),
		ostream_iterator(std::cout,&quot;\t&quot;));

	// swap array
	arr.swap( arrNew );

	cout &amp;#60;&amp;#60; endl&amp;#60;&amp;#60; &amp;#34;Contents of array 1 after swapping with array 2&amp;#34; &amp;#60;&amp;#60;endl;
	copy( arr.begin(), arr.end(),
		ostream_iterator(std::cout,&quot;\t&quot;));

	cout &amp;#60;&amp;#60; endl&amp;#60;&amp;#60; &amp;#34;Contents of array 2 after swapping with array 1&amp;#34; &amp;#60;&amp;#60;endl;
	copy( arrNew.begin(), arrNew.end(),
		ostream_iterator(std::cout,&quot;\t&quot;));
}
</pre>
</div>]]></content:encoded>
</item>

</channel>
</rss>
