Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions barretenberg/cpp/src/barretenberg/common/thread_utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "thread_utils.hpp"

/**
Comment thread
lucasxia01 marked this conversation as resolved.
* @brief calculates number of threads to create based on minimum iterations per thread
* @details Finds the number of cpus with get_num_cpus(), and calculates `desired_num_threads`
* Returns the min of `desired_num_threads` and `max_num_theads`.
* Note that it will not calculate a power of 2 necessarily, use `calc_num_threads_pow2` instead
Comment thread
lucasxia01 marked this conversation as resolved.
Outdated
*
* @param num_iterations
* @param min_iterations_per_thread
* @return size_t
*/
size_t calc_num_threads(size_t num_iterations, size_t min_iterations_per_thread)
{
size_t max_num_threads = get_num_cpus(); // number of available threads
size_t desired_num_threads = num_iterations / min_iterations_per_thread;
size_t num_threads = std::min(desired_num_threads, max_num_threads); // fewer than max if justified
num_threads = num_threads > 0 ? num_threads : 1;
return num_threads;
}
15 changes: 15 additions & 0 deletions barretenberg/cpp/src/barretenberg/common/thread_utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "thread.hpp"

const size_t MIN_ITERS_PER_THREAD = 1 << 4;
Comment thread
lucasxia01 marked this conversation as resolved.
Outdated

/**
* @brief calculates number of threads to create based on minimum iterations per thread
* @details Finds the number of cpus with get_num_cpus(), and calculates `desired_num_threads`
* Returns the min of `desired_num_threads` and `max_num_theads`.
* Note that it will not calculate a power of 2 necessarily, use `calc_num_threads_pow2` instead
*
* @param num_iterations
* @param min_iterations_per_thread
* @return size_t
*/
size_t calc_num_threads(size_t num_iterations, size_t min_iterations_per_thread);
Comment thread
lucasxia01 marked this conversation as resolved.
Outdated
72 changes: 47 additions & 25 deletions barretenberg/cpp/src/barretenberg/polynomials/polynomial.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
#include "polynomial.hpp"
#include "barretenberg/common/assert.hpp"
#include "barretenberg/common/slab_allocator.hpp"
#include "polynomial_arithmetic.hpp"
#include <cstddef>
#include <fcntl.h>
#include <list>
Expand All @@ -11,6 +7,13 @@
#include <unordered_map>
#include <utility>

#include "barretenberg/common/assert.hpp"
#include "barretenberg/common/slab_allocator.hpp"
#include "barretenberg/common/thread.hpp"
#include "barretenberg/common/thread_utils.hpp"
#include "polynomial.hpp"
#include "polynomial_arithmetic.hpp"
Comment thread
lucasxia01 marked this conversation as resolved.
Outdated

namespace barretenberg {
/**
* Constructors / Destructors
Expand Down Expand Up @@ -272,25 +275,34 @@ template <typename Fr> void Polynomial<Fr>::add_scaled(std::span<const Fr> other
const size_t other_size = other.size();
ASSERT(in_place_operation_viable(other_size));

/** TODO parallelize using some kind of generic evaluation domain
* we really only need to know the thread size, but we don't need all the FFT roots
/** Calculates number of threads with calc_num_threads
* Possible improvements: standardize this parallelization code

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible improvement done by your thread util? Our policy should be: either it's worth an explicit Github issue or it's not worth leaving as a TODO.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're welcome to go further and make a function that returns an array of three size_ts and then unpack as in

auto [num_threads, range_per_thread, leftovers] = get_parallel_for_parameters(...)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats a decent idea, but maybe I'll create a function that just does this whole thing, taking in number of iterations, and a function?

*/
for (size_t i = 0; i < other_size; ++i) {
coefficients_.get()[i] += scaling_factor * other[i];
}
size_t num_threads = calc_num_threads(other_size, MIN_ITERS_PER_THREAD);
size_t range_per_thread = other_size / num_threads;
size_t leftovers = other_size - (range_per_thread * num_threads);
parallel_for(num_threads, [&](size_t j) {
size_t offset = j * range_per_thread;
size_t end = (j == num_threads - 1) ? offset + range_per_thread + leftovers : offset + range_per_thread;
for (size_t i = offset; i < end; ++i)
coefficients_.get()[i] += scaling_factor * other[i];
});
}

template <typename Fr> Polynomial<Fr>& Polynomial<Fr>::operator+=(std::span<const Fr> other)
{
const size_t other_size = other.size();
ASSERT(in_place_operation_viable(other_size));

/** TODO parallelize using some kind of generic evaluation domain
* we really only need to know the thread size, but we don't need all the FFT roots
*/
for (size_t i = 0; i < other_size; ++i) {
coefficients_.get()[i] += other[i];
}
size_t num_threads = calc_num_threads(other_size, MIN_ITERS_PER_THREAD);
size_t range_per_thread = other_size / num_threads;
size_t leftovers = other_size - (range_per_thread * num_threads);
parallel_for(num_threads, [&](size_t j) {
size_t offset = j * range_per_thread;
size_t end = (j == num_threads - 1) ? offset + range_per_thread + leftovers : offset + range_per_thread;
for (size_t i = offset; i < end; ++i)
coefficients_.get()[i] += other[i];
});

return *this;
}
Expand All @@ -300,23 +312,33 @@ template <typename Fr> Polynomial<Fr>& Polynomial<Fr>::operator-=(std::span<cons
const size_t other_size = other.size();
ASSERT(in_place_operation_viable(other_size));

/** TODO parallelize using some kind of generic evaluation domain
* we really only need to know the thread size, but we don't need all the FFT roots
*/
for (size_t i = 0; i < other_size; ++i) {
coefficients_.get()[i] -= other[i];
}
size_t num_threads = calc_num_threads(other_size, MIN_ITERS_PER_THREAD);
size_t range_per_thread = other_size / num_threads;
size_t leftovers = other_size - (range_per_thread * num_threads);
parallel_for(num_threads, [&](size_t j) {
size_t offset = j * range_per_thread;
size_t end = (j == num_threads - 1) ? offset + range_per_thread + leftovers : offset + range_per_thread;
for (size_t i = offset; i < end; ++i)
coefficients_.get()[i] -= other[i];
});

return *this;
}

template <typename Fr> Polynomial<Fr>& Polynomial<Fr>::operator*=(const Fr scaling_facor)
template <typename Fr> Polynomial<Fr>& Polynomial<Fr>::operator*=(const Fr scaling_factor)
{
ASSERT(in_place_operation_viable());

for (size_t i = 0; i < size_; ++i) {
coefficients_.get()[i] *= scaling_facor;
}
size_t num_threads = calc_num_threads(size_, MIN_ITERS_PER_THREAD);
size_t range_per_thread = size_ / num_threads;
size_t leftovers = size_ - (range_per_thread * num_threads);
parallel_for(num_threads, [&](size_t j) {
size_t offset = j * range_per_thread;
size_t end = (j == num_threads - 1) ? offset + range_per_thread + leftovers : offset + range_per_thread;
for (size_t i = offset; i < end; ++i)
coefficients_.get()[i] *= scaling_factor;
});

return *this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ template <typename Fr> class Polynomial {
*
* @param scaling_factor s
*/
Polynomial& operator*=(const Fr scaling_facor);
Polynomial& operator*=(const Fr scaling_factor);

/**
* @brief evaluates p(X) = ∑ᵢ aᵢ⋅Xⁱ considered as multi-linear extension p(X₀,…,Xₘ₋₁) = ∑ᵢ aᵢ⋅Lᵢ(X₀,…,Xₘ₋₁)
Expand Down