#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 = 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 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;
std::uniform_real_distribution<double> uniform(-100, 100);
auto engine = pool.get();
hpc::matvec::apply(A, [&](ElementType& val, Index i, Index j) -> void {
val = uniform(engine);
});
pool.free(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");
}