Commit 0814240d by Christian Kern

Merge branch 'development' into embb446_spscqueue_overflow

parents d6c44c56 17341a5c
......@@ -31,109 +31,104 @@ namespace embb {
namespace algorithms {
namespace internal {
template<typename ForwardIterator>
ChunkDescriptor<ForwardIterator>::ChunkDescriptor(ForwardIterator first,
ForwardIterator last) :
first(first), last(last) {
template<typename RAI>
ChunkDescriptor<RAI>::ChunkDescriptor(
RAI first, RAI last) :
first_(first), last_(last) {
}
template<typename ForwardIterator>
ForwardIterator ChunkDescriptor<ForwardIterator>::GetFirst() const {
return first;
template<typename RAI>
RAI ChunkDescriptor<RAI>::GetFirst() const {
return first_;
}
template<typename ForwardIterator>
ForwardIterator ChunkDescriptor<ForwardIterator>::GetLast() const {
return last;
template<typename RAI>
RAI ChunkDescriptor<RAI>::GetLast() const {
return last_;
}
template<typename ForwardIterator>
BlockSizePartitioner<ForwardIterator>::BlockSizePartitioner(
ForwardIterator first, ForwardIterator last, size_t chunkSize) :
first(first), last(last), chunkSize(chunkSize) {
elements_count = static_cast<size_t>(std::distance(first, last));
chunks = elements_count / chunkSize;
if (elements_count % chunkSize != 0)
chunks++;
template<typename RAI>
BlockSizePartitioner<RAI>::BlockSizePartitioner(
RAI first, RAI last, size_t chunkSize) :
first_(first), last_(last), chunk_size_(chunkSize) {
elements_count_ = static_cast<size_t>(std::distance(first_, last_));
chunks_ = elements_count_ / chunk_size_;
if (elements_count_ % chunk_size_ != 0) {
chunks_++;
}
}
template<typename ForwardIterator>
size_t BlockSizePartitioner<ForwardIterator>::Size() {
return chunks;
template<typename RAI>
size_t BlockSizePartitioner<RAI>::Size() {
return chunks_;
}
template<typename ForwardIterator>
const ChunkDescriptor<ForwardIterator>
BlockSizePartitioner<ForwardIterator>::operator[](
size_t const& index) const {
ForwardIterator first_new = first;
std::advance(first_new, index * chunkSize);
ForwardIterator last_new = first_new;
if (index >= chunks - 1) {
last_new = last;
template<typename RAI>
const ChunkDescriptor<RAI>
BlockSizePartitioner<RAI>::operator[](
size_t const & index) const {
typedef typename std::iterator_traits<RAI>::difference_type
difference_type;
RAI first_new(first_);
first_new += static_cast<difference_type>(chunk_size_ * index);
RAI last_new(first_new);
if (index >= chunks_ - 1) {
last_new = last_;
} else {
std::advance(last_new, chunkSize);
last_new += static_cast<difference_type>(chunk_size_);
}
return ChunkDescriptor<ForwardIterator>(first_new, last_new);
return ChunkDescriptor<RAI>(first_new, last_new);
}
template<typename ForwardIterator>
size_t ChunkPartitioner<ForwardIterator>::Size() {
return size;
template<typename RAI>
size_t ChunkPartitioner<RAI>::Size() {
return size_;
}
template<typename ForwardIterator>
ChunkPartitioner<ForwardIterator>::ChunkPartitioner(ForwardIterator first,
ForwardIterator last, size_t amountChunks) :
first(first), last(last) {
template<typename RAI>
ChunkPartitioner<RAI>::ChunkPartitioner(
RAI first, RAI last, size_t amountChunks) :
first_(first), last_(last) {
if (amountChunks > 0) {
size = amountChunks;
size_ = amountChunks;
} else {
// if no concrete chunk size was given, use number of cores...
// if no concrete chunk size was given, use number of cores
embb::tasks::Node& node = embb::tasks::Node::GetInstance();
size = node.GetWorkerThreadCount();
size_ = node.GetWorkerThreadCount();
}
elements_count = static_cast<size_t>(std::distance(first, last));
if (size > elements_count) {
elements_count_ = static_cast<size_t>(std::distance(first_, last_));
if (size_ > elements_count_) {
// if we want to make more chunks than we have elements, correct
// the number of chunks
size = elements_count;
size_ = elements_count_;
}
standard_chunk_size = elements_count / size;
bigger_chunk_count = elements_count % size;
standard_chunk_size_ = elements_count_ / size_;
bigger_chunk_count_ = elements_count_ % size_;
}
template<typename ForwardIterator>
const ChunkDescriptor<ForwardIterator>
ChunkPartitioner<ForwardIterator>::operator[](
template<typename RAI>
const ChunkDescriptor<RAI>
ChunkPartitioner<RAI>::operator[](
size_t const& index) const {
typedef typename std::iterator_traits<ForwardIterator>::difference_type
typedef typename std::iterator_traits<RAI>::difference_type
difference_type;
// Number of element preceding elements in the given chunk
size_t prec_elements_count = 0;
if (index <= bigger_chunk_count) {
prec_elements_count = index * (standard_chunk_size + 1);
if (index <= bigger_chunk_count_) {
prec_elements_count = index * (standard_chunk_size_ + 1);
} else {
prec_elements_count = (standard_chunk_size + 1) * bigger_chunk_count
+ standard_chunk_size * (index - bigger_chunk_count);
prec_elements_count =
(standard_chunk_size_ + 1) * bigger_chunk_count_ +
(standard_chunk_size_ * (index - bigger_chunk_count_));
}
size_t cur_elements_count =
(index < bigger_chunk_count) ?
(standard_chunk_size + 1) : standard_chunk_size;
ForwardIterator first_new = first;
std::advance(first_new, prec_elements_count);
first_new = first + static_cast<difference_type>(prec_elements_count);
ForwardIterator last_new = first_new;
std::advance(last_new, cur_elements_count);
return ChunkDescriptor<ForwardIterator>(first_new, last_new);
size_t cur_elements_count = (index < bigger_chunk_count_)
? (standard_chunk_size_ + 1)
: standard_chunk_size_;
RAI first_new(first_);
first_new += static_cast<difference_type>(prec_elements_count);
RAI last_new(first_new);
last_new += static_cast<difference_type>(cur_elements_count);
return ChunkDescriptor<RAI>(first_new, last_new);
}
} // namespace internal
......
......@@ -38,14 +38,14 @@ namespace internal {
* Describes a single partition of a 1-dimensional
* partitioning, using first and last iterator.
*
* \tparam ForwardIterator Type of the iterator.
* \tparam RAI Type of the iterator.
*/
template<typename ForwardIterator>
template<typename RAI>
class ChunkDescriptor {
private:
ForwardIterator first;
ForwardIterator last;
RAI first_;
RAI last_;
public:
/**
......@@ -54,7 +54,7 @@ class ChunkDescriptor {
* \param first The first iterator.
* \param last The last iterator
*/
ChunkDescriptor(ForwardIterator first, ForwardIterator last);
ChunkDescriptor(RAI first, RAI last);
/**
* Gets the first iterator.
......@@ -63,7 +63,7 @@ class ChunkDescriptor {
*
* \waitfree
*/
ForwardIterator GetFirst() const;
RAI GetFirst() const;
/**
* Gets the last iterator.
......@@ -72,7 +72,7 @@ class ChunkDescriptor {
*
* \waitfree
*/
ForwardIterator GetLast() const;
RAI GetLast() const;
};
/**
......@@ -80,9 +80,9 @@ class ChunkDescriptor {
*
* Describes the interface for accessing a 1-dimensional partitioning.
*
* \tparam ForwardIterator Type of the iterator.
* \tparam RAI Type of the iterator.
*/
template<typename ForwardIterator>
template<typename RAI>
class IPartitioner {
public:
virtual ~IPartitioner() {}
......@@ -106,7 +106,7 @@ class IPartitioner {
*
* \waitfree
*/
virtual const ChunkDescriptor<ForwardIterator> operator[](
virtual const ChunkDescriptor<RAI> operator[](
size_t const& index) const = 0;
};
......@@ -129,16 +129,16 @@ class IPartitioner {
* 2: [6,7,8,9,10]
* 3: [11,12,13]
*
* \tparam ForwardIterator Type of the iterator.
* \tparam RAI Type of the iterator.
*/
template<typename ForwardIterator>
class BlockSizePartitioner : IPartitioner < ForwardIterator > {
template<typename RAI>
class BlockSizePartitioner : IPartitioner < RAI > {
private:
ForwardIterator first;
ForwardIterator last;
size_t chunkSize;
size_t elements_count;
size_t chunks;
RAI first_;
RAI last_;
size_t chunk_size_;
size_t elements_count_;
size_t chunks_;
public:
/**
......@@ -150,7 +150,7 @@ class BlockSizePartitioner : IPartitioner < ForwardIterator > {
* \param chunkSize (Optional) size of the chunk.
*/
BlockSizePartitioner(
ForwardIterator first, ForwardIterator last, size_t chunkSize = 1);
RAI first, RAI last, size_t chunkSize = 1);
/**
* See IPartitioner
......@@ -164,7 +164,7 @@ class BlockSizePartitioner : IPartitioner < ForwardIterator > {
*
* \waitfree
*/
virtual const ChunkDescriptor<ForwardIterator> operator[](
virtual const ChunkDescriptor<RAI> operator[](
size_t const& index) const;
};
......@@ -196,17 +196,17 @@ class BlockSizePartitioner : IPartitioner < ForwardIterator > {
* 4: [10,11]
* 5: [12,13]
*
* \tparam ForwardIterator Type of the iterator.
* \tparam RAI Type of the iterator.
*/
template<typename ForwardIterator>
class ChunkPartitioner : IPartitioner < ForwardIterator > {
template<typename RAI>
class ChunkPartitioner : IPartitioner < RAI > {
private:
size_t size;
size_t elements_count;
ForwardIterator first;
ForwardIterator last;
size_t standard_chunk_size;
size_t bigger_chunk_count;
size_t size_;
size_t elements_count_;
RAI first_;
RAI last_;
size_t standard_chunk_size_;
size_t bigger_chunk_count_;
public:
/**
......@@ -227,7 +227,7 @@ class ChunkPartitioner : IPartitioner < ForwardIterator > {
* \param last The last.
* \param amountChunks (Optional) the amount chunks.
*/
ChunkPartitioner(ForwardIterator first, ForwardIterator last,
ChunkPartitioner(RAI first, RAI last,
size_t amountChunks = 0);
/**
......@@ -235,7 +235,7 @@ class ChunkPartitioner : IPartitioner < ForwardIterator > {
*
* \waitfree
*/
virtual const ChunkDescriptor<ForwardIterator> operator[](
virtual const ChunkDescriptor<RAI> operator[](
size_t const& index) const;
};
......
......@@ -33,9 +33,15 @@
#include <vector>
#include <list>
PartitionerTest::PartitionerTest() {
CreateUnit("algorithms partitioner test").
Add(&PartitionerTest::TestBasic, this);
PartitionerTest::PartitionerTest()
: partitioned_array_size_(16384) {
// Size of array to be partitioned should be power of 2
CreateUnit("TestBasic")
.Add(&PartitionerTest::TestBasic, this);
CreateUnit("TestLargeRange")
.Pre(&PartitionerTest::TestLargeRangePre, this)
.Add(&PartitionerTest::TestLargeRange, this)
.Post(&PartitionerTest::TestLargeRangePost, this);
}
void PartitionerTest::TestBasic() {
......@@ -70,3 +76,62 @@ void PartitionerTest::TestBasic() {
PT_EXPECT_EQ_MSG(partitioner2.Size(), size_t(3), "Check count of partitions");
}
void PartitionerTest::TestLargeRangePre() {
partitioned_array_ = new int[partitioned_array_size_];
for (size_t i = 0; i < partitioned_array_size_; ++i) {
partitioned_array_[i] = static_cast<int>(i);
}
}
void PartitionerTest::TestLargeRangePost() {
delete[] partitioned_array_;
}
void PartitionerTest::TestLargeRange() {
// Test chunk partitioner with increasing number of chunks:
for (size_t num_chunks = 2;
num_chunks < partitioned_array_size_;
num_chunks *= 2) {
embb::algorithms::internal::ChunkPartitioner<int *>
chunk_partitioner(
partitioned_array_,
partitioned_array_ + partitioned_array_size_,
num_chunks);
int last_value_prev = -1;
PT_EXPECT_EQ(num_chunks, chunk_partitioner.Size());
// Iterate over chunks in partition:
for (size_t chunk = 0; chunk < chunk_partitioner.Size(); ++chunk) {
int first_value = *(chunk_partitioner[chunk].GetFirst());
int last_value = *(chunk_partitioner[chunk].GetLast() - 1);
PT_EXPECT_LT(first_value, last_value);
// Test seams between chunks: chunk[i].last + 1 == chunk[i+1].first
PT_EXPECT_EQ((last_value_prev + 1), first_value);
last_value_prev = last_value;
}
}
// Test block size partitioner with increasing chunk size:
for (size_t block_size = 1;
block_size < partitioned_array_size_;
block_size *= 2) {
embb::algorithms::internal::BlockSizePartitioner<int *>
chunk_partitioner(
partitioned_array_,
partitioned_array_ + partitioned_array_size_,
block_size);
int last_value_prev = -1;
// Iterate over chunks in partition:
for (size_t chunk = 0; chunk < chunk_partitioner.Size(); ++chunk) {
int first_value = *(chunk_partitioner[chunk].GetFirst());
int last_value = *(chunk_partitioner[chunk].GetLast() - 1);
if (block_size == 1) {
PT_EXPECT_EQ(first_value, last_value);
} else {
PT_EXPECT_LT(first_value, last_value);
}
// Test seams between chunks: chunk[i].last + 1 == chunk[i+1].first
PT_EXPECT_EQ((last_value_prev + 1), first_value);
last_value_prev = last_value;
}
}
}
......@@ -35,6 +35,13 @@ class PartitionerTest : public partest::TestCase {
private:
void TestBasic();
void TestLargeRangePre();
void TestLargeRangePost();
void TestLargeRange();
int * partitioned_array_;
size_t partitioned_array_size_;
};
#endif // ALGORITHMS_CPP_TEST_PARTITIONER_TEST_H_
......@@ -41,7 +41,8 @@ extern "C" {
/*
* For each extension, follow this template
* /* cl_VEN_extname extension */
* // cl_VEN_extname extension
*/
/* #define cl_VEN_extname 1
* ... define new types, if any
* ... define new tokens, if any
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment