Changeset 807a632 for doc/theses/thierry_delisle_PhD/code/relaxed_list.hpp
- Timestamp:
- Feb 10, 2020, 11:17:31 AM (3 years ago)
- Branches:
- arm-eh, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 3b56166
- Parents:
- 487198c
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/thierry_delisle_PhD/code/relaxed_list.hpp
r487198c r807a632 105 105 static_assert(std::is_same<decltype(node_t::_links), _LinksFields_t<node_t>>::value, "Node must have a links field"); 106 106 107 108 107 public: 109 108 relaxed_list(unsigned numLists) … … 112 111 { 113 112 assertf(7 * 8 * 8 >= numLists, "List currently only supports 448 sublists"); 114 assert(sizeof(*this) == 128); 113 // assert(sizeof(*this) == 128); 114 std::cout << "Constructing Relaxed List with " << numLists << std::endl; 115 116 #ifndef NO_STATS 117 if(head) this->next = head; 118 head = this; 119 #endif 115 120 } 116 121 117 122 ~relaxed_list() { 123 std::cout << "Destroying Relaxed List" << std::endl; 118 124 lists.reset(); 119 #ifndef NO_STATS120 std::cout << "Difference : "121 << ssize_t(double(intrusive_queue_t::stat::dif.value) / intrusive_queue_t::stat::dif.num ) << " avg\t"122 << intrusive_queue_t::stat::dif.max << "max" << std::endl;123 #endif124 125 } 125 126 … … 175 176 int nnempty; 176 177 while(0 != (nnempty = numNonEmpty)) { 178 tls.pick.pop.mask_attempt++; 177 179 unsigned i, j; 178 if( numLists < 4 || (numLists / nnempty) < 4 ) { 179 // Pick two lists at random 180 i = tls.rng.next() % numLists; 181 j = tls.rng.next() % numLists; 182 } else { 180 // if( numLists < 4 || (numLists / nnempty) < 4 ) { 181 // // Pick two lists at random 182 // i = tls.rng.next() % numLists; 183 // j = tls.rng.next() % numLists; 184 // } else 185 { 183 186 #ifndef NO_STATS 184 187 // tls.pick.push.mask_attempt++; … … 199 202 if(maski == 0 && maskj == 0) continue; 200 203 201 unsigned biti = maski ? ri % __builtin_popcountl(maski) : 0; 202 unsigned bitj = maskj ? rj % __builtin_popcountl(maskj) : 0; 203 204 unsigned bi = 64 - nthSetBit(maski, biti + 1); 205 unsigned bj = 64 - nthSetBit(maskj, bitj + 1); 206 207 assertf(bi < 64, "%zu %u %u", maski, biti, bi); 208 assertf(bj < 64, "%zu %u %u", maskj, bitj, bj); 204 unsigned bi = rand_bit(ri, maski); 205 unsigned bj = rand_bit(rj, maskj); 206 207 assertf(bi < 64, "%zu %u", maski, bi); 208 assertf(bj < 64, "%zu %u", maskj, bj); 209 209 210 210 i = bi | (wdxi << 6); … … 294 294 struct stat { 295 295 ssize_t diff = 0; 296 297 static struct Dif { 298 ssize_t value = 0; 299 size_t num = 0; 300 ssize_t max = 0; 301 } dif; 296 size_t push = 0; 297 size_t pop = 0; 298 // size_t value = 0; 299 // size_t count = 0; 302 300 }; 303 301 … … 314 312 #endif 315 313 314 #pragma GCC diagnostic push 315 #pragma GCC diagnostic ignored "-Winvalid-offsetof" 316 316 static constexpr auto fields_offset = offsetof( node_t, _links ); 317 #pragma GCC diagnostic pop 317 318 public: 318 319 intrusive_queue_t() … … 330 331 } 331 332 332 ~intrusive_queue_t() { 333 #ifndef NO_STATS 334 stat::dif.value+= s.diff; 335 stat::dif.num ++; 336 stat::dif.max = std::abs(stat::dif.max) > std::abs(s.diff) ? stat::dif.max : s.diff; 337 #endif 338 } 333 ~intrusive_queue_t() = default; 339 334 340 335 inline node_t * head() const { … … 367 362 tail->_links.prev = node; 368 363 #ifndef NO_STATS 369 if(enable_stats) s.diff++; 364 if(enable_stats) { 365 s.diff++; 366 s.push++; 367 } 370 368 #endif 371 369 if(before._links.ts == 0l) { … … 390 388 391 389 #ifndef NO_STATS 392 if(enable_stats) s.diff--; 390 if(enable_stats) { 391 s.diff--; 392 s.pop ++; 393 } 393 394 #endif 394 395 if(next == tail) { … … 419 420 420 421 public: 421 std::atomic_int numNonEmpty = 0; // number of non-empty lists422 std::atomic_size_t list_mask[7] = { 0}; // which queues are empty422 std::atomic_int numNonEmpty = { 0 }; // number of non-empty lists 423 std::atomic_size_t list_mask[7] = { {0}, {0}, {0}, {0}, {0}, {0}, {0} }; // which queues are empty 423 424 private: 424 425 __attribute__((aligned(64))) std::unique_ptr<intrusive_queue_t []> lists; … … 427 428 public: 428 429 static const constexpr size_t sizeof_queue = sizeof(intrusive_queue_t); 430 431 #ifndef NO_STATS 432 static void stats_print(std::ostream & os) { 433 auto it = head; 434 while(it) { 435 it->stats_print_local(os); 436 it = it->next; 437 } 438 } 439 440 static void stats_tls_tally() { 441 global_stats.pick.push.attempt += tls.pick.push.attempt; 442 global_stats.pick.push.success += tls.pick.push.success; 443 global_stats.pick.pop .attempt += tls.pick.pop.attempt; 444 global_stats.pick.pop .success += tls.pick.pop.success; 445 global_stats.pick.pop .mask_attempt += tls.pick.pop.mask_attempt; 446 447 global_stats.qstat.push.value += tls.empty.push.value; 448 global_stats.qstat.push.count += tls.empty.push.count; 449 global_stats.qstat.pop .value += tls.empty.pop .value; 450 global_stats.qstat.pop .count += tls.empty.pop .count; 451 } 452 453 private: 454 static struct GlobalStats { 455 struct { 456 struct { 457 std::atomic_size_t attempt = { 0 }; 458 std::atomic_size_t success = { 0 }; 459 } push; 460 struct { 461 std::atomic_size_t attempt = { 0 }; 462 std::atomic_size_t success = { 0 }; 463 std::atomic_size_t mask_attempt = { 0 }; 464 } pop; 465 } pick; 466 struct { 467 struct { 468 std::atomic_size_t value = { 0 }; 469 std::atomic_size_t count = { 0 }; 470 } push; 471 struct { 472 std::atomic_size_t value = { 0 }; 473 std::atomic_size_t count = { 0 }; 474 } pop; 475 } qstat; 476 } global_stats; 477 478 // Link list of all lists for stats 479 __attribute__((aligned(64))) relaxed_list<node_t> * next = nullptr; 480 481 static relaxed_list<node_t> * head; 482 483 void stats_print_local(std::ostream & os ) { 484 std::cout << "----- Relaxed List Stats -----" << std::endl; 485 { 486 ssize_t diff = 0; 487 size_t num = 0; 488 ssize_t max = 0; 489 490 for(size_t i = 0; i < numLists; i++) { 491 const auto & list = lists[i]; 492 diff+= list.s.diff; 493 num ++; 494 max = std::abs(max) > std::abs(list.s.diff) ? max : list.s.diff; 495 os << "Local Q ops : " << (list.s.push + list.s.pop) << "(" << list.s.push << "i, " << list.s.pop << "o)\n"; 496 } 497 498 os << "Difference : " << ssize_t(double(diff) / num ) << " avg\t" << max << "max" << std::endl; 499 } 500 501 const auto & global = global_stats; 502 503 double push_sur = (100.0 * double(global.pick.push.success) / global.pick.push.attempt); 504 double pop_sur = (100.0 * double(global.pick.pop .success) / global.pick.pop .attempt); 505 double mpop_sur = (100.0 * double(global.pick.pop .success) / global.pick.pop .mask_attempt); 506 507 os << "Push Pick % : " << push_sur << "(" << global.pick.push.success << " / " << global.pick.push.attempt << ")\n"; 508 os << "Pop Pick % : " << pop_sur << "(" << global.pick.pop .success << " / " << global.pick.pop .attempt << ")\n"; 509 os << "TryPop Pick % : " << mpop_sur << "(" << global.pick.pop .success << " / " << global.pick.pop .mask_attempt << ")\n"; 510 511 double avgQ_push = double(global.qstat.push.value) / global.qstat.push.count; 512 double avgQ_pop = double(global.qstat.pop .value) / global.qstat.pop .count; 513 double avgQ = double(global.qstat.push.value + global.qstat.pop .value) / (global.qstat.push.count + global.qstat.pop .count); 514 os << "Push Avg Qs : " << avgQ_push << " (" << global.qstat.push.count << "ops)\n"; 515 os << "Pop Avg Qs : " << avgQ_pop << " (" << global.qstat.pop .count << "ops)\n"; 516 os << "Global Avg Qs : " << avgQ << " (" << (global.qstat.push.count + global.qstat.pop .count) << "ops)\n"; 517 } 518 #endif 429 519 };
Note: See TracChangeset
for help on using the changeset viewer.