Advertisement
homer512

Shared mutex benchmark

Aug 17th, 2017
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.55 KB | None | 0 0
  1. #include <omp.h>
  2. // using omp_get_max_threads
  3.  
  4. #include <cmath>
  5. // using std::fabsf, HUGE_VALF
  6. #include <chrono>
  7. // using std::chrono::*
  8. #include <random>
  9. // using std::default_random_engine, std::seedq, std::uniform_*_distribution
  10. #include <iostream>
  11. // using std::cout
  12.  
  13. #include <boost/thread/mutex.hpp>
  14. // using boost::mutex
  15. #include <boost/thread/shared_mutex.hpp>
  16. // using boost::shared_mutex
  17. #include <boost/thread/lock_guard.hpp>
  18. // using boost::lock_guard
  19. #include <boost/thread/shared_lock_guard.hpp>
  20. // using boost::shared_lock_guard
  21.  
  22.  
  23. namespace {
  24.  
  25. #ifdef USE_RWLOCK
  26.   using mutex_type = boost::shared_mutex;
  27.   using read_lock_type = boost::shared_lock_guard<mutex_type>;
  28. #else
  29.   using mutex_type = boost::mutex;
  30.   using read_lock_type = boost::lock_guard<mutex_type>;
  31. #endif
  32.   using write_lock_type = boost::lock_guard<mutex_type>;
  33.  
  34.   enum class Direction { up, down, left, right };
  35.  
  36.   struct Vector2f
  37.   {
  38.     float x, y;
  39.     constexpr Vector2f(float x=0.f, float y=0.f) noexcept
  40.     : x(x), y(y)
  41.     {}
  42.   };
  43.  
  44.   struct UnitState
  45.   {
  46.     Vector2f position, velocity;
  47.     Direction facing;
  48.  
  49.     constexpr UnitState() noexcept
  50.     : position(), velocity(), facing(Direction::up)
  51.     {}
  52.   };
  53.  
  54.   class GameUnit
  55.   {
  56.     mutable mutex_type mutex;
  57.     UnitState state;
  58.     float maxSpeed;
  59.    
  60.   public:
  61.     GameUnit() noexcept
  62.     : mutex(), state(), maxSpeed(HUGE_VALF)
  63.     {}
  64.     UnitState getFullState() const
  65.     {
  66.       read_lock_type lock(mutex);
  67.       return state;
  68.     }
  69.     void updatePosition(float x, float y, Direction facing)
  70.     {
  71.       write_lock_type lock(mutex);
  72.       if(std::fabs(state.position.x - x) > maxSpeed
  73.          || std::fabs(state.position.y - y) > maxSpeed)
  74.         return;
  75.       state.position.x = x;
  76.       state.position.y = y;
  77.       state.facing = facing;
  78.     }
  79.   };
  80.  
  81. }
  82.  
  83.  
  84. int main()
  85. {
  86.   using clock_t = std::chrono::steady_clock;
  87.   constexpr int maxReadsToWrites = 1000;
  88.   constexpr std::chrono::seconds seconds(10);
  89.   const clock_t::duration clock_seconds =
  90.     std::chrono::duration_cast<clock_t::duration>(seconds);
  91.   const int maxThreads = omp_get_max_threads();
  92.   std::seed_seq seed;
  93.   std::uniform_real_distribution<float> floatDistr;
  94.   for(int readsToWrites = 1; readsToWrites <= maxReadsToWrites; readsToWrites *= 10) {
  95.     std::uniform_int_distribution<int> intDistr(0, readsToWrites);
  96.     for(int threads = 1; threads <= maxThreads; threads *= 2) {
  97.       GameUnit unit;
  98.       double opsPerSec = 0.;
  99.       const clock_t::time_point startTime = clock_t::now();
  100. #     pragma omp parallel num_threads(threads)
  101.       {
  102.         std::default_random_engine rnd;
  103. #       pragma omp critical
  104.         rnd = std::default_random_engine(seed);
  105.         long long localOps = 0;
  106.         clock_t::duration dt;
  107.         Vector2f pos;
  108.         for(localOps = 0; (dt = clock_t::now() - startTime) < clock_seconds;
  109.             ++localOps) {
  110.           if(intDistr(rnd))
  111.             pos = unit.getFullState().position;
  112.           else {
  113.             pos.x += floatDistr(rnd);
  114.             pos.y += floatDistr(rnd);
  115.             unit.updatePosition(pos.x, pos.y, Direction::up);
  116.           }
  117.         }
  118.         const double localOpsPerSec = localOps /
  119.           (std::chrono::duration_cast<std::chrono::nanoseconds>(dt).count()
  120.            * 1e-9);
  121. #       pragma omp critical
  122.         opsPerSec += localOpsPerSec;
  123.       }
  124.       std::cout << readsToWrites << " reads per write "
  125.                 << threads << " threads "
  126.                 << opsPerSec << " operations per second\n";
  127.     }
  128.   }
  129. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement