Added adaptive sort test and refactored utilities between adaptive benches and the new test

This commit is contained in:
Ion Gaztañaga
2016-03-19 12:20:15 +01:00
parent 499c5932bf
commit baa5f0bbe7
6 changed files with 412 additions and 230 deletions

View File

@@ -119,6 +119,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_merge", "bench_merge.
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "adaptive_sort_test", "adaptive_sort_test.vcproj", "{CD617A28-6217-B79E-4CE2-6BA035379A6A}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global Global
GlobalSection(SolutionConfiguration) = preSolution GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug Debug = Debug
@@ -247,6 +251,10 @@ Global
{CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Debug.Build.0 = Debug|Win32 {CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Debug.Build.0 = Debug|Win32
{CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Release.ActiveCfg = Release|Win32 {CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Release.ActiveCfg = Release|Win32
{CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Release.Build.0 = Release|Win32 {CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Release.Build.0 = Release|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Debug.ActiveCfg = Debug|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Debug.Build.0 = Debug|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Release.ActiveCfg = Release|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Release.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionItems) = postSolution GlobalSection(SolutionItems) = postSolution
..\..\..\..\boost\move\algo\adaptive_merge.hpp = ..\..\..\..\boost\move\algo\adaptive_merge.hpp ..\..\..\..\boost\move\algo\adaptive_merge.hpp = ..\..\..\..\boost\move\algo\adaptive_merge.hpp

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="adaptive_sort_test"
ProjectGUID="{CD617A28-6217-B79E-4CE2-6BA035379A6A}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/adaptive_sort_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
DisableLanguageExtensions="FALSE"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/adaptive_sort_test_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/adaptive_sort_test.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/adaptive_sort_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/adaptive_sort_test.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{163D8753-0546-A605-5C56-3B0FEAD7A52A}">
<File
RelativePath="..\..\test\adaptive_sort_test.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,91 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <cstdlib> //std::srand
#include <algorithm> //std::next_permutation
#include <iostream> //std::cout
#include <boost/config.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/container/vector.hpp>
#include <boost/timer/timer.hpp>
using boost::timer::cpu_timer;
using boost::timer::cpu_times;
using boost::timer::nanosecond_type;
#include "order_type.hpp"
#include <boost/move/algo/adaptive_sort.hpp>
#include <boost/move/core.hpp>
template<class T, class Compare>
void adaptive_sort_buffered(T *elements, std::size_t element_count, Compare comp, std::size_t BufLen)
{
boost::movelib::unique_ptr<char[]> mem(new char[sizeof(T)*BufLen]);
boost::movelib::adaptive_sort(elements, elements + element_count, comp, reinterpret_cast<T*>(mem.get()), BufLen);
}
template<class T>
bool test_all_permutations(std::size_t const element_count, std::size_t const num_keys, std::size_t const num_iter)
{
boost::movelib::unique_ptr<T[]> elements(new T[element_count]);
boost::movelib::unique_ptr<std::size_t[]> key_reps(new std::size_t[num_keys ? num_keys : element_count]);
std::cout << "- - N: " << element_count << ", Keys: " << num_keys << ", It: " << num_iter << " \n";
//Initialize keys
for(std::size_t i=0; i < element_count; ++i){
std::size_t key = num_keys ? (i % num_keys) : i;
elements[i].key=key;
}
std::srand(255);
for (std::size_t i = 0; i != num_iter; ++i)
{
std::random_shuffle(elements.get(), elements.get() + element_count);
for(std::size_t i = 0; i < (num_keys ? num_keys : element_count); ++i){
key_reps[i]=0;
}
for(std::size_t i = 0; i < element_count; ++i){
elements[i].val = key_reps[elements[i].key]++;
}
boost::container::vector<order_type> tmp(elements.get(), elements.get()+element_count);
boost::movelib::adaptive_sort(tmp.data(), tmp.data()+element_count, order_type_less<order_type>());
if (!is_order_type_ordered(tmp.data(), element_count))
{
std::cout << "\n ERROR\n";
throw int(0);
}
}
return true;
}
int main()
{
#ifdef NDEBUG
const std::size_t NIter = 100;
#else
const std::size_t NIter = 10;
#endif
test_all_permutations<order_type>(10001, 65, NIter);
test_all_permutations<order_type>(10001, 101, NIter);
test_all_permutations<order_type>(10001, 1023, NIter);
test_all_permutations<order_type>(10001, 4095, NIter);
test_all_permutations<order_type>(10001, 0, NIter);
return 0;
}

View File

@@ -18,62 +18,18 @@
#include <boost/move/unique_ptr.hpp> #include <boost/move/unique_ptr.hpp>
#include <boost/timer/timer.hpp> #include <boost/timer/timer.hpp>
#include "order_type.hpp"
using boost::timer::cpu_timer; using boost::timer::cpu_timer;
using boost::timer::cpu_times; using boost::timer::cpu_times;
using boost::timer::nanosecond_type; using boost::timer::nanosecond_type;
boost::ulong_long_type num_copy;
boost::ulong_long_type num_elements;
struct merged_type
{
public:
std::size_t key;
std::size_t val;
merged_type()
{
++num_elements;
}
merged_type(const merged_type& other)
: key(other.key), val(other.val)
{
++num_elements;
++num_copy;
}
merged_type & operator=(const merged_type& other)
{
++num_copy;
key = other.key;
val = other.val;
return *this;
}
~merged_type ()
{
--num_elements;
}
};
boost::ulong_long_type num_compare;
//#define BOOST_MOVE_ADAPTIVE_SORT_STATS //#define BOOST_MOVE_ADAPTIVE_SORT_STATS
void print_stats(const char *str, boost::ulong_long_type element_count) void print_stats(const char *str, boost::ulong_long_type element_count)
{ {
std::printf("%sCmp:%8.04f Cpy:%9.04f\n", str, double(num_compare)/element_count, double(num_copy)/element_count ); std::printf("%sCmp:%8.04f Cpy:%9.04f\n", str, double(order_type::num_compare)/element_count, double(order_type::num_copy)/element_count );
} }
template<class T>
struct counted_less
{
bool operator()(const T &a,T const &b) const
{ ++num_compare; return a.key < b.key; }
};
#include <boost/move/algo/adaptive_merge.hpp> #include <boost/move/algo/adaptive_merge.hpp>
#include <boost/move/algo/detail/merge.hpp> #include <boost/move/algo/detail/merge.hpp>
#include <boost/move/core.hpp> #include <boost/move/core.hpp>
@@ -101,21 +57,7 @@ std::size_t generate_elements(T elements[], std::size_t element_count, std::size
return split_count; return split_count;
} }
template<class T>
bool test_order(T *elements, std::size_t element_count, bool stable = true)
{
for(std::size_t i = 1; i < element_count; ++i){
if(counted_less<T>()(elements[i], elements[i-1])){
std::printf("\n Ord KO !!!!");
return false;
}
if( stable && !(counted_less<T>()(elements[i-1], elements[i])) && (elements[i-1].val > elements[i].val) ){
std::printf("\n Stb KO !!!! ");
return false;
}
}
return true;
}
template<class T, class Compare> template<class T, class Compare>
void adaptive_merge_buffered(T *elements, T *mid, T *last, Compare comp, std::size_t BufLen) void adaptive_merge_buffered(T *elements, T *mid, T *last, Compare comp, std::size_t BufLen)
@@ -150,53 +92,53 @@ BOOST_STATIC_ASSERT((sizeof(AlgoNames)/sizeof(*AlgoNames)) == MaxMerge);
template<class T> template<class T>
bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count, std::size_t key_len, unsigned alg, nanosecond_type &prev_clock) bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count, std::size_t key_len, unsigned alg, nanosecond_type &prev_clock)
{ {
std::size_t const split_pos = generate_elements(elements, element_count, key_reps, key_len, counted_less<T>()); std::size_t const split_pos = generate_elements(elements, element_count, key_reps, key_len, order_type_less<T>());
std::printf("%s ", AlgoNames[alg]); std::printf("%s ", AlgoNames[alg]);
num_compare=0; order_type::num_compare=0;
num_copy=0; order_type::num_copy=0;
num_elements = element_count; order_type::num_elements = element_count;
cpu_timer timer; cpu_timer timer;
timer.resume(); timer.resume();
switch(alg) switch(alg)
{ {
case InplaceMerge: case InplaceMerge:
std::inplace_merge(elements, elements+split_pos, elements+element_count, counted_less<T>()); std::inplace_merge(elements, elements+split_pos, elements+element_count, order_type_less<T>());
break; break;
case AdaptiveMerge: case AdaptiveMerge:
boost::movelib::adaptive_merge(elements, elements+split_pos, elements+element_count, counted_less<T>()); boost::movelib::adaptive_merge(elements, elements+split_pos, elements+element_count, order_type_less<T>());
break; break;
case SqrtHAdaptiveMerge: case SqrtHAdaptiveMerge:
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, counted_less<T>() adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less<T>()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1); , boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1);
break; break;
case SqrtAdaptiveMerge: case SqrtAdaptiveMerge:
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, counted_less<T>() adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less<T>()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)); , boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break; break;
case Sqrt2AdaptiveMerge: case Sqrt2AdaptiveMerge:
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, counted_less<T>() adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less<T>()
, 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)); , 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break; break;
case QuartAdaptiveMerge: case QuartAdaptiveMerge:
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, counted_less<T>() adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less<T>()
, (element_count-1)/4+1); , (element_count-1)/4+1);
break; break;
case BuflessMerge: case BuflessMerge:
boost::movelib::merge_bufferless(elements, elements+split_pos, elements+element_count, counted_less<T>()); boost::movelib::merge_bufferless(elements, elements+split_pos, elements+element_count, order_type_less<T>());
break; break;
} }
timer.stop(); timer.stop();
if(num_elements == element_count){ if(order_type::num_elements == element_count){
std::printf(" Tmp Ok "); std::printf(" Tmp Ok ");
} else{ } else{
std::printf(" Tmp KO "); std::printf(" Tmp KO ");
} }
nanosecond_type new_clock = timer.elapsed().wall; nanosecond_type new_clock = timer.elapsed().wall;
//std::cout << "Cmp:" << num_compare << " Cpy:" << num_copy; //for old compilers without ll size argument //std::cout << "Cmp:" << order_type::num_compare << " Cpy:" << order_type::num_copy; //for old compilers without ll size argument
std::printf("Cmp:%8.04f Cpy:%9.04f", double(num_compare)/element_count, double(num_copy)/element_count ); std::printf("Cmp:%8.04f Cpy:%9.04f", double(order_type::num_compare)/element_count, double(order_type::num_copy)/element_count );
double time = double(new_clock); double time = double(new_clock);
@@ -219,7 +161,7 @@ bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count
, units , units
, prev_clock ? double(new_clock)/double(prev_clock): 1.0); , prev_clock ? double(new_clock)/double(prev_clock): 1.0);
prev_clock = new_clock; prev_clock = new_clock;
bool res = test_order(elements, element_count, true); bool res = is_order_type_ordered(elements, element_count, true);
return res; return res;
} }
@@ -261,62 +203,55 @@ bool measure_all(std::size_t L, std::size_t NK)
return res; return res;
} }
struct less
{
template<class T, class U>
bool operator()(const T &t, const U &u)
{ return t < u; }
};
//Undef it to run the long test //Undef it to run the long test
#define BENCH_MERGE_SHORT #define BENCH_MERGE_SHORT
int main() int main()
{ {
try{ try{
measure_all<merged_type>(101,1); measure_all<order_type>(101,1);
measure_all<merged_type>(101,7); measure_all<order_type>(101,7);
measure_all<merged_type>(101,31); measure_all<order_type>(101,31);
measure_all<merged_type>(101,0); measure_all<order_type>(101,0);
// //
measure_all<merged_type>(1101,1); measure_all<order_type>(1101,1);
measure_all<merged_type>(1001,7); measure_all<order_type>(1001,7);
measure_all<merged_type>(1001,31); measure_all<order_type>(1001,31);
measure_all<merged_type>(1001,127); measure_all<order_type>(1001,127);
measure_all<merged_type>(1001,511); measure_all<order_type>(1001,511);
measure_all<merged_type>(1001,0); measure_all<order_type>(1001,0);
// //
#ifndef BENCH_MERGE_SHORT #ifndef BENCH_MERGE_SHORT
measure_all<merged_type>(10001,65); measure_all<order_type>(10001,65);
measure_all<merged_type>(10001,255); measure_all<order_type>(10001,255);
measure_all<merged_type>(10001,1023); measure_all<order_type>(10001,1023);
measure_all<merged_type>(10001,4095); measure_all<order_type>(10001,4095);
measure_all<merged_type>(10001,0); measure_all<order_type>(10001,0);
// //
measure_all<merged_type>(100001,511); measure_all<order_type>(100001,511);
measure_all<merged_type>(100001,2047); measure_all<order_type>(100001,2047);
measure_all<merged_type>(100001,8191); measure_all<order_type>(100001,8191);
measure_all<merged_type>(100001,32767); measure_all<order_type>(100001,32767);
measure_all<merged_type>(100001,0); measure_all<order_type>(100001,0);
// //
#ifdef NDEBUG #ifdef NDEBUG
measure_all<merged_type>(1000001,1); measure_all<order_type>(1000001,1);
measure_all<merged_type>(1000001,1024); measure_all<order_type>(1000001,1024);
measure_all<merged_type>(1000001,32768); measure_all<order_type>(1000001,32768);
measure_all<merged_type>(1000001,524287); measure_all<order_type>(1000001,524287);
measure_all<merged_type>(1000001,0); measure_all<order_type>(1000001,0);
measure_all<merged_type>(1500001,0); measure_all<order_type>(1500001,0);
//measure_all<merged_type>(10000001,0); //measure_all<order_type>(10000001,0);
//measure_all<merged_type>(15000001,0); //measure_all<order_type>(15000001,0);
//measure_all<merged_type>(100000001,0); //measure_all<order_type>(100000001,0);
#endif //NDEBUG #endif //NDEBUG
#endif //#ifndef BENCH_MERGE_SHORT #endif //#ifndef BENCH_MERGE_SHORT
//measure_all<merged_type>(100000001,0); //measure_all<order_type>(100000001,0);
} }
catch(...) catch(...)
{ {

View File

@@ -23,58 +23,15 @@ using boost::timer::cpu_timer;
using boost::timer::cpu_times; using boost::timer::cpu_times;
using boost::timer::nanosecond_type; using boost::timer::nanosecond_type;
#include "order_type.hpp"
boost::ulong_long_type num_copy;
boost::ulong_long_type num_elements;
struct sorted_type
{
public:
std::size_t key;
std::size_t val;
sorted_type()
{
++num_elements;
}
sorted_type(const sorted_type& other)
: key(other.key), val(other.val)
{
++num_elements;
++num_copy;
}
sorted_type & operator=(const sorted_type& other)
{
++num_copy;
key = other.key;
val = other.val;
return *this;
}
~sorted_type ()
{
--num_elements;
}
};
boost::ulong_long_type num_compare;
//#define BOOST_MOVE_ADAPTIVE_SORT_STATS //#define BOOST_MOVE_ADAPTIVE_SORT_STATS
void print_stats(const char *str, boost::ulong_long_type element_count) void print_stats(const char *str, boost::ulong_long_type element_count)
{ {
std::printf("%sCmp:%7.03f Cpy:%8.03f\n", str, double(num_compare)/element_count, double(num_copy)/element_count ); std::printf("%sCmp:%7.03f Cpy:%8.03f\n", str, double(order_type::num_compare)/element_count, double(order_type::num_copy)/element_count );
} }
template<class T>
struct counted_less
{
bool operator()(const T &a,T const &b) const
{ ++num_compare; return a.key < b.key; }
};
#include <boost/move/algo/adaptive_sort.hpp> #include <boost/move/algo/adaptive_sort.hpp>
#include <boost/move/algo/detail/merge_sort.hpp> #include <boost/move/algo/detail/merge_sort.hpp>
#include <boost/move/algo/detail/bufferless_merge_sort.hpp> #include <boost/move/algo/detail/bufferless_merge_sort.hpp>
@@ -99,22 +56,6 @@ void generate_elements(T elements[], std::size_t element_count, std::size_t key_
} }
} }
template<class T>
bool test_order(T *elements, std::size_t element_count, bool stable = true)
{
for(std::size_t i = 1; i < element_count; ++i){
if(counted_less<T>()(elements[i], elements[i-1])){
std::printf("\n Ord KO !!!!");
return false;
}
if( stable && !(counted_less<T>()(elements[i-1], elements[i])) && (elements[i-1].val > elements[i].val) ){
std::printf("\n Stb KO !!!! ");
return false;
}
}
return true;
}
template<class T, class Compare> template<class T, class Compare>
void adaptive_sort_buffered(T *elements, std::size_t element_count, Compare comp, std::size_t BufLen) void adaptive_sort_buffered(T *elements, std::size_t element_count, Compare comp, std::size_t BufLen)
{ {
@@ -164,60 +105,60 @@ bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count
generate_elements(elements, element_count, key_reps, key_len); generate_elements(elements, element_count, key_reps, key_len);
std::printf("%s ", AlgoNames[alg]); std::printf("%s ", AlgoNames[alg]);
num_compare=0; order_type::num_compare=0;
num_copy=0; order_type::num_copy=0;
num_elements = element_count; order_type::num_elements = element_count;
cpu_timer timer; cpu_timer timer;
timer.resume(); timer.resume();
switch(alg) switch(alg)
{ {
case MergeSort: case MergeSort:
merge_sort_buffered(elements, element_count, counted_less<T>()); merge_sort_buffered(elements, element_count, order_type_less<T>());
break; break;
case StableSort: case StableSort:
std::stable_sort(elements,elements+element_count,counted_less<T>()); std::stable_sort(elements,elements+element_count,order_type_less<T>());
break; break;
case AdaptiveSort: case AdaptiveSort:
boost::movelib::adaptive_sort(elements, elements+element_count, counted_less<T>()); boost::movelib::adaptive_sort(elements, elements+element_count, order_type_less<T>());
break; break;
case SqrtHAdaptiveSort: case SqrtHAdaptiveSort:
adaptive_sort_buffered( elements, element_count, counted_less<T>() adaptive_sort_buffered( elements, element_count, order_type_less<T>()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1); , boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1);
break; break;
case SqrtAdaptiveSort: case SqrtAdaptiveSort:
adaptive_sort_buffered( elements, element_count, counted_less<T>() adaptive_sort_buffered( elements, element_count, order_type_less<T>()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)); , boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break; break;
case Sqrt2AdaptiveSort: case Sqrt2AdaptiveSort:
adaptive_sort_buffered( elements, element_count, counted_less<T>() adaptive_sort_buffered( elements, element_count, order_type_less<T>()
, 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)); , 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break; break;
case QuartAdaptiveSort: case QuartAdaptiveSort:
adaptive_sort_buffered( elements, element_count, counted_less<T>() adaptive_sort_buffered( elements, element_count, order_type_less<T>()
, (element_count-1)/4+1); , (element_count-1)/4+1);
break; break;
case NoBufMergeSort: case NoBufMergeSort:
boost::movelib::bufferless_merge_sort(elements, elements+element_count, counted_less<T>()); boost::movelib::bufferless_merge_sort(elements, elements+element_count, order_type_less<T>());
break; break;
case SlowStableSort: case SlowStableSort:
boost::movelib::detail_adaptive::slow_stable_sort(elements, elements+element_count, counted_less<T>()); boost::movelib::detail_adaptive::slow_stable_sort(elements, elements+element_count, order_type_less<T>());
break; break;
case HeapSort: case HeapSort:
std::make_heap(elements, elements+element_count, counted_less<T>()); std::make_heap(elements, elements+element_count, order_type_less<T>());
std::sort_heap(elements, elements+element_count, counted_less<T>()); std::sort_heap(elements, elements+element_count, order_type_less<T>());
break; break;
} }
timer.stop(); timer.stop();
if(num_elements == element_count){ if(order_type::num_elements == element_count){
std::printf(" Tmp Ok "); std::printf(" Tmp Ok ");
} else{ } else{
std::printf(" Tmp KO "); std::printf(" Tmp KO ");
} }
nanosecond_type new_clock = timer.elapsed().wall; nanosecond_type new_clock = timer.elapsed().wall;
//std::cout << "Cmp:" << num_compare << " Cpy:" << num_copy; //for old compilers without ll size argument //std::cout << "Cmp:" << order_type::num_compare << " Cpy:" << order_type::num_copy; //for old compilers without ll size argument
std::printf("Cmp:%7.03f Cpy:%8.03f", double(num_compare)/element_count, double(num_copy)/element_count ); std::printf("Cmp:%7.03f Cpy:%8.03f", double(order_type::num_compare)/element_count, double(order_type::num_copy)/element_count );
double time = double(new_clock); double time = double(new_clock);
@@ -240,7 +181,7 @@ bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count
, units , units
, prev_clock ? double(new_clock)/double(prev_clock): 1.0); , prev_clock ? double(new_clock)/double(prev_clock): 1.0);
prev_clock = new_clock; prev_clock = new_clock;
bool res = test_order(elements, element_count, alg != HeapSort && alg != NoBufMergeSort); bool res = is_order_type_ordered(elements, element_count, alg != HeapSort && alg != NoBufMergeSort);
return res; return res;
} }
@@ -294,58 +235,49 @@ bool measure_all(std::size_t L, std::size_t NK)
//Undef it to run the long test //Undef it to run the long test
#define BENCH_SORT_SHORT #define BENCH_SORT_SHORT
struct less
{
template<class T, class U>
bool operator()(const T &t, const U &u)
{ return t < u; }
};
int main() int main()
{ {
measure_all<sorted_type>(101,1); measure_all<order_type>(101,1);
measure_all<sorted_type>(101,7); measure_all<order_type>(101,7);
measure_all<sorted_type>(101,31); measure_all<order_type>(101,31);
measure_all<sorted_type>(101,0); measure_all<order_type>(101,0);
// //
measure_all<sorted_type>(1101,1); measure_all<order_type>(1101,1);
measure_all<sorted_type>(1001,7); measure_all<order_type>(1001,7);
measure_all<sorted_type>(1001,31); measure_all<order_type>(1001,31);
measure_all<sorted_type>(1001,127); measure_all<order_type>(1001,127);
measure_all<sorted_type>(1001,511); measure_all<order_type>(1001,511);
measure_all<sorted_type>(1001,0); measure_all<order_type>(1001,0);
// //
#ifndef BENCH_SORT_SHORT #ifndef BENCH_SORT_SHORT
measure_all<sorted_type>(10001,65); measure_all<order_type>(10001,65);
measure_all<sorted_type>(10001,255); measure_all<order_type>(10001,255);
measure_all<sorted_type>(10001,1023); measure_all<order_type>(10001,1023);
measure_all<sorted_type>(10001,4095); measure_all<order_type>(10001,4095);
measure_all<sorted_type>(10001,0); measure_all<order_type>(10001,0);
// //
measure_all<sorted_type>(100001,511); measure_all<order_type>(100001,511);
measure_all<sorted_type>(100001,2047); measure_all<order_type>(100001,2047);
measure_all<sorted_type>(100001,8191); measure_all<order_type>(100001,8191);
measure_all<sorted_type>(100001,32767); measure_all<order_type>(100001,32767);
measure_all<sorted_type>(100001,0); measure_all<order_type>(100001,0);
// //
#ifdef NDEBUG #ifdef NDEBUG
measure_all<sorted_type>(1000001,1); measure_all<order_type>(1000001,1);
measure_all<sorted_type>(1000001,1024); measure_all<order_type>(1000001,1024);
measure_all<sorted_type>(1000001,32768); measure_all<order_type>(1000001,32768);
measure_all<sorted_type>(1000001,524287); measure_all<order_type>(1000001,524287);
measure_all<sorted_type>(1000001,0); measure_all<order_type>(1000001,0);
measure_all<sorted_type>(1500001,0); measure_all<order_type>(1500001,0);
//measure_all<sorted_type>(10000001,0); //measure_all<order_type>(10000001,0);
#endif //NDEBUG #endif //NDEBUG
#endif //#ifndef BENCH_SORT_SHORT #endif //#ifndef BENCH_SORT_SHORT
//measure_all<sorted_type>(100000001,0); //measure_all<order_type>(100000001,0);
return 0; return 0;
} }

82
test/order_type.hpp Normal file
View File

@@ -0,0 +1,82 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_MOVE_TEST_ORDER_TYPE_HPP
#define BOOST_MOVE_TEST_ORDER_TYPE_HPP
#include <boost/config.hpp>
#include <cstddef>
#include <cstdio>
struct order_type
{
public:
std::size_t key;
std::size_t val;
order_type()
{
++num_elements;
}
order_type(const order_type& other)
: key(other.key), val(other.val)
{
++num_elements;
++num_copy;
}
order_type & operator=(const order_type& other)
{
++num_copy;
key = other.key;
val = other.val;
return *this;
}
~order_type ()
{
--num_elements;
}
static boost::ulong_long_type num_compare;
static boost::ulong_long_type num_copy;
static boost::ulong_long_type num_elements;
};
boost::ulong_long_type order_type::num_compare = 0;
boost::ulong_long_type order_type::num_copy = 0;
boost::ulong_long_type order_type::num_elements = 0;
template<class T>
struct order_type_less
{
bool operator()(const T &a,T const &b) const
{ ++order_type::num_compare; return a.key < b.key; }
};
template<class T>
inline bool is_order_type_ordered(T *elements, std::size_t element_count, bool stable = true)
{
for(std::size_t i = 1; i < element_count; ++i){
if(order_type_less<T>()(elements[i], elements[i-1])){
std::printf("\n Ord KO !!!!");
return false;
}
if( stable && !(order_type_less<T>()(elements[i-1], elements[i])) && (elements[i-1].val > elements[i].val) ){
std::printf("\n Stb KO !!!! ");
return false;
}
}
return true;
}
#endif //BOOST_MOVE_TEST_ORDER_TYPE_HPP