Stxxl
1.4.0
|
00001 /*************************************************************************** 00002 * containers/stack_benchmark.cpp 00003 * 00004 * Part of the STXXL. See http://stxxl.sourceforge.net 00005 * 00006 * Copyright (C) 2006 Roman Dementiev <dementiev@ira.uka.de> 00007 * Copyright (C) 2009, 2010 Andreas Beckmann <beckmann@cs.uni-frankfurt.de> 00008 * 00009 * Distributed under the Boost Software License, Version 1.0. 00010 * (See accompanying file LICENSE_1_0.txt or copy at 00011 * http://www.boost.org/LICENSE_1_0.txt) 00012 **************************************************************************/ 00013 00014 //! \example containers/stack_benchmark.cpp 00015 //! This is a benchmark mentioned in the paper 00016 //! R. Dementiev, L. Kettner, P. Sanders "STXXL: standard template library for XXL data sets" 00017 //! Software: Practice and Experience 00018 //! Volume 38, Issue 6, Pages 589-637, May 2008 00019 //! DOI: 10.1002/spe.844 00020 00021 00022 #include <stxxl/stack> 00023 #include <stxxl/stats> 00024 #include <stxxl/timer> 00025 00026 #define MEM_2_RESERVE (768 * 1024 * 1024) 00027 00028 #ifndef BLOCK_SIZE 00029 #define BLOCK_SIZE (2 * 1024 * 1024) 00030 #endif 00031 00032 #ifndef DISKS 00033 #define DISKS 4 00034 #endif 00035 00036 template <unsigned RECORD_SIZE> 00037 struct my_record_ 00038 { 00039 char data[RECORD_SIZE]; 00040 my_record_() 00041 { 00042 memset(data, 0, sizeof(data)); 00043 } 00044 }; 00045 00046 template <unsigned RECORD_SIZE> 00047 inline std::ostream & operator << (std::ostream & o, const my_record_<RECORD_SIZE> &) 00048 { 00049 o << "."; 00050 return o; 00051 } 00052 00053 00054 template <typename stack_type> 00055 void benchmark_insert(stack_type & Stack, stxxl::int64 volume) 00056 { 00057 typedef typename stack_type::value_type value_type; 00058 00059 STXXL_MSG("Record size: " << sizeof(value_type) << " bytes"); 00060 00061 stxxl::int64 ops = volume / sizeof(value_type); 00062 00063 value_type cur; 00064 00065 // test whether top() returns an lvalue 00066 Stack.push(cur); 00067 Stack.top() = cur; 00068 Stack.pop(); 00069 00070 stxxl::stats_data stats_begin(*stxxl::stats::get_instance()); 00071 00072 stxxl::timer Timer; 00073 Timer.start(); 00074 00075 for (stxxl::int64 i = 0; i < ops; ++i) 00076 { 00077 Stack.push(cur); 00078 } 00079 00080 Timer.stop(); 00081 00082 STXXL_MSG("Records in Stack: " << Stack.size()); 00083 if (ops != stxxl::int64(Stack.size())) 00084 { 00085 STXXL_MSG("Size does not match"); 00086 abort(); 00087 } 00088 00089 STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) << 00090 " seconds : " << (double(volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) << 00091 " MiB/s"); 00092 00093 std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats_begin; 00094 } 00095 00096 template <typename stack_type> 00097 void benchmark_delete(stack_type & Stack, stxxl::int64 volume) 00098 { 00099 typedef typename stack_type::value_type value_type; 00100 00101 stxxl::int64 ops = volume / sizeof(value_type); 00102 00103 value_type cur; 00104 00105 stxxl::stats_data stats_begin(*stxxl::stats::get_instance()); 00106 00107 stxxl::timer Timer; 00108 Timer.start(); 00109 00110 for (stxxl::int64 i = 0; i < ops; ++i) 00111 { 00112 Stack.pop(); 00113 } 00114 00115 Timer.stop(); 00116 00117 STXXL_MSG("Records in Stack: " << Stack.size()); 00118 if (!Stack.empty()) 00119 { 00120 STXXL_MSG("Stack must be empty"); 00121 abort(); 00122 } 00123 00124 STXXL_MSG("Deletions elapsed time: " << (Timer.mseconds() / 1000.) << 00125 " seconds : " << (double(volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) << 00126 " MiB/s"); 00127 00128 std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats_begin; 00129 } 00130 00131 00132 template <class my_record> 00133 void run_stxxl_growshrink2_stack(stxxl::int64 volume) 00134 { 00135 typedef typename stxxl::STACK_GENERATOR<my_record, stxxl::external, 00136 stxxl::grow_shrink2, DISKS, BLOCK_SIZE>::result stack_type; 00137 typedef typename stack_type::block_type block_type; 00138 00139 stxxl::read_write_pool<block_type> pool(DISKS * 4, DISKS * 4); 00140 stack_type Stack(pool); 00141 00142 benchmark_insert(Stack, volume); 00143 00144 Stack.set_prefetch_aggr(DISKS * 8); 00145 00146 benchmark_delete(Stack, volume); 00147 } 00148 00149 00150 template <class my_record> 00151 void run_stxxl_normal_stack(stxxl::int64 volume) 00152 { 00153 typedef typename stxxl::STACK_GENERATOR<my_record, stxxl::external, 00154 stxxl::normal, DISKS, BLOCK_SIZE>::result stack_type; 00155 00156 stack_type Stack; 00157 00158 benchmark_insert(Stack, volume); 00159 benchmark_delete(Stack, volume); 00160 } 00161 00162 00163 template <class my_record> 00164 void run_stl_stack(stxxl::int64 volume) 00165 { 00166 typedef std::stack<my_record> stack_type; 00167 00168 stack_type Stack; 00169 00170 benchmark_insert(Stack, volume); 00171 benchmark_delete(Stack, volume); 00172 } 00173 00174 00175 int main(int argc, char * argv[]) 00176 { 00177 STXXL_MSG("stxxl::pq block size: " << BLOCK_SIZE << " bytes"); 00178 00179 #ifdef STXXL_DIRECT_IO_OFF 00180 STXXL_MSG("STXXL_DIRECT_IO_OFF is defined"); 00181 #else 00182 STXXL_MSG("STXXL_DIRECT_IO_OFF is NOT defined"); 00183 #endif 00184 00185 if (argc < 3) 00186 { 00187 STXXL_MSG("Usage: " << argv[0] << " variant volume"); 00188 STXXL_MSG("\t variant = 1: grow-shrink-stack2 with 4 byte records"); 00189 STXXL_MSG("\t variant = 2: grow-shrink-stack2 with 32 byte records"); 00190 STXXL_MSG("\t variant = 3: normal-stack with 4 byte records"); 00191 STXXL_MSG("\t variant = 4: normal-stack with 32 byte records"); 00192 STXXL_MSG("\t variant = 5: std::stack with 4 byte records"); 00193 STXXL_MSG("\t variant = 6: std::stack with 32 byte records"); 00194 STXXL_MSG("\t volume: in bytes"); 00195 return -1; 00196 } 00197 00198 int variant = atoi(argv[1]); 00199 stxxl::int64 volume = stxxl::atoint64(argv[2]); 00200 00201 STXXL_MSG("Allocating array with size " << 00202 MEM_2_RESERVE << " bytes to prevent file buffering."); 00203 int * array = new int[MEM_2_RESERVE / sizeof(int)]; 00204 std::fill(array, array + (MEM_2_RESERVE / sizeof(int)), 0); 00205 00206 STXXL_MSG("Running variant: " << variant); 00207 STXXL_MSG("Data volume : " << volume << " bytes"); 00208 00209 switch (variant) 00210 { 00211 case 1: 00212 run_stxxl_growshrink2_stack<my_record_<4> >(volume); 00213 break; 00214 case 2: 00215 run_stxxl_growshrink2_stack<my_record_<32> >(volume); 00216 break; 00217 case 3: 00218 run_stxxl_normal_stack<my_record_<4> >(volume); 00219 break; 00220 case 4: 00221 run_stxxl_normal_stack<my_record_<32> >(volume); 00222 break; 00223 case 5: 00224 run_stl_stack<my_record_<4> >(volume); 00225 break; 00226 case 6: 00227 run_stl_stack<my_record_<32> >(volume); 00228 break; 00229 default: 00230 STXXL_MSG("Unsupported variant " << variant); 00231 } 00232 00233 delete[] array; 00234 }