<?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>Blog::Quibb &#187; sorting</title> <atom:link href="http://blog.quibb.org/tag/sorting/feed/" rel="self" type="application/rss+xml" /><link>http://blog.quibb.org</link> <description>Software development and more.</description> <lastBuildDate>Mon, 21 Nov 2011 05:12:26 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <item><title>JSR-166: The Java fork/join Framework</title><link>http://blog.quibb.org/2010/03/jsr-166-the-java-forkjoin-framework/</link> <comments>http://blog.quibb.org/2010/03/jsr-166-the-java-forkjoin-framework/#comments</comments> <pubDate>Wed, 10 Mar 2010 02:53:22 +0000</pubDate> <dc:creator>Joe</dc:creator> <category><![CDATA[Java]]></category> <category><![CDATA[sorting]]></category> <category><![CDATA[threading]]></category><guid isPermaLink="false">http://blog.quibb.org/?p=153</guid> <description><![CDATA[The JSR-166 are concurrent utilities that were included in Java 5.  The fork/join framework was a piece of it that didn&#8217;t make it into Java 5.  After all this time the fork/join framework is finally making it into JDK 7.  What surprised me about the framework is that it is so easy to use. The [...]]]></description> <content:encoded><![CDATA[<p>The <a title="JSR-166" href="http://jcp.org/en/jsr/detail?id=166">JSR-166</a> are concurrent utilities that were  included in Java 5.  The fork/join framework was a piece of it that  didn&#8217;t make it into Java 5.  After all this time the fork/join framework  is finally making it into JDK 7.  What surprised me about the framework  is that it is so easy to use.</p><p>The fork/join framework is designed to make divide-and-conquer algorithms easy to parallelize.   More specifically, recursive algorithms where the control path branches  out over a few paths and they each process an equal part of the data  set.  The typical setup is a new class is created that extends either  the <a title="RecursiveAction" href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166ydocs/jsr166y/RecursiveAction.html">RecursiveAction</a> or <a title="RecursiveTask" href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166ydocs/jsr166y/RecursiveTask.html">RecursiveTask</a> class.  The parameters that were sent into the recursive function  become member variables in the newly defined class.  Then the recursive  calls are replaced by invokeAll(&#8230;) rather than the calls to the  function itself.</p><p>In writing this post, I kept going back for  forth on whether I should use Fibonacci numbers as an example or  something with more meat to it.  The computations done by each recursive  call of a Fibonacci numbers algorithm is too small to matter, not only  that, but there are much better non-parallel algorithms for Fibonacci numbers.  In the end, I decided on showing a merge sort.  It is used as the example in the fork/join documentation, but this will be a more complete example showing both the sequential algorithm and the changes made for the  parallel version of the algorithm.  You&#8217;ll see that it&#8217;s not that hard.</p><p>First  let me start by showing the source code for a typical MergeSort:</p><div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> MergeSort <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> SIZE_THRESHOLD <span style="color: #339933;">=</span> <span style="color: #cc66cc;">16</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> sort<span style="color: #009900;">&#40;</span><span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> a<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        sort<span style="color: #009900;">&#40;</span>a, <span style="color: #cc66cc;">0</span>, a.<span style="color: #006633;">length</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> sort<span style="color: #009900;">&#40;</span><span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> a, <span style="color: #000066; font-weight: bold;">int</span> lo, <span style="color: #000066; font-weight: bold;">int</span> hi<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>hi <span style="color: #339933;">-</span> lo <span style="color: #339933;">&lt;</span> SIZE_THRESHOLD<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            insertionsort<span style="color: #009900;">&#40;</span>a, lo, hi<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> tmp <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>hi <span style="color: #339933;">-</span> lo<span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        mergeSort<span style="color: #009900;">&#40;</span>a, tmp, lo, hi<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> mergeSort<span style="color: #009900;">&#40;</span><span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> a, <span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> tmp, <span style="color: #000066; font-weight: bold;">int</span> lo, <span style="color: #000066; font-weight: bold;">int</span> hi<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>hi <span style="color: #339933;">-</span> lo <span style="color: #339933;">&lt;</span> SIZE_THRESHOLD<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            insertionsort<span style="color: #009900;">&#40;</span>a, lo, hi<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">int</span> m <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>lo <span style="color: #339933;">+</span> hi<span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">;</span>
        mergeSort<span style="color: #009900;">&#40;</span>a, tmp, lo, m<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        mergeSort<span style="color: #009900;">&#40;</span>a, tmp, m <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span>, hi<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        merge<span style="color: #009900;">&#40;</span>a, tmp, lo, m, hi<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> merge<span style="color: #009900;">&#40;</span><span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> a, <span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> b, <span style="color: #000066; font-weight: bold;">int</span> lo, <span style="color: #000066; font-weight: bold;">int</span> m, <span style="color: #000066; font-weight: bold;">int</span> hi<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span>m<span style="color: #009900;">&#93;</span>.<span style="color: #006633;">compareTo</span><span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span>m<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
            <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #003399;">System</span>.<span style="color: #006633;">arraycopy</span><span style="color: #009900;">&#40;</span>a, lo, b, <span style="color: #cc66cc;">0</span>, m<span style="color: #339933;">-</span>lo<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">int</span> j <span style="color: #339933;">=</span> m<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">int</span> k <span style="color: #339933;">=</span> lo<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// copy back next-greatest element at each time</span>
        <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>k <span style="color: #339933;">&lt;</span> j <span style="color: #339933;">&amp;&amp;</span> j <span style="color: #339933;">&lt;=</span> hi<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #006633;">compareTo</span><span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                a<span style="color: #009900;">&#91;</span>k<span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> b<span style="color: #009900;">&#91;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
                a<span style="color: #009900;">&#91;</span>k<span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> a<span style="color: #009900;">&#91;</span>j<span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// copy back remaining elements of first half (if any)</span>
        <span style="color: #003399;">System</span>.<span style="color: #006633;">arraycopy</span><span style="color: #009900;">&#40;</span>b, i, a, k, j<span style="color: #339933;">-</span>k<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> insertionsort<span style="color: #009900;">&#40;</span><span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> a, <span style="color: #000066; font-weight: bold;">int</span> lo, <span style="color: #000066; font-weight: bold;">int</span> hi<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> lo<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;=</span> hi<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">int</span> j <span style="color: #339933;">=</span> i<span style="color: #339933;">;</span>
            <span style="color: #003399;">Comparable</span> t <span style="color: #339933;">=</span> a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>j <span style="color: #339933;">&gt;</span> lo <span style="color: #339933;">&amp;&amp;</span> t.<span style="color: #006633;">compareTo</span><span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span>j <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> a<span style="color: #009900;">&#91;</span>j <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
                <span style="color: #339933;">--</span>j<span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
            a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> t<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p>Now here is the code for the parallel version of  MergeSort:</p><div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ParallelMergeSort <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> ForkJoinPool threadPool <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ForkJoinPool<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> SIZE_THRESHOLD <span style="color: #339933;">=</span> <span style="color: #cc66cc;">16</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> sort<span style="color: #009900;">&#40;</span><span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> a<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        sort<span style="color: #009900;">&#40;</span>a, <span style="color: #cc66cc;">0</span>, a.<span style="color: #006633;">length</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> sort<span style="color: #009900;">&#40;</span><span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> a, <span style="color: #000066; font-weight: bold;">int</span> lo, <span style="color: #000066; font-weight: bold;">int</span> hi<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>hi <span style="color: #339933;">-</span> lo <span style="color: #339933;">&lt;</span> SIZE_THRESHOLD<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            insertionsort<span style="color: #009900;">&#40;</span>a, lo, hi<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> tmp <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span>a.<span style="color: #006633;">length</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        threadPool.<span style="color: #006633;">invoke</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> SortTask<span style="color: #009900;">&#40;</span>a, tmp, lo, hi<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * This class replaces the recursive function that was
     * previously here.
     */</span>
    <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">class</span> SortTask <span style="color: #000000; font-weight: bold;">extends</span> RecursiveAction <span style="color: #009900;">&#123;</span>
        <span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> a<span style="color: #339933;">;</span>
        <span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> tmp<span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">int</span> lo, hi<span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">public</span> SortTask<span style="color: #009900;">&#40;</span><span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> a, <span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> tmp, <span style="color: #000066; font-weight: bold;">int</span> lo, <span style="color: #000066; font-weight: bold;">int</span> hi<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">a</span> <span style="color: #339933;">=</span> a<span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">lo</span> <span style="color: #339933;">=</span> lo<span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">hi</span> <span style="color: #339933;">=</span> hi<span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">tmp</span> <span style="color: #339933;">=</span> tmp<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        @Override
        <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> compute<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>hi <span style="color: #339933;">-</span> lo <span style="color: #339933;">&lt;</span> SIZE_THRESHOLD<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                insertionsort<span style="color: #009900;">&#40;</span>a, lo, hi<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
&nbsp;
            <span style="color: #000066; font-weight: bold;">int</span> m <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>lo <span style="color: #339933;">+</span> hi<span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">;</span>
            <span style="color: #666666; font-style: italic;">// the two recursive calls are replaced by a call to invokeAll</span>
            invokeAll<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> SortTask<span style="color: #009900;">&#40;</span>a, tmp, lo, m<span style="color: #009900;">&#41;</span>, <span style="color: #000000; font-weight: bold;">new</span> SortTask<span style="color: #009900;">&#40;</span>a, tmp, m<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span>, hi<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            merge<span style="color: #009900;">&#40;</span>a, tmp, lo, m, hi<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> merge<span style="color: #009900;">&#40;</span><span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> a, <span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> b, <span style="color: #000066; font-weight: bold;">int</span> lo, <span style="color: #000066; font-weight: bold;">int</span> m, <span style="color: #000066; font-weight: bold;">int</span> hi<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span>m<span style="color: #009900;">&#93;</span>.<span style="color: #006633;">compareTo</span><span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span>m<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
            <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #003399;">System</span>.<span style="color: #006633;">arraycopy</span><span style="color: #009900;">&#40;</span>a, lo, b, lo, m<span style="color: #339933;">-</span>lo<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> lo<span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">int</span> j <span style="color: #339933;">=</span> m<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">int</span> k <span style="color: #339933;">=</span> lo<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// copy back next-greatest element at each time</span>
        <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>k <span style="color: #339933;">&lt;</span> j <span style="color: #339933;">&amp;&amp;</span> j <span style="color: #339933;">&lt;=</span> hi<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #006633;">compareTo</span><span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                a<span style="color: #009900;">&#91;</span>k<span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> b<span style="color: #009900;">&#91;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
                a<span style="color: #009900;">&#91;</span>k<span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> a<span style="color: #009900;">&#91;</span>j<span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// copy back remaining elements of first half (if any)</span>
        <span style="color: #003399;">System</span>.<span style="color: #006633;">arraycopy</span><span style="color: #009900;">&#40;</span>b, i, a, k, j<span style="color: #339933;">-</span>k<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> insertionsort<span style="color: #009900;">&#40;</span><span style="color: #003399;">Comparable</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> a, <span style="color: #000066; font-weight: bold;">int</span> lo, <span style="color: #000066; font-weight: bold;">int</span> hi<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> lo<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;=</span> hi<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">int</span> j <span style="color: #339933;">=</span> i<span style="color: #339933;">;</span>
            <span style="color: #003399;">Comparable</span> t <span style="color: #339933;">=</span> a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>j <span style="color: #339933;">&gt;</span> lo <span style="color: #339933;">&amp;&amp;</span> t.<span style="color: #006633;">compareTo</span><span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span>j <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> a<span style="color: #009900;">&#91;</span>j <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
                <span style="color: #339933;">--</span>j<span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
            a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> t<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p>As you can see the majority of the  algorithm has remained intact.  As stated above a new class is created  that extends RecursiveAction, and the parameters of the function are  then passed into that class during creation.  One thing to take note, is that previously only half the size of the original array was created as  secondary storage.  Now the entire length of the array is created as a  temporary storage.  This is used to avoid different threads needing the  same area of the array at the same time.</p><p>Changes to the algorithm may  be needed, but it definitely helps in making it easier to move to parallel processing.  One other thing to note is the presence of the <a title="ForkJoinPool" href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166ydocs/jsr166y/ForkJoinPool.html">ForkJoinPool</a>.  The default constructor looks at the processor and determines the appropriate level of parallelism for the task.</p><p>I have a quad core CPU, so the ForkJoinPool will spawn at least four threads if necessary.  That said, I&#8217;ve seen in where only two threads are spawned because more than that was not  necessary for the given task.  The ForkJoinPool spawns more threads as deemed necessary without starting right at the maximum.</p><p>A complete API for the fork/join  framework can be found here at the Concurrency <a title="JSR-166 Interest Site" href="http://gee.cs.oswego.edu/dl/concurrency-interest/">JSR-166 Interest Site</a>.  All that is needed  for Java 6 is the jsr166y package.</p><p>Some other algorithms that  are suited for parallelism that I&#8217;ve been thinking about are graph  searching algorithms such as depth first and breadth first search.   Depending on whether they are done on a tree or a graph determines how  much the underlying data structure will need to be changed to support  the parallelism.  I plan to look at making a parallel version of the  quicksort algorithm using this framework.  Most divide and conquer  algorithms can be adapted fairly easily to be multi-threaded using this  method, but remember for a performance benefit to be seen the task must  be sufficiently large.</p> ]]></content:encoded> <wfw:commentRss>http://blog.quibb.org/2010/03/jsr-166-the-java-forkjoin-framework/feed/</wfw:commentRss> <slash:comments>10</slash:comments> </item> <item><title>Sort Optimization (Part 2) with JDK 6 vs JDK 7</title><link>http://blog.quibb.org/2009/12/sort-optimization-part-2-with-jdk-6-vs-jdk-7/</link> <comments>http://blog.quibb.org/2009/12/sort-optimization-part-2-with-jdk-6-vs-jdk-7/#comments</comments> <pubDate>Wed, 23 Dec 2009 15:00:28 +0000</pubDate> <dc:creator>Joe</dc:creator> <category><![CDATA[Java]]></category> <category><![CDATA[benchmarks]]></category> <category><![CDATA[shootout]]></category> <category><![CDATA[sorting]]></category><guid isPermaLink="false">http://blog.quibb.org/?p=94</guid> <description><![CDATA[In part 1, I went over my first foray into the world of sorting algorithms.  Since then, I&#8217;ve had some other ideas on how to improve my quicksort implementation.  One idea that I had while originally working on the sorting algorithm, was to rework the partition function to take into account duplicate elements.  I had [...]]]></description> <content:encoded><![CDATA[<p>In <a href="http://blog.quibb.org/2008/11/sort-optimization/">part 1</a>, I went over my first foray into the world of sorting algorithms.  Since then, I&#8217;ve had some other ideas on how to improve my quicksort implementation.  One idea that I had while originally working on the sorting algorithm, was to rework the partition function to take into account duplicate elements.  I had a few different working implementations, but all of them came with severe performance penalty.  I finally figured out a way to get performance close to the previous algorithm.</p><p>The partition function needs to perform the minimal number of swaps possible.  So moving towards the center from both ends and only swapping when both are out of order is the best approach I&#8217;ve found so far.  When grouping duplicate elements, they are swapped to the beginning of the partition area as they are found.  Then at the end, a pass is run to move them to their correct location in the final list.  Then instead of returning one number from the partition function, it returns two.  It returns the minimum and maximum indices on the range that has the pivot value.</p><p>Another area that I was able to get some performance gain out of was getting rid of the shell sort form the first algorithm.  While that was there to make sure the quicksort did not recurse too deeply, in practice the shell sort algorithm doesn&#8217;t run.</p><p><strong>Results</strong></p><p>Here are the results of JDK 6 MergeSort, <a href="http://en.wikipedia.org/wiki/Timsort">Tim Sort</a>, <a href="http://blog.quibb.org/2008/11/sort-optimization/">QSort</a>, QSortv2, and Dual Pivot sort 2 benchmarked on the same set of files.  Overall, the new version doesn&#8217;t outperform the old version, but I thought it was worth posting my findings.  On most data sets with duplicates it does perform better.  I ran these benchmarks on OpenJDK 7 because I was curious as to how they would compare to one another.</p><p>It&#8217;s important to note that the tables are speedup relative the Java implementation on the given JDK.  The graphs are the average runtimes for each algorithm.  The reason for doing the average runtime is that it could show the performance difference between Sun&#8217;s JDK 6 and OpenJDK 7 build 73.<br /><center></p><table><tbody><tr><td><p><div id="attachment_105" class="wp-caption alignnone" style="width: 122px"><a href="http://blog.quibb.org/wp-content/uploads/2009/12/JDK6nowarm.png"><img class="size-medium wp-image-105" title="Sun JDK 6 without Warmup" src="http://blog.quibb.org/wp-content/uploads/2009/12/JDK6nowarm-112x300.png" alt="Sun JDK 6 without Warmup" width="112" height="300" /></a><p class="wp-caption-text">Sun JDK 6 without Warmup</p></div></td><td><p><div id="attachment_106" class="wp-caption alignnone" style="width: 106px"><a href="http://blog.quibb.org/wp-content/uploads/2009/12/JDK7nowarm.png"><img class="size-medium wp-image-106 " title="OpenJDK 7 without Warmup" src="http://blog.quibb.org/wp-content/uploads/2009/12/JDK7nowarm-96x300.png" alt="Sun JDK 7 without Warmup" width="96" height="300" /></a><p class="wp-caption-text">OpenJDK 7 without Warmup</p></div></td></tr></tbody></table><p></center><br /><center></p><table><tbody><tr><td><p><div id="attachment_107" class="wp-caption alignnone" style="width: 174px"><a href="http://blog.quibb.org/wp-content/uploads/2009/12/JDK61000warm.png"><img class="size-medium wp-image-107" title="Sun JDK 6 1000 Warmup Iterations" src="http://blog.quibb.org/wp-content/uploads/2009/12/JDK61000warm-164x300.png" alt="Sun JDK 6 1000 Warmup Iterations" width="164" height="300" /></a><p class="wp-caption-text">Sun JDK 6 1000 Warmup Iterations</p></div></td><td><p><div id="attachment_108" class="wp-caption alignnone" style="width: 151px"><a href="http://blog.quibb.org/wp-content/uploads/2009/12/JDK71000warm.png"><img class="size-medium wp-image-108" title="OpenJDK 7 1000 Warmup Iterations" src="http://blog.quibb.org/wp-content/uploads/2009/12/JDK71000warm-141x300.png" alt="OpenJDK 7 1000 Warmup Iterations" width="141" height="300" /></a><p class="wp-caption-text">OpenJDK 7 1000 Warmup Iterations</p></div></td></tr></tbody></table><p></center><br /><div id="attachment_109" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.quibb.org/wp-content/uploads/2009/12/nowarmup.png"><img class="size-medium wp-image-109  " title="Sun JDK 6 vs OpenJDK 7 without Warmup" src="http://blog.quibb.org/wp-content/uploads/2009/12/nowarmup-300x249.png" alt="JDK 6 vs JDK 7 with No Warmup" width="300" height="249" /></a><p class="wp-caption-text">Sun JDK 6 vs OpenJDK 7 without Warmup</p></div></p><div id="attachment_104" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.quibb.org/wp-content/uploads/2009/12/1000warm.png"><img class="size-medium wp-image-104 " title="Sun JDK 6 vs OpenJDK 7 1000 Iterations of Warmup" src="http://blog.quibb.org/wp-content/uploads/2009/12/1000warm-300x248.png" alt="Sun JDK 6 vs OpenJDK 7 1000 Warmup Iterations" width="300" height="248" /></a><p class="wp-caption-text">Sun JDK 6 vs OpenJDK 7 1000 Iterations of Warmup</p></div><p><strong>Conclusions</strong></p><p>Overall the new version of the Qsort implementation doesn&#8217;t improve greatly over the previous implementation.  While it didn&#8217;t work out to be the performace improvement I was looking for.  I think the last graph with 1000 iterations of warmup for each algorithm is the most interesting.  The Qsort v2 implementation apparently doesn&#8217;t get handled any better by OpenJDK 7.  The partition function is larger after my changes, so perhaps it didn&#8217;t JIT very well.  What is interesting is the boost that Tim Sort saw with the change of JDK&#8217;s.  Running these benchmarks made me realize that upgrading my Java Runtime will increase the performance of all my Java applications.  It will be interesting to see if the performance carries over to Netbeans and Eclipse; I expect it will.</p> ]]></content:encoded> <wfw:commentRss>http://blog.quibb.org/2009/12/sort-optimization-part-2-with-jdk-6-vs-jdk-7/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Sorting Algorithm Shootout</title><link>http://blog.quibb.org/2009/10/sorting-algorithm-shootout/</link> <comments>http://blog.quibb.org/2009/10/sorting-algorithm-shootout/#comments</comments> <pubDate>Thu, 08 Oct 2009 14:00:55 +0000</pubDate> <dc:creator>Joe</dc:creator> <category><![CDATA[Java]]></category> <category><![CDATA[shootout]]></category> <category><![CDATA[sorting]]></category><guid isPermaLink="false">http://blog.quibb.org/?p=75</guid> <description><![CDATA[Since I did my Sort Optimization post, I&#8217;ve been keeping an eye on things that happen in the sorting world.  Recently an article popped up on Reddit about someone wanting to replace the JDK sorting algorithm with a Dual Pivot Quick Sort.  This lead to the discovery that Tim Sort would be replacing Merge Sort [...]]]></description> <content:encoded><![CDATA[<p><strong> </strong>Since I did my <a href="http://blog.quibb.org/2008/11/sort-optimization/">Sort Optimization</a> post, I&#8217;ve been keeping an eye on things that happen in the sorting world.  Recently an article popped up on Reddit about someone wanting to replace the JDK sorting algorithm with a Dual Pivot Quick Sort.  This lead to the discovery that Tim Sort would be replacing Merge Sort in the JDK starting with version 7.  This probably got some attention because of the <a href="http://openjdk.java.net/">OpenJDK</a> project.  It&#8217;s nice to see that allowing more developers to work on different areas of the JDK.  First I&#8217;ll do a quick overview of the algorithms, then show some benchmarks.  All algorithms are written in Java.</p><p><strong>JDK 6 Sort</strong></p><p>The JDK6 implements a fairly standard Merge Sort.  It will switch to an insertion sort at a specific depth.</p><p><strong>QSort</strong></p><p>This is the implementation of quicksort I outlined in the earlier blog post.  It performed admirably at the time, but how will it hold up against tougher competition.  It&#8217;s pretty much an iterative quicksort, that short-circuits to a shell sort if it&#8217;s going too deep.</p><p>Original QSort Post:<br /> <a href="http://blog.quibb.org/2008/11/sort-optimization/">Sort Optimization</a></p><p><strong>Tim Sort</strong></p><p>This is an optimized in place variation of a merge sort.  Tim Peters developed this sorting algorithm for the Python programming language.  It is in use by Python and will be used by Java starting with JDK 7.  It takes advantage of partially sorted parts of the list.</p><p>Available here:<br /> <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6804124">http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6804124</a><br /> <a href="http://hg.openjdk.java.net/jdk7/tl/jdk/rev/bfd7abda8f79">http://hg.openjdk.java.net/jdk7/tl/jdk/rev/bfd7abda8f79</a><br /> <strong><br /> Dual Pivot Quick sort</strong></p><p>This is a newcomer to the sorting table.  Developed by Vladimir Yaroslavskiy for the inclusion into the Java language.  The premise is the same as quick sort, only it will choose two pivot points rather than one.  He did a full writeup detailing the algorithm, and its benefits.  I did modify it to take the comparable interface, and Vladimir explicitly said this was not the intended target of the algorithm.  He has stated it is designed to work directly with primitive types.  I don&#8217;t see how doing an int comparison vs a Integer.compareTo() would be different, as long as they are used uniformly between all algorithms.  Since my sorting algorithm works with comparable, as does Tim Sort, I chose to convert this algorithm to use the Comparable interface also.</p><p>Available here:<br /> <a href="http://article.gmane.org/gmane.comp.java.openjdk.core-libs.devel/2628">http://article.gmane.org/gmane.comp.java.openjdk.core-libs.devel/2628</a></p><p><strong>Results</strong></p><p>These tables show the speedup relative to JDK 6 with and without warm up.</p><div id="attachment_83" class="wp-caption alignnone" style="width: 123px"><a href="http://blog.quibb.org/wp-content/uploads/2009/10/nowarm_server.png"><img class="size-medium wp-image-83" title="nowarm_server" src="http://blog.quibb.org/wp-content/uploads/2009/10/nowarm_server-113x300.png" alt="nowarm_server" width="113" height="300" /></a><p class="wp-caption-text">sorting algorithm speedup without warm up</p></div><div id="attachment_84" class="wp-caption alignnone" style="width: 175px"><a href="http://blog.quibb.org/wp-content/uploads/2009/10/10000warm_server.png"><img class="size-medium wp-image-84" title="10000warm_server" src="http://blog.quibb.org/wp-content/uploads/2009/10/10000warm_server-165x300.png" alt="sorting algorithm comparison with warmup" width="165" height="300" /></a><p class="wp-caption-text">sorting algorithm speedup with warm up</p></div><p>Here is the original text data if you&#8217;re interested in that.  These are in simple table format.  The columns store the runtime in seconds for each algorithm.  The number in parenthesis is the speedup relative to JDK 6.</p><p><a href="http://blog.quibb.org/wp-content/uploads/2009/10/results_nowarm_server.txt">Without Warmup</a></p><p><a href="http://blog.quibb.org/wp-content/uploads/2009/10/results_10000warm_server.txt">With Warmup</a></p><p>Tim Sort is definitely the way to go if you&#8217;re interested in a stable sorting algorithm.  I was pretty amazed when I first looked at the results with how well it actually it did.  It really takes advantage of any presorted parts of the lists.  Overall, I&#8217;d say my optimized quicksort does fairly well, but maybe it could do better.  I may have to look into that again.</p> ]]></content:encoded> <wfw:commentRss>http://blog.quibb.org/2009/10/sorting-algorithm-shootout/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>Sort Optimization</title><link>http://blog.quibb.org/2008/11/sort-optimization/</link> <comments>http://blog.quibb.org/2008/11/sort-optimization/#comments</comments> <pubDate>Sat, 15 Nov 2008 18:31:19 +0000</pubDate> <dc:creator>Joe</dc:creator> <category><![CDATA[Java]]></category> <category><![CDATA[Ruby]]></category> <category><![CDATA[benchmarks]]></category> <category><![CDATA[jruby]]></category> <category><![CDATA[optimization]]></category> <category><![CDATA[sorting]]></category><guid isPermaLink="false">http://blog.quibb.org/?p=5</guid> <description><![CDATA[This all started one night when I was in the #JRuby channel on irc.freenode.net.  A channel user was complaining about JRuby&#8217;s sorting algorithm being slow.  I thought to myself, I should be able to speed it up.  At the time I was thinking since sorting has been so well researched it&#8217;d likely be easy to [...]]]></description> <content:encoded><![CDATA[<p style="text-align: left;">This all started one night when I was in the #JRuby channel on irc.freenode.net.  A channel user was complaining about JRuby&#8217;s sorting algorithm being slow.  I thought to myself, I should be able to speed it up.  At the time I was thinking since sorting has been so well researched it&#8217;d likely be easy to find documentation about it.  That didn&#8217;t turn out to be entirely the case.</p><p style="text-align: left;">I started by looking around on wikipedia, to see what that had to offer.  <a href="http://en.wikipedia.org/wiki/Introsort">IntroSort</a> caught my eye (also see: <a href="http://ralphunden.net/content/tutorials/a-guide-to-introsort/">A guide to Introsort</a>).  I thought it was interesting that after recursing to a certain depth it would switch from quicksort to heapsort.  I don&#8217;t think this optimization turned out to be that needed in the end though.  Other than switching to heapsort, it was pretty much a median of three quicksort with an insertion sort added.</p><p style="text-align: left;">It was a good starting point though.  I switched the heapsort for a shell sort and that dropped the number of comparisons needed by a good amount.  One thing I saw was only my &#8220;Median of 3 Killer&#8221; test case was affected by that.  I searched around the Internet often during this, and came across this page: <a href="http://arunchaganty.wordpress.com/2008/07/06/quicksort/">QuickSort</a>.  It had some interesting ideas like grouping the same element together when running the partition function.  I tried implementing that several times and it always ended up increasing the number of comparisons and the runtime.  I&#8217;m not 100% sure why.  If someone who knows more about sorting that I do has any input on that, I&#8217;d be happy to hear it.</p><p style="text-align: left;">Anyway, after working on that for a while I took a look at the competition.  I looked at Ruby&#8217;s C code.  They do some interesting things, which I hadn&#8217;t thought of up to that point.  First, they take the median of 7 if it has more than 200 elements.  Second, they don&#8217;t sample the end elements, this helps me out later in my optimizations.  I didn&#8217;t copy exactly what they were doing, but did a similar idea.  One thing they also did was look at the order of the 3 values that they compared last (I&#8217;ll refer to these as v1, v2, and v3).  v1 is before v2 and v3 in the list&#8217;s current state.  v2 is in the middle of the other two, and so on.</p><p style="text-align: left;">They had a lot more checks than what I ended up using, but I check if v1 &lt;= v2 &lt;= v3.  If this is the case I run the sequential test.  I also check if v1 &gt;= v2 &gt;= v3 to see if the list is in reversed order, and if it is I reverse the list before continuing.  While running these tests, I don&#8217;t check the first or last element of list because I have a separate test for that.  If it passes the sequential or reverse test that means the entire list is sorted except for potentially the first and/or the last element.  I then do a test on them and if they&#8217;re out of sequence I do bubble sort style swaps until they&#8217;re in the correct location.</p><p style="text-align: left;">Checking the end was one of the last optimizations I performed.  The main reason I added it is that case can be slow with the normal sorting algorithm, and I don&#8217;t think it&#8217;s that uncommon a case.  I&#8217;ve seen it happen where an element is appended to a sorted list and then the list is sorted again.  Overall, this catches a case with the potential to be slow in a fairly cheap manner.  These cases weren&#8217;t weeded out by the v1 &lt;= v2 &lt;= v3 style checks because the median of 7 that I use doesn&#8217;t check the end elements.</p><p style="text-align: left;">One of the last optimizations I performed was converting it to use a stack rather than operating recursively.  To be honest, this provided more speedup than I was expecting.  I guess all the function calls were taking a toll on the performance that I just didn&#8217;t realize at the time.</p><p style="text-align: left;">Another implementation technique that I ran tests to figure out which was better was whether to do insertion sort at the end on the entire list, or to do it as I find sections that are smaller than the threshold value.  After running benchmarks it turned out that putting it at the end was better.  I suspect that the extra function calls required for it to be done during the quicksort loop was more overhead than the potential gain of having more cache locality.</p><p style="text-align: left;">On with the benchmarks: (The numbers are time in seconds.  In parenthesis is speedup over Java.)</p><blockquote style="text-align: left;"><pre>                          Java                 My Qsort
1245.repeat.1000.txt      1.6552300e-05 (1.00) 8.1874300e-06   (2.02 )
1245.repeat.10000.txt     0.00026284956 (1.00) 0.00012648017   (2.08 )
end.0.1000.txt            5.8904900e-06 (1.00) 1.7295600e-06   (3.41 )
end.0.10000.txt           8.3629030e-05 (1.00) 2.3148840e-05   (3.61 )
identical.1000.txt        3.5435500e-06 (1.00) 5.9168000e-07   (5.99 )
identical.10000.txt       3.7097050e-05 (1.00) 6.5003600e-06   (5.71 )
med.3.killer.1000.txt     1.0182050e-05 (1.00) 7.2132600e-06   (1.41 )
med.3.killer.10000.txt    0.00013968449 (1.00) 9.4941470e-05   (1.47 )
rand.dups.100.txt         1.2044400e-06 (1.00) 6.3194000e-07   (1.91 )
rand.dups.1000.txt        1.9847760e-05 (1.00) 1.0417630e-05   (1.91 )
rand.dups.10000.txt       0.00031415178 (1.00) 0.00020365385   (1.54 )
rand.no.dups.100.txt      1.2328200e-06 (1.00) 8.1612000e-07   (1.51 )
rand.no.dups.1000.txt     1.9309830e-05 (1.00) 1.1890280e-05   (1.62 )
rand.no.dups.10000.txt    0.00027436851 (1.00) 0.00017424722   (1.57 )
rand.steps.1000.txt       1.6057600e-05 (1.00) 1.0023700e-05   (1.60 )
rand.steps.10000.txt      0.00019955369 (1.00) 0.00017004971   (1.17 )
rev.ends.1000.txt         1.2306600e-05 (1.00) 2.8749300e-06   (4.28 )
rev.ends.10000.txt        9.4499880e-05 (1.00) 2.7255840e-05   (3.47 )
rev.partial.1000.txt      1.7107210e-05 (1.00) 8.7564000e-06   (1.95 )
rev.partial.10000.txt     0.00024198949 (1.00) 0.00013045623   (1.85 )
rev.saw.1000.txt          1.6793840e-05 (1.00) 9.4294600e-06   (1.78 )
rev.saw.10000.txt         0.00025133096 (1.00) 0.00014296088   (1.76 )
reverse.1000.txt          1.4600270e-05 (1.00) 1.1565800e-06   (12.6 )
reverse.10000.txt         0.00020535965 (1.00) 1.3798890e-05   (14.9 )
seq.0.is.1000.1000.txt    6.5672500e-06 (1.00) 1.4837800e-06   (4.43 )
seq.0.is.1000.10000.txt   4.7335130e-05 (1.00) 7.2842900e-06   (6.50 )
seq.partial.1000.txt      1.5497830e-05 (1.00) 6.0515300e-06   (2.56 )
seq.partial.10000.txt     0.00022936435 (1.00) 9.1791120e-05   (2.50 )
seq.saw.1000.txt          1.1645670e-05 (1.00) 4.6621150e-05   (0.250)
seq.saw.10000.txt         0.00019771144 (1.00) 0.00011184647   (1.77 )
sequential.1000.txt       3.4216700e-06 (1.00) 5.8689000e-07   (5.83 )
sequential.10000.txt      3.7812430e-05 (1.00) 6.1648500e-06   (6.13 )</pre></blockquote><p>These benchmarks were taken by running the sorting algorithm on each dataset 10000 times (to warm up the JVM), and then running it on the data 10 times to time it.  I took the average of those 10 runs.  The only case where My Qsort was slower than the built-in Java Arrays.sort() was seq.saw.1000.txt.  I attribute this to noise.  I ran it again and got the following:</p><blockquote><pre>seq.saw.1000.txt          0.00013980571 (1.00) 0.00012667049   (1.10 )</pre></blockquote><p>Hopefully this makes JRuby&#8217;s sorting comparable to Ruby&#8217;s.  One note, while Java&#8217;s sort is stable, the quicksort I wrote is not.  All that means is that if multiple entries have the same value they may get sorted differently.</p><p>You can do whatever you&#8217;d like with the source code.  If you do find it useful some credit and/or a link to here would be nice.</p><p>Here are the test files: <a href="http://blog.quibb.org/wp-content/uploads/2008/11/test_files.zip">Test Files<br /> </a></p><p>Here is the sort itself: <a href="http://blog.quibb.org/wp-content/uploads/2008/11/sort.zip">Sorting Algorithm </a></p> ]]></content:encoded> <wfw:commentRss>http://blog.quibb.org/2008/11/sort-optimization/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk
Page Caching using disk (enhanced)
Database Caching 2/19 queries in 0.004 seconds using disk
Object Caching 467/494 objects using disk

Served from: blog.quibb.org @ 2012-02-05 12:12:53 -->
