Skip to content

Commit

Permalink
Now we have 2 thread pools.
Browse files Browse the repository at this point in the history
  • Loading branch information
martun committed Jan 29, 2024
1 parent a5a65ea commit fce0696
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 57 deletions.
33 changes: 20 additions & 13 deletions include/nil/crypto3/math/multithreading/thread_pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

#include <functional>
#include <future>
#include <thread>
#include <limits>
#include <memory>
#include <stdexcept>

Expand All @@ -46,17 +48,13 @@ namespace nil {
class ThreadPool {
public:

static std::unique_ptr<ThreadPool> instance;
static ThreadPool& get_instance(std::size_t pool_number, std::size_t pool_size = std::thread::hardware_concurrency()) {
static std::map<std::size_t, std::unique_ptr<ThreadPool>> instances;

static void start(std::size_t pool_size) {
instance.reset(new ThreadPool(pool_size));
}

static ThreadPool& get_instance() {
if (!instance) {
throw std::logic_error("Getting instance of a thread pool before it was started.");
if (instances.find(pool_number) == instances.end() || !instances[pool_number]) {
instances[pool_number].reset(new ThreadPool(pool_number, pool_size));
}
return *instance;
return *instances[pool_number];
}

ThreadPool(const ThreadPool& obj)= delete;
Expand Down Expand Up @@ -85,6 +83,13 @@ namespace nil {
std::size_t cpu_usage = std::min(elements_count, pool_size);
std::size_t element_per_cpu = elements_count / cpu_usage;

// Pool #0 will take care of the lowest level of operations, like polynomial operations.
// We want the minimal size of element_per_cpu to be 65536, otherwise the cores are not loaded.
if (pool_number == 0 && element_per_cpu < 65536) {
cpu_usage = elements_count / 65536 + elements_count % 65536 ? 1 : 0;
element_per_cpu = elements_count / cpu_usage;
}

for (int i = 0; i < cpu_usage; i++) {
auto begin = element_per_cpu * i;
auto end = (i == cpu_usage - 1) ? elements_count : element_per_cpu * (i + 1);
Expand All @@ -96,16 +101,18 @@ namespace nil {
}

private:
inline ThreadPool(std::size_t pool_size)
inline ThreadPool(std::size_t pool_number, std::size_t pool_size)
: pool(pool_size)
, pool_size(pool_size){
, pool_size(pool_size)
, pool_number(pool_number) {
}

boost::asio::thread_pool pool;
std::size_t pool_size;
};

std::unique_ptr<ThreadPool> ThreadPool::instance = nullptr;
// Each pool with know it's number.
std::size_t pool_number;
};

} // namespace crypto3
} // namespace nil
Expand Down
18 changes: 8 additions & 10 deletions include/nil/crypto3/math/polynomial/polynomial_dfs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ namespace nil {
if (this->size() > other.size()) {
polynomial_dfs tmp(other);
tmp.resize(this->size());
wait_for_all(ThreadPool::get_instance().block_execution<void>(
wait_for_all(ThreadPool::get_instance(0).block_execution<void>(
result.size(),
[&result, &tmp](std::size_t begin, std::size_t end) {
for (std::size_t i = begin; i < end; i++) {
Expand All @@ -447,7 +447,7 @@ namespace nil {
return result;
}

wait_for_all(ThreadPool::get_instance().block_execution<void>(
wait_for_all(ThreadPool::get_instance(0).block_execution<void>(
result.size(),
[&result, &other](std::size_t begin, std::size_t end) {
for (std::size_t i = begin; i < end; i++) {
Expand All @@ -472,7 +472,7 @@ namespace nil {
polynomial_dfs tmp(other);
tmp.resize(this->size());

wait_for_all(ThreadPool::get_instance().block_execution<void>(
wait_for_all(ThreadPool::get_instance(0).block_execution<void>(
this->size(),
[this, &tmp](std::size_t begin, std::size_t end) {
for (std::size_t i = begin; i < end; i++) {
Expand All @@ -482,7 +482,7 @@ namespace nil {
return *this;
}

wait_for_all(ThreadPool::get_instance().block_execution<void>(
wait_for_all(ThreadPool::get_instance(0).block_execution<void>(
this->size(),
[this, &other](std::size_t begin, std::size_t end) {
for (std::size_t i = begin; i < end; i++) {
Expand Down Expand Up @@ -583,7 +583,7 @@ namespace nil {
if (other.size() < polynomial_s) {
polynomial_dfs tmp(other);
tmp.resize(polynomial_s);
wait_for_all(ThreadPool::get_instance().block_execution<void>(
wait_for_all(ThreadPool::get_instance(0).block_execution<void>(
result.size(),
[&result, &tmp](std::size_t begin, std::size_t end) {
for (std::size_t i = begin; i < end; i++) {
Expand All @@ -593,14 +593,12 @@ namespace nil {

return result;
}
wait_for_all(ThreadPool::get_instance().block_execution<void>(
wait_for_all(ThreadPool::get_instance(0).block_execution<void>(
result.size(),
[&result, &other](std::size_t begin, std::size_t end) {
//std::cout << "Multiplying range " << begin << " " << end << std::endl;
for (std::size_t i = begin; i < end; i++) {
result[i] *= other[i];
}
//std::cout << "Done Multiplying range " << begin << " " << end << std::endl;
}));

return result;
Expand All @@ -626,7 +624,7 @@ namespace nil {
polynomial_dfs tmp(other);
tmp.resize(polynomial_s);

wait_for_all(ThreadPool::get_instance().block_execution<void>(
wait_for_all(ThreadPool::get_instance(0).block_execution<void>(
this->size(),
[this, &tmp](std::size_t begin, std::size_t end) {
for (std::size_t i = begin; i < end; i++) {
Expand All @@ -635,7 +633,7 @@ namespace nil {
}));
return *this;
}
wait_for_all(ThreadPool::get_instance().block_execution<void>(
wait_for_all(ThreadPool::get_instance(0).block_execution<void>(
this->size(),
[this, &other](std::size_t begin, std::size_t end) {
for (std::size_t i = begin; i < end; i++) {
Expand Down
66 changes: 32 additions & 34 deletions test/polynomial_dfs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1296,7 +1296,7 @@ BOOST_AUTO_TEST_CASE(polynomial_dfs_zero_one_test) {
BOOST_CHECK((small_poly - one * small_poly).is_zero());
}

BOOST_AUTO_TEST_CASE(polynomial_dfs_addition_perf_test) {
BOOST_AUTO_TEST_CASE(polynomial_dfs_addition_perf_test, *boost::unit_test::disabled()) {
std::vector<typename FieldType::value_type> values;
for (int i = 0; i < 131072; i++) {
values.push_back(nil::crypto3::algebra::random_element<FieldType>());
Expand All @@ -1309,23 +1309,43 @@ BOOST_AUTO_TEST_CASE(polynomial_dfs_addition_perf_test) {
}
}

BOOST_AUTO_TEST_CASE(polynomial_dfs_multiplication_perf_test) {
nil::crypto3::ThreadPool::start(8);

size_t size = 131072 * 32;
BOOST_AUTO_TEST_CASE(polynomial_dfs_multiplication_perf_test, *boost::unit_test::disabled()) {
size_t size = 8;

polynomial_dfs<typename FieldType::value_type> poly = {
size / 4096, size, nil::crypto3::algebra::random_element<FieldType>()};
size / 4, size, nil::crypto3::algebra::random_element<FieldType>()};

std::vector<polynomial_dfs<typename FieldType::value_type>> poly4(40, poly);

auto start = std::chrono::high_resolution_clock::now();
nil::crypto3::wait_for_all(nil::crypto3::ThreadPool::get_instance(1).block_execution<void>(
poly4.size(),
[&poly4, &poly](std::size_t begin, std::size_t end) {
for (std::size_t i = begin; i < end; i++) {
for (int j = 0; j < 1; ++j)
poly4[i] *= poly;
}
}));

for (int i = 1; i < poly4.size(); ++i) {
if (poly4[i] != poly4[0]) {
std::cout << i << std::endl;
std::cout << poly4[i] << std::endl << std::endl;
std::cout << poly4[0] << std::endl << std::endl;
return;
}
}

polynomial_dfs<typename FieldType::value_type> poly4 = poly;
// Record the end time
auto end = std::chrono::high_resolution_clock::now();

for (int i = 0; i < 100; ++i) {
poly4 *= poly;
}
BOOST_CHECK(poly4 != poly);
// Calculate the duration
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);

std::cout << "Multiplication time: " << duration.count() << " microseconds." << std::endl;
}

BOOST_AUTO_TEST_CASE(polynomial_dfs_resize_perf_test) {
BOOST_AUTO_TEST_CASE(polynomial_dfs_resize_perf_test, *boost::unit_test::disabled()) {
std::vector<typename FieldType::value_type> values;
size_t size = 131072 * 16;
for (int i = 0; i < size; i++) {
Expand All @@ -1340,26 +1360,4 @@ BOOST_AUTO_TEST_CASE(polynomial_dfs_resize_perf_test) {
}
}

BOOST_AUTO_TEST_CASE(vector_mult_test) {
nil::crypto3::ThreadPool::start(8);

size_t size = 131072 * 16 * 16;
std::vector<int> result(size);
std::vector<int> other(size);
for (int i = 0; i < result.size(); ++i) {
result[i] = rand();
other[i] = rand();
}

for (int i = 0; i < 1000; ++i) {
nil::crypto3::wait_for_all(nil::crypto3::ThreadPool::get_instance().block_execution<void>(
result.size(),
[&result, &other](std::size_t begin, std::size_t end) {
for (std::size_t i = begin; i < end; i++) {
result[i] *= other[i];
}
}));
}
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit fce0696

Please sign in to comment.