Sample solution

Content

#include <condition_variable>
#include <cstdlib>
#include <list>
#include <mutex>
#include <random>
#include <thread>
#include <vector>
#include <hpc/aux/slices.hpp>
#include <hpc/matvec/gematrix.hpp>
#include <hpc/matvec/iterators.hpp>
#include <hpc/matvec/print.hpp>

using namespace hpc;
using namespace hpc::matvec;
using namespace hpc::aux;

template<typename T>
struct RandomEnginePool {
      using EngineType = T;
      RandomEnginePool(std::size_t size) :
	    size(size), nof_free_engines(size),
	    inuse(size), engines(size) {
	 std::random_device r;
	 for (std::size_t i = 0; i < size; ++i) {
	    engines[i].seed(r()); inuse[i] = false;
	 }
      }
      T& get() {
	 std::unique_lock<std::mutex> lock(mutex);
	 while (nof_free_engines == 0) {
	    cv.wait(lock);
	 }
	 for (std::size_t i = 0; i < size; ++i) {
	    if (!inuse[i]) {
	       inuse[i] = true; --nof_free_engines;
	       return engines[i];
	    }
	 }
	 assert(false);
	 #pragma GCC diagnostic ignored "-Wreturn-type"
      }
      void free(T& engine) {
	 {
	    std::unique_lock<std::mutex> lock(mutex);
	    bool found = false;
	    for (std::size_t i = 0; i < size; ++i) {
	       if (&engine == &engines[i]) {
		  inuse[i] = false; ++nof_free_engines;
		  found = true; break;
	       }
	    }
	    assert(found);
	 }
	 cv.notify_one();
      }
   private:
      std::mutex mutex;
      std::condition_variable cv;
      std::size_t size;
      std::size_t nof_free_engines;
      std::vector<bool> inuse;
      std::vector<T> engines;
};

template<typename T>
struct RandomEngineGuard {
   using EngineType = T;
   RandomEngineGuard(RandomEnginePool<T>& pool) :
      pool(pool), engine(pool.get()) {
   }
   ~RandomEngineGuard() {
      pool.free(engine);
   }
   T& get() {
      return engine;
   }
   RandomEnginePool<T>& pool;
   T& engine;
};

template <
   template<typename> class MatrixA, typename T,
   typename POOL,
   Require< Ge<MatrixA<T>> > = true
>
void randomInit(MatrixA<T>& A, POOL& pool) {
   using EngineType = typename POOL::EngineType;
   RandomEngineGuard<EngineType> guard(pool);
   std::uniform_real_distribution<double> uniform(-100, 100);
   auto& engine = guard.get();

   for (auto [i, j, Aij]: A) {
      Aij = uniform(engine);
      (void) i; (void) j; // suppress gcc warning
   }
}

