1 : // ソートテスト その3 : list データのソート. 2 : #include <stdio.h> 3 : #include <stdlib.h> 4 : #include <time.h> 5 : #include <assert.h> 6 : #include <algorithm> 7 : #include <functional> 8 : #include <vector> 9 : #include <list> 10 : #include <string> 11 : 12 : 13 : template<typename BidiIte, class C > 14 : void bidi_quick_sort(BidiIte first, BidiIte last, C cmp ) 15 : { 16 : typedef typename std::iterator_traits<BidiIte>::value_type T; 17 : 18 : using std::iter_swap; 19 : std::size_t size = std::size_t(std::distance(first, last)); 20 : if (size <= 32) { 21 : if (size <= 1) 22 : return; 23 : BidiIte i = first; 24 : while (++i != last) { 25 : T tmp( *i ); 26 : BidiIte j = i; 27 : BidiIte k = i; 28 : do { 29 : --k; 30 : if (!cmp(tmp, *k)) 31 : break; 32 : *j = *k; 33 : --j; 34 : } while (k != first); 35 : *j = tmp; 36 : } 37 : return; 38 : } 39 : BidiIte ite( first ); 40 : std::advance( ite, size / 2 ); 41 : const T m( *ite ); 42 : BidiIte l = first; 43 : BidiIte r = last; 44 : std::size_t lc = 0; 45 : std::size_t rc = size; 46 : for (;;) { 47 : while (cmp(*l, m)) 48 : ++l, ++lc; 49 : do { 50 : --r, --rc; 51 : } while (cmp(m, *r)); 52 : if (lc >= rc) 53 : break; 54 : iter_swap(l, r); 55 : ++l, ++lc; 56 : } 57 : bidi_quick_sort(first, l , cmp); 58 : bidi_quick_sort(l , last, cmp); 59 : } 60 : 61 : 62 : 63 : template<typename BidiIte> inline 64 : void bidi_quick_sort(BidiIte first, BidiIte last) { 65 : bidi_quick_sort( first, last, std::less<typename std::iterator_traits<BidiIte>::value_type>() ); 66 : } 67 : 68 : 69 : 70 : // =========================================================================== 71 : #ifdef _WIN32 72 : #include <windows.h> 73 : typedef unsigned __int64 PerfCnt_tick_t; 74 : PerfCnt_tick_t PerfCnt_getTick() { PerfCnt_tick_t c; QueryPerformanceCounter((LARGE_INTEGER*)&c); return c; } 75 : PerfCnt_tick_t PerfCnt_tickPerSec() { static PerfCnt_tick_t s = 0; if (!s) QueryPerformanceFrequency((LARGE_INTEGER*)&s); return s; } 76 : #else 77 : #include <time.h> 78 : typedef clock_t PerfCnt_tick_t; 79 : #define PerfCnt_getTick() clock() 80 : #define PerfCnt_tickPerSec() CLOCKS_PER_SEC 81 : #endif 82 : 83 : 84 : 85 : // =========================================================================== 86 : 87 : template<typename T> 88 : T random() { 89 : return T(rand()); 90 : } 91 : 92 : template<> 93 : std::string random<std::string>() { 94 : char buf[128]; 95 : sprintf(buf, "%d%d%d", rand(),rand(),rand()); 96 : return std::string(buf); 97 : } 98 : 99 : 100 : 101 : // =========================================================================== 102 : #ifdef USE_SMPCLASS 103 : #if USE_SMPCLASS != 1 104 : #include <tr1/array> 105 : #endif 106 : 107 : class SmpClass { 108 : public: 109 : ~SmpClass() { free(name_); } 110 : SmpClass() : name_(0), x_(0),y_(0),z_(0),argb_(0xFFFFFFFF),mode_(0) { /*buf_.resize(256);*/ } 111 : 112 : SmpClass(const SmpClass& r) 113 : : name_(strdup(r.name_)), x_(r.x_), y_(r.y_), z_(r.z_), argb_(r.argb_), mode_(r.mode_), buf_(r.buf_) {} 114 : 115 : SmpClass(const char* name, double x, double y, double z, unsigned argb=0xffffffff, unsigned mode=0) 116 : : name_(strdup(name)), x_(x), y_(y), z_(z), argb_(argb), mode_(mode) 117 : { 118 : #if USE_SMPCLASS == 1 119 : buf_.resize(256); 120 : #endif 121 : } 122 : 123 : SmpClass& operator=(const SmpClass& r) { SmpClass(r).swap( *this ); return *this; } 124 : 125 : void swap(SmpClass& r); 126 : bool operator<(const SmpClass& r) const; 127 : 128 : private: 129 : char* name_; 130 : double x_, y_, z_; 131 : unsigned argb_; 132 : unsigned mode_; 133 : #if USE_SMPCLASS == 1 134 : std::vector<char> buf_; 135 : #else 136 : std::tr1::array<char,160> buf_; 137 : #endif 138 : }; 139 : 140 : 141 : inline void SmpClass::swap(SmpClass& r) { 142 : using std::swap; 143 : swap(name_, r.name_); 144 : swap(x_ , r.x_ ); 145 : swap(y_ , r.y_ ); 146 : swap(z_ , r.z_ ); 147 : swap(argb_, r.argb_); 148 : swap(mode_, r.mode_); 149 : swap(buf_ , r.buf_ ); 150 : } 151 : 152 : 153 : inline bool SmpClass::operator<(const SmpClass& r) const { 154 : if (z_ < r.z_) 155 : return 1; 156 : if (z_ > r.z_) 157 : return 0; 158 : if (y_ < r.y_) 159 : return 1; 160 : if (y_ > r.y_) 161 : return 0; 162 : return strcmp(name_, r.name_) < 0; 163 : } 164 : 165 : 166 : template<> 167 : SmpClass random<SmpClass>() { 168 : char name[128]; 169 : sprintf(name, "%c%c%d", 'A'+rand()%26,'a'+rand()%26,'a'+rand()%26, rand()); 170 : return SmpClass(name, rand(), rand(), rand()); 171 : } 172 : 173 : 174 : #define TYPE SmpClass 175 : #endif 176 : 177 : 178 : 179 : // =========================================================================== 180 : 181 : template<typename T> 182 : double benchmark1(unsigned size, unsigned count, int seed=1) { 183 : srand(seed); 184 : PerfCnt_tick_t elapsed = 0; 185 : for (unsigned j = 0; j < count; ++j) { 186 : std::vector<T> data; 187 : data.reserve(size); 188 : for (unsigned i = 0; i < size; ++i) 189 : data.push_back(random<T>()); 190 : PerfCnt_tick_t start_time = PerfCnt_getTick(); 191 : bidi_quick_sort(data.begin(), data.end() ); 192 : elapsed += PerfCnt_getTick() - start_time; 193 : } 194 : return elapsed / double(PerfCnt_tickPerSec() * count); 195 : } 196 : 197 : 198 : template<typename T> 199 : double benchmark2(unsigned size, unsigned count, int seed=1) { 200 : srand(seed); 201 : PerfCnt_tick_t elapsed = 0; 202 : for (unsigned j = 0; j < count; ++j) { 203 : std::list<T> data; 204 : for (unsigned i = 0; i < size; ++i) 205 : data.push_back(random<T>()); 206 : PerfCnt_tick_t start_time = PerfCnt_getTick(); 207 : bidi_quick_sort( data.begin(), data.end() ); 208 : elapsed += PerfCnt_getTick() - start_time; 209 : } 210 : return elapsed / double(PerfCnt_tickPerSec() * count); 211 : } 212 : 213 : 214 : template<typename T> 215 : double benchmark3(unsigned size, unsigned count, int seed=1) { 216 : srand(seed); 217 : PerfCnt_tick_t elapsed = 0; 218 : for (unsigned j = 0; j < count; ++j) { 219 : std::list<T> data; 220 : for (unsigned i = 0; i < size; ++i) 221 : data.push_back(random<T>()); 222 : PerfCnt_tick_t start_time = PerfCnt_getTick(); 223 : data.sort(); 224 : elapsed += PerfCnt_getTick() - start_time; 225 : } 226 : return elapsed / double(PerfCnt_tickPerSec() * count); 227 : } 228 : 229 : 230 : template<typename T> 231 : struct ptr_less { 232 : bool operator()(T l, T r) const { 233 : return *l < *r; 234 : } 235 : }; 236 : 237 : 238 : template<typename T> 239 : double benchmark4(unsigned size, unsigned count, int seed=1) { 240 : srand(seed); 241 : PerfCnt_tick_t elapsed = 0; 242 : for (unsigned j = 0; j < count; ++j) { 243 : std::list<T> data; 244 : for (unsigned i = 0; i < size; ++i) 245 : data.push_back(random<T>()); 246 : 247 : PerfCnt_tick_t start_time = PerfCnt_getTick(); 248 : std::vector<T*> ent(size); 249 : typename std::vector<T*>::iterator vi = ent.begin(); 250 : for (typename std::list<T>::iterator li = data.begin(); li != data.end(); ++li) { 251 : *vi = &*li; 252 : ++vi; 253 : } 254 : bidi_quick_sort(ent.begin(), ent.end(), ptr_less<T*>() ); 255 : elapsed += PerfCnt_getTick() - start_time; 256 : } 257 : return elapsed / double(PerfCnt_tickPerSec() * count); 258 : } 259 : 260 : 261 : 262 : 263 : #ifndef TYPE 264 : #define TYPE int 265 : #endif 266 : 267 : struct St { 268 : size_t size; 269 : size_t count; 270 : double elaped[4]; 271 : }; 272 : 273 : 274 : // 275 : int main(int argc, char **argv) { 276 : if (argc < 2) { 277 : printf("usage> sort_test3 size1 count1 [size2 count2 ...]\n"); 278 : return 1; 279 : } 280 : std::vector<St> st; 281 : unsigned n = 0; 282 : for (unsigned i = 1; i < argc; i += 2) { 283 : St t; 284 : t.size = atoi(argv[i]); 285 : t.count = (i+1 < argc) ? atoi(argv[i+1]) : 1; 286 : std::fill(t.elaped, t.elaped+4, 0.0); 287 : st.push_back(t); 288 : ++n; 289 : } 290 : 291 : printf("\nsort_test3 : sizeof(TYPE)=%dbytes\n", sizeof(TYPE)); 292 : int seed = 1; //time(0); 293 : for (unsigned i = 0; i < n; ++i) { 294 : St& t = st[i]; 295 : printf("個数 %9d, 処理回数 %9d\n", t.size, t.count); 296 : t.elaped[0] = benchmark1<TYPE>(t.size, t.count, seed); 297 : t.elaped[1] = benchmark2<TYPE>(t.size, t.count, seed); 298 : t.elaped[2] = benchmark3<TYPE>(t.size, t.count, seed); 299 : t.elaped[3] = benchmark4<TYPE>(t.size, t.count, seed); 300 : } 301 : 302 : // 結果表示. 303 : static const char* ttl[] = { 304 : "vectorを quick sort ", 305 : "list を quick sort ", 306 : "std::list.sort ", 307 : "list要素へのポインタのvectorをsort", 308 : NULL, 309 : }; 310 : printf("\n"); 311 : printf("%34s ,", "個数"); 312 : for (unsigned i = 0; i < n; ++i) { 313 : printf("%9d個,", st[i].size); 314 : }; 315 : printf("\n"); 316 : for (unsigned j = 0; ttl[j]; ++j) { 317 : printf("%-34s ,", ttl[j]); 318 : for (unsigned i = 0; i < n; ++i) { 319 : printf("%11.3f,", st[i].elaped[j]*1000000.0); 320 : }; 321 : printf("\n"); 322 : } 323 : return 0; 324 : }