Sample solution

Content

#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;
      T get() {
         /* check if we have a free engine in the unused list */
         {
            std::lock_guard<std::mutex> lock(mutex);
            if (unused.size() > 0) {
               T rg = std::move(unused.front());
               unused.pop_front();
               return rg;
            }
         }
         /* prepare new random generator */
         return T(r());
      }
      void free(T&& engine) {
         std::lock_guard<std::mutex> lock(mutex);
         unused.push_back(engine);
      }
   private:
      std::mutex mutex;
      std::random_device r;
      std::list<T> unused;
};

template<typename T>
struct RandomEngineGuard {
   using EngineType = T;
   RandomEngineGuard(RandomEnginePool<T>& pool) :
      pool(pool), engine(pool.get()) {
   }
   ~RandomEngineGuard() {
      pool.free(std::move(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;
   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_init11 random_init11.cpp
theon$ ./random_init11
   52.05  -84.42  -70.41   82.71   42.99  -10.32  -26.67
   18.42  -67.41  -98.07  -52.44   32.25   38.25   94.61
  -96.13  -95.66   93.61  -14.67  -18.19    1.62   31.80
    9.01  -54.77  -67.99  -36.52   25.79    4.47  -50.03
   80.51    9.21  -45.58  -57.71  -93.08  -96.91  -64.45
  -68.71  -76.98   -6.86   -4.40   -3.40  -42.95   81.60
  -22.70  -35.60  -51.70  -75.60  -69.47   25.08  -94.80
  -67.77   52.75   -2.80   16.00  -15.22  -71.08  -11.12
   79.68   11.78   75.86   83.90    9.78  -86.12   23.36
   52.41   65.12  -80.13  -18.31  -58.01  -66.47  -26.16
   68.37   56.91  -42.28  -49.31  -87.41   29.05   80.23
   73.17  -60.38  -34.49  -17.82   27.98   43.84  -14.49
   22.11   -7.32   40.94  -31.15  -11.52  -95.68   75.82
  -75.69  -36.68  -74.44  -11.45  -37.08   12.85  -67.06
  -71.38   72.95   97.41   37.68   33.07  -86.24  -23.83
   44.00   60.54  -86.69  -11.59   27.79  -12.76   -4.94
   -5.48  -27.00   20.48   -4.65  -23.89   21.78   81.62
  -53.42  -42.26  -63.81   14.61   62.05  -95.61   97.66
  -18.66  -82.45  -35.22   83.93  -70.50   41.23    8.53
  -76.29  -88.75   37.39  -26.61  -69.61  -81.37  -94.74
  -15.67  -28.90    3.77  -89.33   42.83  -32.81   -3.57
   60.41  -63.28  -95.06   53.32  -91.42   44.80   76.33
  -46.25   24.22   -4.99  -16.86   16.55   40.34   99.24
   53.14   12.15  -20.86   14.80  -42.90  -59.19  -84.50
   -6.02   46.38  -15.88   95.35   63.49  -12.10  -84.82
   96.46   -1.44    1.57   57.75  -89.38  -19.93    0.21
  -19.42   73.92  -37.51   13.41  -51.27   13.01   13.74
  -65.19  -48.52   80.76   55.04   49.35  -64.61  -56.82
   -5.21   64.21   68.86  -53.74  -77.67   97.51   81.25
  -23.70  -90.48    1.87  -37.97   -7.07  -53.05   96.32
  -40.13   45.47  -38.37  -84.48  -38.19  -80.99    4.82
  -71.17   -0.81  -93.29   31.08   26.49   -3.87  -33.61
  -95.68  -32.96    8.76   68.92  -78.09   42.14  -38.04
    2.82   59.05  -43.83  -95.74   23.91  -21.95  -54.79
  -64.45   90.79  -49.29  -42.83   32.07  -46.61  -90.83
   35.15  -63.41   43.35   99.42  -91.02   72.04   27.14
   -8.49  -38.77  -86.11   79.22   77.04   40.39   75.72
   62.94  -26.84  -89.79  -38.39   86.08   44.47  -49.29
  -41.06  -97.89  -21.50   85.16  -96.68   64.89   24.91
   -5.58   81.60  -12.94   59.97   -5.03   69.06   50.61
   67.83  -57.11   46.39  -54.23   -9.37  -88.16  -19.27
  -29.50   -2.96   68.65   83.50   53.72  -67.49  -32.26
   69.38  -84.02  -10.05  -12.30   76.54   72.94   33.93
  -77.29   68.07  -20.85  -76.94  -91.80    2.44   58.24
   85.18  -35.56   69.53  -83.92   13.84  -25.58  -28.67
  -60.53  -80.18   14.90   -7.27   88.86   81.02  -38.75
   35.69  -67.53   13.23   30.54   13.55  -70.63  -89.98
  -57.03  -69.84  -36.94   -5.20   44.46  -12.10   28.91
  -56.69   77.09   48.39  -43.31  -27.18   27.01   -0.40
  -31.97  -50.45  -55.41  -32.06   14.85   86.69  -29.84
  -41.44   73.78  -47.88   94.31   32.61  -65.25  -38.40
theon$