From octave-maintainers-request at bevo dot che dot wisc dot edu Wed Jan 21 16:14:30 2004 Subject: Re: benchmarks - sort From: David Bateman To: THOMAS Paul Richard Cc: octave-maintainers at bevo dot che dot wisc dot edu Date: Wed, 21 Jan 2004 23:09:52 +0100 --VbJkn9YxBvnuCH5J Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit Hi Thomas, Well the fact is I've come a bit further in testing some sorting algorithms. I've tried several different cases. Firstly, what Alois said about sorting IEEE754 as integers numbers made me starting looking at radix sorting. Then Paul Kienzle strongly suggested the Python mergesort algorithm as having great abilities especially for partially ordered lists. I've taken the Python code and implemented it as a class and use it to sort either directly on the doubles or recasting as uint64 and use the same trick I used for the radix sort. One problem I have with the Python code, is that when calling "[b,bi] = sort(a)", I have to create a new class containing the element and the index like template class vec_index { public: vec_index (void) : vec (0), indx (-1) { } vec_index (T v, int i) : vec (v), indx (i) { } vec_index &operator = (const vec_index &x); T vec; int indx; }; template vec_index; bool operator < (const vec_index &a, const vec_index &b) { return (xisnan(b.vec) || (a.vec < b.vec)); } This is due to the fact that the calls in the class to sort the elements are of the form "tmp = *a; *a = *b; *b = tmp;". This imposes quite a penalty on the mergesort. I can really see another way to do this without writing specific versions of the code for all instantiations of the mergesort class for with and without indexing (Ugly)... Any suggestions are welcome. In any case there are 5 test case, with and without indexing 1a) Matlab R12 "b = sort(a)" - baseline for unindexed octave tests 1b) Matlab R12 "[b,bi] = sort(a)" - baseline for indexed octave tests 2a) Octave "b = sort(a)" - orginal octave code 2b) Octave "[b,bi] = sort(a)" - orginal octave code with indexing 3a) Octave "b = radix(a)" - Radix sort test code 3b) Octave "[b,bi] = radix(a)" - Radix sort test code with indexing 4a) Octave "b = merge_double(a)" - Mergesort on doubles 4b) Octave "[b,bi] = merge_double(a)" - Mergesort on doubles with indexing 5a) Octave "b = merge_ieee7543(a)" - Mergesort on IEEE754 case as uint64 5b) Octave "[b,bi] = merge_double(a)" - Mergesort on IEEE754 case as uint64 with indexing I've benchmarked the matlab code seperately (in "matlab.log") and used this to benchmark the other four versions of the code, with and without returning the index array. All tests were run on the same machine under the same conditions. I also trying to do a bit of averaging in the tests to remove variation in the runtimes. I attach the code I used in the tarball in this mail. The names of the tests I used are the same as those in the Python code and are *sort Randomly distributed lists \sort Descending list /sort Ascending list 3sort Ascending list with 3 values randomly interchanged +sort Ascending list with the last 10 values replace with random data =sort All values equal There are two tables in "octave.log" for each test. The first table is the runtime of each iteration, while the second table is the relative time wrt Matlab. So as to not bias the results against Octave, with its problems with "for" loops, I've assumed that a = randn(n,rep) t = cputime; b = sort(a); time (cputime - t) / rep; gives the runtime of "b = sort(a)", where "a = randn(n,1)". The basic result is that the radix sort compares well against Matlab for randomly distributed values (1.10 times the speed of Matlab), but as this sort takes no advantage of partial ordering, it breaks down in these cases. The mergesort with double values is faster than Matlab for partailly ordered lists, but about 2.5 to 3 times slower than Matlab for random lists. Interestingly, although merge_double is significantly slower with indexing, it maintains the same relationship with Matlab. The clear winner for me is the mergesort with integer comparison of IEEE754 values. This is roughly two times faster than Matlab for partially ordered lists, while being only slightly slower (1.29 relative to Matlab) than the radix sort (1.10 relative to Matlab). This algorithm is roughly 6 times faster than the current Octave sort code. The performance degrades slightly with indexing (roughly 2.0 relative to Matlab). Note that my test code, checked the correctness of the sorting algorithms, that it sorted NaN, Inf and -Inf correctly and that it was stable. There are several questions to answer before this might be rewritten for inclusion either in octave or octave-forge. * Does octave support any platform with 8-byte integers? If so the mergesort class could be used with doubles in this case. If not I can simplify the code. In any case having mergesort as a class means that other parts of octave might use this class (sort char matrices for instance). * Is there any other way to win back the speed loss I get for sorting with indexing with the mergesort class? Maybe someone could look at merge.cc and oct-sort.cc and give their thoughts? * Is there any chance of this going into octave, or should I be targeting octave-forge? * Should I bother implementing complex sorting (done it for radix sort but not in the attached tar-ball)? Cheers David Daprès THOMAS Paul Richard (le 21/01/2004): > For what it is worth ( 0.02 euros?), in the course of educating myself about > the C++ standard library, I did a test of the sorting capability of > multimaps. It turns out to be a bit off the performance discussion, in that > the timing is EXACTLY the same as that of octave's sort and about a factor > of five slower than Matlab R13 on the same machine (not very surprising, > since the standard library uses exactly the same algorithm as octave!). > However, it is interesting just how concise a routine, exploiting the > standard library can become. Please find the routine below. > > Paul Thomas > > //Test of auto-sorting properties of standard library multi-map > //In input vector x is inserted element by element into a > //multi-map vmap, together with the input index of the element. > //Since multi-map insert sorts according to the value of the first > //element, reading the map pairs back, using the multi-map iterator, > //yields the sorted values and the sorted index. > // > //Paul Thomas 17/01/04 > > #include > #include > #include > using namespace std; > > DEFUN_DLD (mysort, args, , > "mysort. Call using \ > [a,b]=mysort(x)") > { > typedef multimap ddmap; // > ColumnVector vin(args(0).vector_value()); //turn input into > ColumnVector > int vinlen=vin.length(); //number of input elements > ddmap vmap; //multimap container for x > and its index > ddmap::iterator pos; //iterator for the multimap > double didx=1; //double index > for (int idx=0;idx by value > { > vmap.insert(make_pair(vin(idx),didx++)); //insert value,index > } > int idx=0; //output counter > ColumnVector idxout(vinlen); //sorted index > for (pos=vmap.begin();pos!=vmap.end();pos++,idx++) > { > vin(idx)=pos->first; //sorted value > idxout(idx)=pos->second; //sorted index > } > octave_value_list retval(vin); //sorted value to output > retval.append(octave_value(idxout)); //sorted index to output > return retval; //return > } > > > --- > Outgoing mail is certified Virus Free. > Checked by AVG anti-virus system (http://www.grisoft.com). > Version: 6.0.564 / Virus Database: 356 - Release Date: 19/01/04 > -- David Bateman David dot Bateman at motorola dot com Motorola CRM +33 1 69 35 48 04 (Ph) Parc Les Algorithmes, Commune de St Aubin +33 1 69 35 77 01 (Fax) 91193 Gif-Sur-Yvette FRANCE The information contained in this communication has been classified as: [x] General Business Information [ ] Motorola Internal Use Only [ ] Motorola Confidential Proprietary --VbJkn9YxBvnuCH5J Content-Type: application/octet-stream Content-Disposition: attachment; filename="sort.tgz" Content-Transfer-Encoding: base64 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 9rP9bD/bz1qf/wOyuq86AEABAA== --VbJkn9YxBvnuCH5J--