#include <thread>
#include <random>
#include <cstdlib>
#include <list>
#include <mutex>
#include <vector>
#include <hpc/matvec/gematrix.h>
#include <hpc/matvec/apply.h>
#include <hpc/matvec/print.h>
#include <hpc/aux/slices.h>
template<typename T>
struct RandomEnginePool {
using EngineType = T;
T get() {
/* check if we have a free engine in unused */
{
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<typename MA, typename Pool>
typename std::enable_if<hpc::matvec::IsRealGeMatrix<MA>::value, void>::type
randomInit(MA& A, Pool& pool) {
using ElementType = typename MA::ElementType;
using Index = typename MA::Index;
using EngineType = typename Pool::EngineType;
std::uniform_real_distribution<double> uniform(-100, 100);
RandomEngineGuard<EngineType> guard(pool);
auto& engine(guard.get());
hpc::matvec::apply(A, [&](ElementType& val, Index i, Index j) -> void {
val = uniform(engine);
});
}
int main() {
using namespace hpc::matvec;
using namespace hpc::aux;
RandomEnginePool<std::mt19937> pool;
GeMatrix<double> A(51, 7);
unsigned int nof_threads = std::thread::hardware_concurrency();
std::vector<std::thread> threads(nof_threads);
Slices<GeMatrix<double>::Index> slices(nof_threads, A.numRows);
for (int index = 0; index < nof_threads; ++index) {
auto firstRow = slices.offset(index);
auto numRows = slices.size(index);
auto A_ = A(firstRow, 0, numRows, A.numCols);
threads[index] = std::thread([=,&pool]() mutable { randomInit(A_, pool); });
}
for (int index = 0; index < nof_threads; ++index) {
threads[index].join();
}
print(A, "A");
}