-
-
Notifications
You must be signed in to change notification settings - Fork 447
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
153 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
22 changes: 22 additions & 0 deletions
22
libs/core/synchronization/tests/unit/range_mutex/range_mutex.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#include <hpx/hpx_main.hpp> | ||
#include <hpx/synchronization/mutex.hpp> | ||
#include <hpx/synchronization/range_mutex.hpp> | ||
|
||
#include "range_mutex_util.hpp" | ||
|
||
#include <cstddef> | ||
|
||
int main() | ||
{ | ||
hpx::ranged_lock::test::util::test_lock_n_times< | ||
hpx::synchronization::range_mutex>( | ||
10, 1'00'000, 4, 100, | ||
[](std::size_t x, std::size_t len) { return (std::min)(x + 100, len); }, | ||
[](auto& v, std::size_t begin, std::size_t end) { | ||
for (std::size_t i = begin; i != end; i++) | ||
{ | ||
v[i] += 1; | ||
} | ||
}); | ||
return 0; | ||
} |
130 changes: 130 additions & 0 deletions
130
libs/core/synchronization/tests/unit/range_mutex/range_mutex_util.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
#include <hpx/assert.hpp> | ||
#include <hpx/thread.hpp> | ||
|
||
#include <iterator> | ||
#include <random> | ||
#include <thread> | ||
|
||
using increments_ty = std::vector<std::pair<std::size_t, std::size_t>>; | ||
|
||
std::random_device rnd_device; | ||
std::mt19937 mersenne_engine{rnd_device()}; | ||
|
||
/* | ||
thread execution times of each run | ||
*/ | ||
namespace hpx::ranged_lock::test::util { | ||
template <typename RangeEndGen> | ||
increments_ty get_increment_ranges( | ||
std::size_t const num_ranges, std::size_t const len, RangeEndGen&& f) | ||
{ | ||
increments_ty ranges; | ||
ranges.resize(num_ranges); | ||
|
||
for (std::size_t i = 0; i != num_ranges; i++) | ||
{ | ||
std::size_t x, y; | ||
|
||
x = mersenne_engine() % len; | ||
y = f(x, len); | ||
|
||
std::size_t begin = std::min(x, y); | ||
std::size_t end = std::max(x, y); | ||
|
||
ranges[i] = std::make_pair(begin, end); | ||
} | ||
|
||
return ranges; | ||
} | ||
|
||
template <typename T, typename Modifier> | ||
std::vector<T> get_final_vector(std::vector<T>&& init_vector, | ||
increments_ty increments, Modifier&& modifier) | ||
{ | ||
auto const for_each_unary_func = [&modifier, &init_vector]( | ||
auto const& p) { | ||
std::size_t begin = p.first; | ||
std::size_t end = p.second; | ||
|
||
modifier(init_vector, begin, end); | ||
}; | ||
|
||
std::for_each( | ||
increments.begin(), increments.end(), for_each_unary_func); | ||
|
||
return init_vector; | ||
} | ||
|
||
/* | ||
1) Generates incremenet num_threads * num_incr_per_thread valid ranges | ||
2) Spawns num_threads threads and assigns all equal amount of work | ||
3) Checks if result is valid | ||
NOTE : Critical Section should take care of obtaining the lock | ||
passed as first parameter | ||
*/ | ||
template <typename Lock, typename RangeEndGen, typename CriticalSection> | ||
void test_lock_once(std::size_t const len, std::size_t const num_threads, | ||
std::size_t const num_incr_per_thread, RangeEndGen&& range_end_gen, | ||
CriticalSection&& critical_section) | ||
{ | ||
std::vector<hpx::thread> threads; | ||
std::vector<std::size_t> v(len); | ||
|
||
increments_ty increments = | ||
get_increment_ranges(num_incr_per_thread * num_threads, len, | ||
std::forward<RangeEndGen>(range_end_gen)); | ||
|
||
Lock bl; | ||
|
||
for (std::size_t i = 0; i != num_threads; i++) | ||
{ | ||
increments_ty::iterator start_iter = | ||
increments.begin() + (i * num_incr_per_thread); | ||
|
||
increments_ty::iterator end_iter = | ||
increments.begin() + ((i + 1) * num_incr_per_thread); | ||
|
||
threads.emplace_back( | ||
[&bl, &v, &critical_section, start_iter, end_iter, i]() { | ||
increments_ty::iterator it = start_iter; | ||
for (; it != end_iter; it++) | ||
{ | ||
std::size_t begin = it->first; | ||
std::size_t end = it->second; | ||
|
||
std::size_t lockId = bl.lock(begin, end); | ||
|
||
critical_section(v, begin, end); | ||
|
||
bl.unlock(lockId); | ||
} | ||
}); | ||
} | ||
|
||
for (auto& t : threads) | ||
{ | ||
t.join(); | ||
} | ||
|
||
std::vector<std::size_t> expectedVector = get_final_vector( | ||
std::vector<std::size_t>(len), std::move(increments), | ||
std::forward<CriticalSection>(critical_section)); | ||
|
||
HPX_ASSERT(v == expectedVector); | ||
} | ||
|
||
template <typename Lock, typename RangeEndGen, typename CriticalSection> | ||
void test_lock_n_times(std::size_t const n, std::size_t const len, | ||
std::size_t const num_threads, std::size_t const num_incr_per_thread, | ||
RangeEndGen&& range_end_gen, CriticalSection&& critical_section) | ||
{ | ||
for (std::size_t i = 0; i != n; i++) | ||
{ | ||
test_lock_once<Lock>(len, num_threads, num_incr_per_thread, | ||
std::forward<RangeEndGen>(range_end_gen), | ||
std::forward<CriticalSection>(critical_section)); | ||
} | ||
} | ||
|
||
} // namespace hpx::ranged_lock::test::util |