feat(linear-static-3d-euler-beam): step 17 - parallel-for-tbb-review-fix
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
@@ -28,43 +29,64 @@ TEST(ParallelFor, ZeroOneManyExecuteExactlyOnce) {
|
||||
const TbbParallelFor tbb;
|
||||
|
||||
for (const ParallelFor& parallelFor : parallelForBackends(serial, tbb)) {
|
||||
bool zeroBodyCalled = false;
|
||||
parallelFor.execute(0U, [&zeroBodyCalled](std::size_t) {
|
||||
zeroBodyCalled = true;
|
||||
std::atomic<std::size_t> zeroVisits{0U};
|
||||
parallelFor.execute(0U, [&zeroVisits](std::size_t) {
|
||||
zeroVisits.fetch_add(1U, std::memory_order_relaxed);
|
||||
});
|
||||
EXPECT_FALSE(zeroBodyCalled);
|
||||
EXPECT_EQ(zeroVisits.load(std::memory_order_relaxed), 0U);
|
||||
|
||||
for (const std::size_t count : {1U, 257U}) {
|
||||
std::vector<int> visits(count, 0);
|
||||
std::vector<std::atomic<std::size_t>> visits(count);
|
||||
for (auto& visit : visits) {
|
||||
visit.store(0U, std::memory_order_relaxed);
|
||||
}
|
||||
parallelFor.execute(count, [&visits](std::size_t index) {
|
||||
++visits[index];
|
||||
visits[index].fetch_add(1U, std::memory_order_relaxed);
|
||||
});
|
||||
EXPECT_EQ(visits, std::vector<int>(count, 1));
|
||||
for (std::size_t index = 0; index < count; ++index) {
|
||||
EXPECT_EQ(visits[index].load(std::memory_order_relaxed), 1U);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ParallelFor, SerialAndTbbProduceStableIndexedOutput) {
|
||||
constexpr std::size_t count = 1024U;
|
||||
std::vector<std::size_t> serialOutput(count, 0U);
|
||||
std::vector<std::size_t> tbbOutput(count, 0U);
|
||||
std::vector<std::atomic<std::size_t>> serialOutput(count);
|
||||
std::vector<std::atomic<std::size_t>> tbbOutput(count);
|
||||
std::vector<std::atomic<std::size_t>> serialVisits(count);
|
||||
std::vector<std::atomic<std::size_t>> tbbVisits(count);
|
||||
for (std::size_t index = 0; index < count; ++index) {
|
||||
serialOutput[index].store(0U, std::memory_order_relaxed);
|
||||
tbbOutput[index].store(0U, std::memory_order_relaxed);
|
||||
serialVisits[index].store(0U, std::memory_order_relaxed);
|
||||
tbbVisits[index].store(0U, std::memory_order_relaxed);
|
||||
}
|
||||
const auto valueForIndex = [](std::size_t index) {
|
||||
return (index + 17U) * (index + 3U);
|
||||
};
|
||||
|
||||
const SerialParallelFor serial;
|
||||
serial.execute(count, [&serialOutput, &valueForIndex](std::size_t index) {
|
||||
serialOutput[index] = valueForIndex(index);
|
||||
serial.execute(count, [&serialOutput, &serialVisits, &valueForIndex](std::size_t index) {
|
||||
serialOutput[index].store(valueForIndex(index), std::memory_order_relaxed);
|
||||
serialVisits[index].fetch_add(1U, std::memory_order_relaxed);
|
||||
});
|
||||
|
||||
const TbbParallelFor tbb;
|
||||
tbb.execute(count, [&tbbOutput, &valueForIndex](std::size_t index) {
|
||||
tbbOutput[index] = valueForIndex(index);
|
||||
tbb.execute(count, [&tbbOutput, &tbbVisits, &valueForIndex](std::size_t index) {
|
||||
tbbOutput[index].store(valueForIndex(index), std::memory_order_relaxed);
|
||||
tbbVisits[index].fetch_add(1U, std::memory_order_relaxed);
|
||||
});
|
||||
|
||||
EXPECT_EQ(tbbOutput, serialOutput);
|
||||
for (std::size_t index = 0; index < count; ++index) {
|
||||
EXPECT_EQ(tbbOutput[index], valueForIndex(index));
|
||||
EXPECT_EQ(serialVisits[index].load(std::memory_order_relaxed), 1U);
|
||||
EXPECT_EQ(tbbVisits[index].load(std::memory_order_relaxed), 1U);
|
||||
EXPECT_EQ(
|
||||
tbbOutput[index].load(std::memory_order_relaxed),
|
||||
serialOutput[index].load(std::memory_order_relaxed));
|
||||
EXPECT_EQ(
|
||||
tbbOutput[index].load(std::memory_order_relaxed),
|
||||
valueForIndex(index));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user