Commit 32cd1a1a authored by BRAMAS Berenger's avatar BRAMAS Berenger

Update the quicksort to have a nice sequential and threaded version which...

Update the quicksort to have a nice sequential and threaded version which accept <= operator or lambda function
parent 88a4ebf4
......@@ -18,9 +18,9 @@ protected:
MortonIndex outIndex;
MortonIndex insideIndex;
int outPosition;
operator long long() const{
return static_cast<long long>(outIndex);
// To sort
bool operator <=(const OutOfBlockInteraction& other) const{
return outIndex <= other.outIndex;
}
};
......@@ -184,7 +184,7 @@ protected:
// Manage outofblock interaction
FQuickSort<OutOfBlockInteraction, long long, int>::QsSequential(outsideInteractions.data(),int(outsideInteractions.size()));
FQuickSort<OutOfBlockInteraction, int>::QsSequential(outsideInteractions.data(),int(outsideInteractions.size()));
typename std::list<CellContainerClass*>::iterator iterLeftCells = tree->cellsBegin(idxLevel);
int currentOutInteraction = 0;
......@@ -357,7 +357,7 @@ protected:
// Manage outofblock interaction
FQuickSort<OutOfBlockInteraction, long long, int>::QsSequential(outsideInteractions.data(),int(outsideInteractions.size()));
FQuickSort<OutOfBlockInteraction, int>::QsSequential(outsideInteractions.data(),int(outsideInteractions.size()));
typename std::list<ParticleGroupClass*>::iterator iterLeftParticles = tree->leavesBegin();
int currentOutInteraction = 0;
......
......@@ -203,10 +203,6 @@ public:
struct ParticleSortingStruct{
int originalIndex;
MortonIndex mindex;
operator MortonIndex(){
return mindex;
}
};
// Convert position to morton index
const int nbParticles = inParticlesContainer->getNbParticles();
......@@ -226,7 +222,9 @@ public:
// Sort if needed
if(particlesAreSorted == false){
FQuickSort<ParticleSortingStruct, MortonIndex, int>::QsOmp(particlesToSort, nbParticles);
FQuickSort<ParticleSortingStruct, int>::QsOmp(particlesToSort, nbParticles, [&](const ParticleSortingStruct& v1, const ParticleSortingStruct& v2){
return v1.mindex <= v2.mindex;
});
}
// Convert to block
......
......@@ -153,7 +153,9 @@ public:
FAssert(np == flag, "Bitonic sort work only with power of 2 for now.")
}
FQuickSort<SortType,CompareType,IndexType>::QsOmp(array, size);
FQuickSort<SortType,IndexType>::QsOmp(array, size, [&](const SortType& v1, const SortType& v2){
return CompareType(v1) <= CompareType(v2);
});
const int logNp = int(log2(np));
for(int bitIdx = 1 ; bitIdx <= logNp ; ++bitIdx){
......@@ -175,7 +177,9 @@ public:
}
// A merge sort is possible since the array is composed
// by two part already sorted, but we want to do this in space
FQuickSort<SortType,CompareType,IndexType>::QsOmp(array, size);
FQuickSort<SortType,IndexType>::QsOmp(array, size, [&](const SortType& v1, const SortType& v2){
return CompareType(v1) <= CompareType(v2);
});
}
}
}
......
......@@ -23,6 +23,7 @@
#include <cstring>
#include <vector> // For parallel without task
#include <utility> // For move
#include <functional> // To have std::function
#include "FGlobal.hpp"
#include "FMemUtils.hpp"
......@@ -38,9 +39,33 @@
* Introduction to parallel computing (Grama Gupta Karypis Kumar)
*/
template <class SortType, class CompareType, class IndexType>
template <class SortType, class IndexType = size_t>
class FQuickSort {
protected:
#if _OPENMP < 200805 || defined(__ICC) || defined(__INTEL_COMPILER)
#define FQS_TASKS_ARE_DISABLED
class TaskInterval{
IndexType left;
IndexType right;
int deep;
public:
TaskInterval(const IndexType inLeft, const IndexType inRight, const int inDeep)
: left(inLeft), right(inRight), deep(inDeep){
}
IndexType getLeft() const{
return left;
}
IndexType getRight() const{
return right;
}
int getDeep() const{
return deep;
}
};
#endif
/** swap to value */
template <class NumType>
static inline void Swap(NumType& value, NumType& other){
......@@ -49,22 +74,24 @@ protected:
other = std::move(temp);
}
typedef bool (*infOrEqualPtr)(const SortType&, const SortType&);
////////////////////////////////////////////////////////////
// Quick sort
////////////////////////////////////////////////////////////
/* Use in the sequential qs */
static IndexType QsPartition(SortType array[], IndexType left, IndexType right){
static IndexType QsPartition(SortType array[], IndexType left, IndexType right, const infOrEqualPtr infOrEqual){
Swap(array[right],array[((right - left ) / 2) + left]);
IndexType idx = left;
while( idx < right && CompareType(array[idx]) <= CompareType(array[right])){
while( idx < right && infOrEqual(array[idx],array[right])){
idx += 1;
}
left = idx;
for( ; idx < right ; ++idx){
if( CompareType(array[idx]) <= CompareType(array[right]) ){
if( infOrEqual(array[idx],array[right]) ){
Swap(array[idx],array[left]);
left += 1;
}
......@@ -77,59 +104,45 @@ protected:
/* The sequential qs */
static void QsSequentialStep(SortType array[], const IndexType left, const IndexType right){
static void QsSequentialStep(SortType array[], const IndexType left, const IndexType right, const infOrEqualPtr infOrEqual){
if(left < right){
const IndexType part = QsPartition(array, left, right);
QsSequentialStep(array,part + 1,right);
QsSequentialStep(array,left,part - 1);
const IndexType part = QsPartition(array, left, right, infOrEqual);
QsSequentialStep(array,part + 1,right, infOrEqual);
QsSequentialStep(array,left,part - 1, infOrEqual);
}
}
/** A task dispatcher */
static void QsOmpTask(SortType array[], const IndexType left, const IndexType right, const int deep){
static void QsOmpTask(SortType array[], const IndexType left, const IndexType right, const int deep, const infOrEqualPtr infOrEqual){
if(left < right){
const IndexType part = QsPartition(array, left, right);
const IndexType part = QsPartition(array, left, right, infOrEqual);
if( deep ){
#pragma omp task
QsOmpTask(array,part + 1,right, deep - 1);
#pragma omp task
QsOmpTask(array,left,part - 1, deep - 1);
QsOmpTask(array,part + 1,right, deep - 1, infOrEqual);
// #pragma omp task // not needed
QsOmpTask(array,left,part - 1, deep - 1, infOrEqual);
}
else {
QsSequentialStep(array,part + 1,right);
QsSequentialStep(array,left,part - 1);
QsSequentialStep(array,part + 1,right, infOrEqual);
QsSequentialStep(array,left,part - 1, infOrEqual);
}
}
}
public:
/* a sequential qs */
static void QsSequential(SortType array[], const IndexType size){
QsSequentialStep(array,0,size-1);
static void QsSequential(SortType array[], const IndexType size, const infOrEqualPtr infOrEqual){
QsSequentialStep(array, 0, size-1, infOrEqual);
}
#if _OPENMP < 200805 || defined(__ICC) || defined(__INTEL_COMPILER)
class TaskInterval{
IndexType left;
IndexType right;
int deep;
public:
TaskInterval(const IndexType inLeft, const IndexType inRight, const int inDeep)
: left(inLeft), right(inRight), deep(inDeep){
}
IndexType getLeft() const{
return left;
}
IndexType getRight() const{
return right;
}
int getDeep() const{
return deep;
}
};
static void QsSequential(SortType array[], const IndexType size){
QsSequential(array, size, [&](const SortType& v1, const SortType& v2){
return v1 <= v2;
});
}
static void QsOmp(SortType elements[], const int nbElements){
#ifdef FQS_TASKS_ARE_DISABLED
static void QsOmp(SortType elements[], const int nbElements, const infOrEqualPtr infOrEqual){
const int nbTasksRequiere = (omp_get_max_threads() * 5);
int deep = 0;
while( (1 << deep) < nbTasksRequiere ) deep += 1;
......@@ -155,7 +168,7 @@ public:
if(ts.getDeep() == 0){
// No release the mutex and run in seq
omp_unset_lock(&mutexShareVariable);
QsSequentialStep(elements , ts.getLeft(), ts.getRight());
QsSequentialStep(elements , ts.getLeft(), ts.getRight(), infOrEqual);
}
else{
// Yes so inform other and release the mutex
......@@ -163,7 +176,7 @@ public:
omp_unset_lock(&mutexShareVariable);
// Partition
const IndexType part = QsPartition(elements, ts.getLeft(), ts.getRight());
const IndexType part = QsPartition(elements, ts.getLeft(), ts.getRight(), infOrEqual);
// Push the new task in the vector
omp_set_lock(&mutexShareVariable);
......@@ -191,7 +204,7 @@ public:
}
#else
/** The openmp quick sort */
static void QsOmp(SortType array[], const IndexType size){
static void QsOmp(SortType array[], const IndexType size, const infOrEqualPtr infOrEqual){
const int nbTasksRequiere = (omp_get_max_threads() * 5);
int deep = 0;
while( (1 << deep) < nbTasksRequiere ) deep += 1;
......@@ -200,11 +213,17 @@ public:
{
#pragma omp single nowait
{
QsOmpTask(array, 0, size - 1 , deep);
QsOmpTask(array, 0, size - 1 , deep, infOrEqual);
}
}
}
#endif
static void QsOmp(SortType array[], const IndexType size){
QsOmp(array, size, [&](const SortType& v1, const SortType& v2){
return v1 <= v2;
});
}
};
#endif // FQUICKSORT_HPP
......@@ -23,8 +23,8 @@
#include <memory>
#include <utility>
template <class SortType, class CompareType, class IndexType>
class FQuickSortMpi : public FQuickSort< SortType, CompareType, IndexType> {
template <class SortType, class CompareType, class IndexType = size_t>
class FQuickSortMpi : public FQuickSort< SortType, IndexType> {
// We need a structure see the algorithm detail to know more
struct Partition{
IndexType lowerPart;
......@@ -392,7 +392,9 @@ public:
////FLOG( FLog::Controller << currentComm.processId() << "] Sequential sort\n"; )
// Finish by a local sort
FQuickSort< SortType, CompareType, IndexType>::QsOmp(workingArray, currentSize);
FQuickSort< SortType, IndexType>::QsOmp(workingArray, currentSize, [&](const SortType& v1, const SortType& v2){
return CompareType(v1) <= CompareType(v2);
});
(*outputSize) = currentSize;
(*outputArray) = workingArray;
}
......
......@@ -47,7 +47,7 @@ class TestQuickSort : public FUTester<TestQuickSort> {
array[idx] = rand();
}
FQuickSort<long long, long long, long>::QsOmp(array, Size);
FQuickSort<long long, long>::QsOmp(array, Size);
uassert(IsSorted(array,Size));
}
......@@ -64,7 +64,7 @@ class TestQuickSort : public FUTester<TestQuickSort> {
array[idx] = rand();
}
FQuickSort<long long, long long, long>::QsOmp(array, Size);
FQuickSort<long long, long>::QsOmp(array, Size);
uassert(IsSorted(array,Size));
delete [] array;
......@@ -78,7 +78,7 @@ class TestQuickSort : public FUTester<TestQuickSort> {
array[idx] = Size-idx;
}
FQuickSort<long long, long long, long>::QsOmp(array, Size);
FQuickSort<long long, long>::QsOmp(array, Size);
uassert(IsSorted(array,Size));
delete [] array;
......@@ -92,7 +92,7 @@ class TestQuickSort : public FUTester<TestQuickSort> {
array[idx] = idx;
}
FQuickSort<long long, long long, long>::QsOmp(array, Size);
FQuickSort<long long, long>::QsOmp(array, Size);
uassert(IsSorted(array,Size));
delete [] array;
......
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 to comment