int main() {
   RandomEnginePool<std::mt19937> pool(2);
   GeMatrix<double> A(51, 7);
   std::size_t nof_threads = std::thread::hardware_concurrency();

   std::vector<std::thread> threads(nof_threads);
   UniformSlices<std::size_t> slices(nof_threads, A.numRows());
   for (std::size_t index = 0; index < nof_threads; ++index) {
      auto firstRow = slices.offset(index);
      auto numRows = slices.size(index);
      threads[index] = std::thread([
	       A_ = A.view(firstRow, 0, numRows, A.numCols()),
	       &pool
	    ]() mutable {
	 randomInit(A_, pool);
      });
   }
   for (std::size_t index = 0; index < nof_threads; ++index) {
      threads[index].join();
   }
   print(A, " %7.2f");
}
theon$ g++ -O3 -g -I/home/numerik/pub/hpc/ws18/session16 -std=c++17 -o random_init12 random_init12.cpp
theon$ ./random_init12
   91.67   40.08  -16.18  -44.78    2.82  -26.80   72.12
   76.92  -26.13    5.21   92.40   94.37    3.62  -43.70
   83.16   96.61  -59.61  -69.57  -35.10  -52.70   39.95
   35.01  -33.91  -46.07   34.67   20.12  -35.46   81.39
  -95.23  -10.26    4.48   91.55   12.13   30.12   85.64
  -79.13   43.93   86.74   38.63   78.19  -78.12  -77.95
  -11.74  -48.54    2.15    0.36   74.00  -89.90  -54.96
   48.31    9.40   98.51    3.96   86.50   82.66    6.24
   -4.60   29.66   38.76   25.43   87.69   -6.25  -61.40
   68.47   16.71  -87.28   35.77   34.97  -81.61   -6.21
  -17.21   34.78  -81.83  -39.14  -30.20   33.59  -42.88
  -72.49   35.38   48.98   35.77  -35.44  -27.91  -84.33
   69.18   59.69  -84.77  -52.01   36.44  -88.44   97.81
   61.41   38.50  -19.03   64.28   98.83  -41.01   28.03
  -32.55   69.16   43.99    1.16  -98.71   57.37  -92.01
  -94.23   64.35   27.60  -29.61  -44.12  -49.69  -82.82
  -19.91  -61.40   41.64   44.07   85.40  -64.03   98.66
  -16.75  -46.90   -9.70   59.81   17.19   15.10  -46.99
  -75.11  -10.18  -37.99   36.75  -17.74  -35.27   -8.47
  -39.38  -93.50   60.34   70.68   36.35  -17.66   -9.34
    0.46  -48.63   68.29   94.02   16.65  -27.35  -29.15
  -70.08   51.53   21.74  -36.08  -70.23  -48.08   56.89
  -82.48   10.73  -96.87  -68.58    4.11   72.68   55.28
   28.56   80.08   10.02  -63.68   15.96   25.59    7.73
  -33.54  -17.74   -1.52  -11.48  -50.68  -40.32   -9.80
   -2.16   69.23   48.12  -50.27  -29.87   60.55  -94.59
  -61.60  -88.70   66.41   90.34   -3.37  -26.78  -54.71
   25.05  -33.61  -77.84   58.91   16.60  -67.47   92.99
   94.38  -34.62  -80.64   59.59   -1.84    3.26  -49.44
  -31.44   -2.22  -64.94  -69.95    5.53  -46.65  -12.67
   11.07  -46.07    9.40   66.05  -68.06   24.73  -19.35
  -49.23  -61.38  -38.85  -33.31  -19.26   84.77  -60.48
  -53.33   47.25  -64.66   40.18   39.85   92.69   -0.91
   92.44  -75.70   85.57  -36.83   94.54  -76.00  -69.76
  -59.04   94.69   16.09  -96.82  -29.39  -87.35   62.04
  -20.94  -40.23    9.73  -48.59   83.16  -99.54  -46.70
  -21.04   21.16   83.50   68.57  -75.13   35.62   54.82
   33.09   67.80  -86.50   60.81  -76.00   70.90  -72.37
  -62.45   91.64   71.68   72.76   84.33  -85.35    2.25
   65.37   98.93  -70.09   20.07  -18.99  -14.23   -0.42
   10.63  -70.61   68.36  -34.04  -80.54   39.65   98.54
   58.13  -44.00   29.36   76.67   47.63  -48.33   57.59
  -51.95  -20.16  -96.36   19.60   31.39  -43.47   80.93
   61.89  -75.43  -22.66  -15.54  -65.64  -19.99  -81.42
  -55.31   45.89   24.45  -46.79  -28.74  -90.46   97.37
  -83.72  -92.48   24.48   77.37  -72.63  -51.37   51.54
  -46.72  -14.28   67.27  -41.68   56.60  -14.16  -68.96
    2.61    5.03  -72.72  -39.17   91.26   -9.17   79.49
  -21.65   35.92  -13.31   38.18  -53.02  -61.83  -94.34
  -14.11  -40.64   64.29  -70.97  -32.77  -23.81   38.52
   68.20   67.19   95.14   62.63   32.61  -71.26  -73.61
theon$