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