#include #include #include #include #include #include #include #include #include #include using namespace hpc; using namespace hpc::aux; using namespace hpc::matvec; template 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 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 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 inuse; std::vector engines; }; template struct RandomEngineGuard { using EngineType = T; RandomEngineGuard(RandomEnginePool& pool) : pool(pool), engine(pool.get()) { } ~RandomEngineGuard() { pool.free(engine); } T& get() { return engine; } RandomEnginePool& pool; T& engine; }; template < template class MatrixA, typename T, typename POOL, Require< Ge> > = true > void randomInit(MatrixA& A, POOL& pool) { using EngineType = typename POOL::EngineType; RandomEngineGuard guard(pool); std::uniform_real_distribution 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 pool(2); GeMatrix A(51, 7); std::size_t nof_threads = std::thread::hardware_concurrency(); std::vector threads(nof_threads); UniformSlices 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"); }