Changeset 95cb63b
- Timestamp:
- May 22, 2020, 3:22:43 PM (4 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 8f4f3e0
- Parents:
- 0e4df2e
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/thierry_delisle_PhD/code/relaxed_list.cpp
r0e4df2e r95cb63b 57 57 size_t valmax = 0; 58 58 size_t valmin = 100000000ul; 59 struct { 60 size_t val = 0; 61 size_t cnt = 0; 62 } comp; 63 struct { 64 size_t val = 0; 65 size_t cnt = 0; 66 } subm; 59 67 }; 60 68 … … 67 75 std::atomic_size_t valmax = { 0 }; 68 76 std::atomic_size_t valmin = { 100000000ul }; 77 struct { 78 std::atomic_size_t val = { 0 }; 79 std::atomic_size_t cnt = { 0 }; 80 } comp; 81 struct { 82 std::atomic_size_t val = { 0 }; 83 std::atomic_size_t cnt = { 0 }; 84 } subm; 69 85 }; 70 86 … … 95 111 global.crc_in += local.crc_in; 96 112 global.crc_out += local.crc_out; 113 114 global.comp.val += local.comp.val; 115 global.comp.cnt += local.comp.cnt; 116 global.subm.val += local.subm.val; 117 global.subm.cnt += local.subm.cnt; 97 118 98 119 atomic_max(global.valmax, local.valmax); … … 159 180 auto dur_nano = duration_cast<std::nano>(1.0); 160 181 182 if(global.valmax != 0) { 183 std::cout << "Max runs : " << global.valmax << "\n"; 184 std::cout << "Min runs : " << global.valmin << "\n"; 185 } 186 if(global.comp.cnt != 0) { 187 std::cout << "Submit count : " << global.subm.cnt << "\n"; 188 std::cout << "Submit average: " << ((double(global.subm.val)) / global.subm.cnt) << "\n"; 189 std::cout << "Complete count: " << global.comp.cnt << "\n"; 190 std::cout << "Complete avg : " << ((double(global.comp.val)) / global.comp.cnt) << "\n"; 191 } 161 192 std::cout << "Duration : " << duration << "s\n"; 162 193 std::cout << "ns/Op : " << ( dur_nano / ops_thread )<< "\n"; … … 164 195 std::cout << "Ops/sec : " << ops_sec << "\n"; 165 196 std::cout << "Total ops : " << ops << "(" << global.in << "i, " << global.out << "o, " << global.empty << "e)\n"; 166 if(global.valmax != 0) {167 std::cout << "Max runs : " << global.valmax << "\n";168 std::cout << "Min runs : " << global.valmin << "\n";169 }170 197 #ifndef NO_STATS 171 198 relaxed_list<Node>::stats_print(std::cout); … … 395 422 396 423 enable_stats = false; 424 } 425 426 print_stats(duration, nthread, global); 427 } 428 429 // ================================================================================================ 430 struct __attribute__((aligned(64))) Slot { 431 Node * volatile node; 432 }; 433 434 __attribute__((noinline)) void runProducer_body( 435 std::atomic<bool>& done, 436 Random & rand, 437 Slot * slots, 438 int nslots, 439 local_stat_t & local, 440 relaxed_list<Node> & list 441 ) { 442 while(__builtin_expect(!done.load(std::memory_order_relaxed), true)) { 443 444 Node * node = list.pop(); 445 if(!node) { 446 local.empty ++; 447 continue; 448 } 449 450 local.crc_out += node->value; 451 local.out++; 452 453 if(node->id == 0) { 454 unsigned cnt = 0; 455 for(int i = 0; i < nslots; i++) { 456 Node * found = __atomic_exchange_n( &slots[i].node, nullptr, __ATOMIC_SEQ_CST ); 457 if( found ) { 458 local.crc_in += found->value; 459 local.in++; 460 cnt++; 461 list.push( found ); 462 } 463 } 464 465 local.crc_in += node->value; 466 local.in++; 467 list.push( node ); 468 469 local.comp.cnt++; 470 local.comp.val += cnt; 471 } 472 else { 473 unsigned len = 0; 474 while(true) { 475 auto off = rand.next(); 476 for(int i = 0; i < nslots; i++) { 477 Node * expected = nullptr; 478 int idx = (i + off) % nslots; 479 Slot & slot = slots[ idx ]; 480 if( 481 slot.node == nullptr && 482 __atomic_compare_exchange_n( &slot.node, &expected, node, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) 483 ) { 484 local.subm.cnt++; 485 local.subm.val += len; 486 goto LOOP; 487 } 488 assert( expected != node ); 489 len++; 490 } 491 } 492 } 493 494 LOOP:; 495 } 496 } 497 498 void runProducer(unsigned nthread, unsigned nqueues, double duration, unsigned nnodes) { 499 std::cout << "Producer Benchmark" << std::endl; 500 501 // Barrier for synchronization 502 barrier_t barrier(nthread + 1); 503 504 // Data to check everything is OK 505 global_stat_t global; 506 507 // Flag to signal termination 508 std::atomic_bool done = { false }; 509 510 std::cout << "Initializing "; 511 512 int nslots = nnodes * 4; 513 Slot * slots = new Slot[nslots]; 514 std::cout << nnodes << " nodes (" << nslots << " slots)" << std::endl; 515 516 // List being tested 517 relaxed_list<Node> list = { nthread * nqueues }; 518 { 519 Random rand(rdtscl()); 520 for(unsigned i = 0; i < nnodes; i++) { 521 Node * node = new Node(rand.next() % 100); 522 node->id = i; 523 global.crc_in += node->value; 524 list.push(node); 525 } 526 527 for(int i = 0; i < nslots; i++) { 528 slots[i].node = nullptr; 529 } 530 } 531 532 { 533 enable_stats = true; 534 535 std::thread * threads[nthread]; 536 unsigned i = 1; 537 for(auto & t : threads) { 538 t = new std::thread([&done, &list, &barrier, &global, slots, nslots](unsigned tid) { 539 Random rand(tid + rdtscl()); 540 541 local_stat_t local; 542 barrier.wait(tid); 543 544 // EXPERIMENT START 545 546 runProducer_body(done, rand, slots, nslots, local, list); 547 548 // EXPERIMENT END 549 550 barrier.wait(tid); 551 552 tally_stats(global, local); 553 }, i++); 554 } 555 556 waitfor(duration, barrier, done); 557 558 for(auto t : threads) { 559 t->join(); 560 delete t; 561 } 562 563 enable_stats = false; 564 } 565 566 { 567 while(Node * node = list.pop()) { 568 global.crc_out += node->value; 569 delete node; 570 } 571 572 for(int i = 0; i < nslots; i++) { 573 delete slots[i].node; 574 } 575 576 delete [] slots; 397 577 } 398 578 … … 521 701 print_stats(duration, nthread, global); 522 702 523 save_fairness(data_out.get(), 100, nthread, width, length, output);703 // save_fairness(data_out.get(), 100, nthread, width, length, output); 524 704 } 525 705 … … 547 727 Churn, 548 728 PingPong, 729 Producer, 549 730 Fairness, 550 731 NONE … … 577 758 case PingPong: 578 759 nnodes = 1; 579 nslots = 1;580 760 switch(argc - optind) { 581 761 case 0: break; … … 591 771 break; 592 772 default: 593 std::cerr << "'PingPong' benchmark doesn't accept more than 2 extra arguments" << std::endl; 773 std::cerr << "'PingPong' benchmark doesn't accept more than 1 extra arguments" << std::endl; 774 goto usage; 775 } 776 break; 777 case Producer: 778 nnodes = 32; 779 switch(argc - optind) { 780 case 0: break; 781 case 1: 782 try { 783 arg = optarg = argv[optind]; 784 nnodes = stoul(optarg, &len); 785 if(len != arg.size()) { throw std::invalid_argument(""); } 786 } catch(std::invalid_argument &) { 787 std::cerr << "Number of nodes must be a positive integer, was " << arg << std::endl; 788 goto usage; 789 } 790 break; 791 default: 792 std::cerr << "'Producer' benchmark doesn't accept more than 1 extra arguments" << std::endl; 594 793 goto usage; 595 794 } … … 662 861 break; 663 862 } 863 if(iequals(arg, "producer")) { 864 benchmark = Producer; 865 break; 866 } 664 867 if(iequals(arg, "fairness")) { 665 868 benchmark = Fairness; … … 702 905 std::cerr << "Usage: " << argv[0] << ": [options] -b churn [NNODES] [NSLOTS = NNODES]" << std::endl; 703 906 std::cerr << " or: " << argv[0] << ": [options] -b pingpong [NNODES]" << std::endl; 907 std::cerr << " or: " << argv[0] << ": [options] -b producer [NNODES]" << std::endl; 704 908 std::cerr << std::endl; 705 909 std::cerr << " -d, --duration=DURATION Duration of the experiment, in seconds" << std::endl; … … 720 924 case PingPong: 721 925 runPingPong(nthreads, nqueues, duration, nnodes); 926 break; 927 case Producer: 928 runProducer(nthreads, nqueues, duration, nnodes); 722 929 break; 723 930 case Fairness: … … 801 1008 } 802 1009 803 void save_fairness(const int data[], int factor, unsigned nthreads, size_t columns, size_t rows, const std::string & output) {804 std::ofstream os(output);805 os << "<html>\n";806 os << "<head>\n";807 os << "<style>\n";808 os << "</style>\n";809 os << "</head>\n";810 os << "<body>\n";811 os << "<table style=\"width=100%\">\n";812 813 size_t idx = 0;814 for(size_t r = 0ul; r < rows; r++) {815 os << "<tr>\n";816 for(size_t c = 0ul; c < columns; c++) {817 os << "<td class=\"custom custom" << data[idx] << "\"></td>\n";818 idx++;819 }820 os << "</tr>\n";821 }822 823 os << "</table>\n";824 os << "</body>\n";825 os << "</html>\n";826 os << std::endl;827 }828 829 #include <png.h>830 #include <setjmp.h>1010 // void save_fairness(const int data[], int factor, unsigned nthreads, size_t columns, size_t rows, const std::string & output) { 1011 // std::ofstream os(output); 1012 // os << "<html>\n"; 1013 // os << "<head>\n"; 1014 // os << "<style>\n"; 1015 // os << "</style>\n"; 1016 // os << "</head>\n"; 1017 // os << "<body>\n"; 1018 // os << "<table style=\"width=100%\">\n"; 1019 1020 // size_t idx = 0; 1021 // for(size_t r = 0ul; r < rows; r++) { 1022 // os << "<tr>\n"; 1023 // for(size_t c = 0ul; c < columns; c++) { 1024 // os << "<td class=\"custom custom" << data[idx] << "\"></td>\n"; 1025 // idx++; 1026 // } 1027 // os << "</tr>\n"; 1028 // } 1029 1030 // os << "</table>\n"; 1031 // os << "</body>\n"; 1032 // os << "</html>\n"; 1033 // os << std::endl; 1034 // } 1035 1036 // #include <png.h> 1037 // #include <setjmp.h> 831 1038 832 1039 /*
Note: See TracChangeset
for help on using the changeset viewer.